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#include "progress_meter_data.c" 110 111#include "sys/msgbuf.h" 112 113/* 114 * Generic Console (Front-End) 115 * --------------------------- 116 */ 117 118struct vc_info vinfo; 119 120void noroot_icon_test(void); 121 122 123extern int disableConsoleOutput; 124static boolean_t gc_enabled = FALSE; 125static boolean_t gc_initialized = FALSE; 126static boolean_t vm_initialized = FALSE; 127 128static struct { 129 void (*initialize)(struct vc_info * info); 130 void (*enable)(boolean_t enable); 131 void (*paint_char)(unsigned int xx, unsigned int yy, unsigned char ch, 132 int attrs, unsigned char ch_previous, 133 int attrs_previous); 134 void (*clear_screen)(unsigned int xx, unsigned int yy, unsigned int top, 135 unsigned int bottom, int which); 136 void (*scroll_down)(int num, unsigned int top, unsigned int bottom); 137 void (*scroll_up)(int num, unsigned int top, unsigned int bottom); 138 void (*hide_cursor)(unsigned int xx, unsigned int yy); 139 void (*show_cursor)(unsigned int xx, unsigned int yy); 140 void (*update_color)(int color, boolean_t fore); 141} gc_ops; 142 143static unsigned char *gc_buffer_attributes; 144static unsigned char *gc_buffer_characters; 145static unsigned char *gc_buffer_colorcodes; 146static unsigned char *gc_buffer_tab_stops; 147static uint32_t gc_buffer_columns; 148static uint32_t gc_buffer_rows; 149static uint32_t gc_buffer_size; 150 151#if defined(__i386__) || defined(__x86_64__) 152decl_simple_lock_data(static, vcputc_lock); 153 154#define VCPUTC_LOCK_INIT() \ 155MACRO_BEGIN \ 156 simple_lock_init(&vcputc_lock, 0); \ 157MACRO_END 158 159#define VCPUTC_LOCK_LOCK() \ 160MACRO_BEGIN \ 161 boolean_t istate = ml_get_interrupts_enabled(); \ 162 while (!simple_lock_try(&vcputc_lock)) \ 163 { \ 164 if (!istate) \ 165 handle_pending_TLB_flushes(); \ 166 cpu_pause(); \ 167 } \ 168MACRO_END 169 170#define VCPUTC_LOCK_UNLOCK() \ 171MACRO_BEGIN \ 172 simple_unlock(&vcputc_lock); \ 173MACRO_END 174#else 175static hw_lock_data_t vcputc_lock; 176 177#define VCPUTC_LOCK_INIT() \ 178MACRO_BEGIN \ 179 hw_lock_init(&vcputc_lock); \ 180MACRO_END 181 182#define VCPUTC_LOCK_LOCK() \ 183MACRO_BEGIN \ 184 if (!hw_lock_to(&vcputc_lock, ~0U))\ 185 { \ 186 panic("VCPUTC_LOCK_LOCK"); \ 187 } \ 188MACRO_END 189 190#define VCPUTC_LOCK_UNLOCK() \ 191MACRO_BEGIN \ 192 hw_lock_unlock(&vcputc_lock); \ 193MACRO_END 194#endif 195 196/* 197# Attribute codes: 198# 00=none 01=bold 04=underscore 05=blink 07=reverse 08=concealed 199# Text color codes: 200# 30=black 31=red 32=green 33=yellow 34=blue 35=magenta 36=cyan 37=white 201# Background color codes: 202# 40=black 41=red 42=green 43=yellow 44=blue 45=magenta 46=cyan 47=white 203*/ 204 205#define ATTR_NONE 0 206#define ATTR_BOLD 1 207#define ATTR_UNDER 2 208#define ATTR_REVERSE 4 209 210#define COLOR_BACKGROUND 0 211#define COLOR_FOREGROUND 7 212 213#define COLOR_CODE_GET(code, fore) (((code) & ((fore) ? 0xF0 : 0x0F)) >> ((fore) ? 4 : 0)) 214#define COLOR_CODE_SET(code, color, fore) (((code) & ((fore) ? 0x0F : 0xF0)) | ((color) << ((fore) ? 4 : 0))) 215 216static unsigned char gc_color_code; 217 218/* VT100 state: */ 219#define MAXPARS 16 220static unsigned int gc_x, gc_y, gc_savex, gc_savey; 221static unsigned int gc_par[MAXPARS], gc_numpars, gc_hanging_cursor, gc_attr, gc_saveattr; 222 223/* VT100 scroll region */ 224static unsigned int gc_scrreg_top, gc_scrreg_bottom; 225 226enum vt100state_e { 227 ESnormal, /* Nothing yet */ 228 ESesc, /* Got ESC */ 229 ESsquare, /* Got ESC [ */ 230 ESgetpars, /* About to get or getting the parameters */ 231 ESgotpars, /* Finished getting the parameters */ 232 ESfunckey, /* Function key */ 233 EShash, /* DEC-specific stuff (screen align, etc.) */ 234 ESsetG0, /* Specify the G0 character set */ 235 ESsetG1, /* Specify the G1 character set */ 236 ESask, 237 EScharsize, 238 ESignore /* Ignore this sequence */ 239} gc_vt100state = ESnormal; 240 241 242enum 243{ 244 /* secs */ 245 kProgressAcquireDelay = 0, 246 kProgressReacquireDelay = 5, 247}; 248 249static int8_t vc_rotate_matr[4][2][2] = { 250 { { 1, 0 }, 251 { 0, 1 } }, 252 { { 0, 1 }, 253 { -1, 0 } }, 254 { { -1, 0 }, 255 { 0, -1 } }, 256 { { 0, -1 }, 257 { 1, 0 } } 258}; 259 260static int gc_wrap_mode = 1, gc_relative_origin = 0; 261static int gc_charset_select = 0, gc_save_charset_s = 0; 262static int gc_charset[2] = { 0, 0 }; 263static int gc_charset_save[2] = { 0, 0 }; 264 265static void gc_clear_line(unsigned int xx, unsigned int yy, int which); 266static void gc_clear_screen(unsigned int xx, unsigned int yy, int top, 267 unsigned int bottom, int which); 268static void gc_enable(boolean_t enable); 269static void gc_hide_cursor(unsigned int xx, unsigned int yy); 270static void gc_initialize(struct vc_info * info); 271static boolean_t gc_is_tab_stop(unsigned int column); 272static void gc_paint_char(unsigned int xx, unsigned int yy, unsigned char ch, 273 int attrs); 274static void gc_putchar(char ch); 275static void gc_putc_askcmd(unsigned char ch); 276static void gc_putc_charsetcmd(int charset, unsigned char ch); 277static void gc_putc_charsizecmd(unsigned char ch); 278static void gc_putc_esc(unsigned char ch); 279static void gc_putc_getpars(unsigned char ch); 280static void gc_putc_gotpars(unsigned char ch); 281static void gc_putc_normal(unsigned char ch); 282static void gc_putc_square(unsigned char ch); 283static void gc_reset_screen(void); 284static void gc_reset_tabs(void); 285static void gc_reset_vt100(void); 286static void gc_scroll_down(int num, unsigned int top, unsigned int bottom); 287static void gc_scroll_up(int num, unsigned int top, unsigned int bottom); 288static void gc_set_tab_stop(unsigned int column, boolean_t enabled); 289static void gc_show_cursor(unsigned int xx, unsigned int yy); 290static void gc_update_color(int color, boolean_t fore); 291 292static void 293gc_clear_line(unsigned int xx, unsigned int yy, int which) 294{ 295 unsigned int start, end, i; 296 297 /* 298 * This routine runs extremely slowly. I don't think it's 299 * used all that often, except for To end of line. I'll go 300 * back and speed this up when I speed up the whole vc 301 * module. --LK 302 */ 303 304 switch (which) { 305 case 0: /* To end of line */ 306 start = xx; 307 end = vinfo.v_columns-1; 308 break; 309 case 1: /* To start of line */ 310 start = 0; 311 end = xx; 312 break; 313 case 2: /* Whole line */ 314 start = 0; 315 end = vinfo.v_columns-1; 316 break; 317 default: 318 return; 319 } 320 321 for (i = start; i <= end; i++) { 322 gc_paint_char(i, yy, ' ', ATTR_NONE); 323 } 324} 325 326static void 327gc_clear_screen(unsigned int xx, unsigned int yy, int top, unsigned int bottom, 328 int which) 329{ 330 if (!gc_buffer_size) return; 331 332 if ( xx < gc_buffer_columns && yy < gc_buffer_rows && bottom <= gc_buffer_rows ) 333 { 334 uint32_t start, end; 335 336 switch (which) { 337 case 0: /* To end of screen */ 338 start = (yy * gc_buffer_columns) + xx; 339 end = (bottom * gc_buffer_columns) - 1; 340 break; 341 case 1: /* To start of screen */ 342 start = (top * gc_buffer_columns); 343 end = (yy * gc_buffer_columns) + xx; 344 break; 345 case 2: /* Whole screen */ 346 start = (top * gc_buffer_columns); 347 end = (bottom * gc_buffer_columns) - 1; 348 break; 349 default: 350 start = 0; 351 end = 0; 352 break; 353 } 354 355 memset(gc_buffer_attributes + start, ATTR_NONE, end - start + 1); 356 memset(gc_buffer_characters + start, ' ', end - start + 1); 357 memset(gc_buffer_colorcodes + start, gc_color_code, end - start + 1); 358 } 359 360 gc_ops.clear_screen(xx, yy, top, bottom, which); 361} 362 363static void 364gc_enable( boolean_t enable ) 365{ 366 unsigned char *buffer_attributes = NULL; 367 unsigned char *buffer_characters = NULL; 368 unsigned char *buffer_colorcodes = NULL; 369 unsigned char *buffer_tab_stops = NULL; 370 uint32_t buffer_columns = 0; 371 uint32_t buffer_rows = 0; 372 uint32_t buffer_size = 0; 373 spl_t s; 374 375 if ( enable == FALSE ) 376 { 377 // only disable console output if it goes to the graphics console 378 if ( console_is_serial() == FALSE ) 379 disableConsoleOutput = TRUE; 380 gc_enabled = FALSE; 381 gc_ops.enable(FALSE); 382 } 383 384 s = splhigh( ); 385 VCPUTC_LOCK_LOCK( ); 386 387 if ( gc_buffer_size ) 388 { 389 buffer_attributes = gc_buffer_attributes; 390 buffer_characters = gc_buffer_characters; 391 buffer_colorcodes = gc_buffer_colorcodes; 392 buffer_tab_stops = gc_buffer_tab_stops; 393 buffer_columns = gc_buffer_columns; 394 buffer_rows = gc_buffer_rows; 395 buffer_size = gc_buffer_size; 396 397 gc_buffer_attributes = NULL; 398 gc_buffer_characters = NULL; 399 gc_buffer_colorcodes = NULL; 400 gc_buffer_tab_stops = NULL; 401 gc_buffer_columns = 0; 402 gc_buffer_rows = 0; 403 gc_buffer_size = 0; 404 405 VCPUTC_LOCK_UNLOCK( ); 406 splx( s ); 407 408 kfree( buffer_attributes, buffer_size ); 409 kfree( buffer_characters, buffer_size ); 410 kfree( buffer_colorcodes, buffer_size ); 411 kfree( buffer_tab_stops, buffer_columns ); 412 } 413 else 414 { 415 VCPUTC_LOCK_UNLOCK( ); 416 splx( s ); 417 } 418 419 if ( enable ) 420 { 421 if ( vm_initialized ) 422 { 423 buffer_columns = vinfo.v_columns; 424 buffer_rows = vinfo.v_rows; 425 buffer_size = buffer_columns * buffer_rows; 426 427 if ( buffer_size ) 428 { 429 buffer_attributes = (unsigned char *) kalloc( buffer_size ); 430 buffer_characters = (unsigned char *) kalloc( buffer_size ); 431 buffer_colorcodes = (unsigned char *) kalloc( buffer_size ); 432 buffer_tab_stops = (unsigned char *) kalloc( buffer_columns ); 433 434 if ( buffer_attributes == NULL || 435 buffer_characters == NULL || 436 buffer_colorcodes == NULL || 437 buffer_tab_stops == NULL ) 438 { 439 if ( buffer_attributes ) kfree( buffer_attributes, buffer_size ); 440 if ( buffer_characters ) kfree( buffer_characters, buffer_size ); 441 if ( buffer_colorcodes ) kfree( buffer_colorcodes, buffer_size ); 442 if ( buffer_tab_stops ) kfree( buffer_tab_stops, buffer_columns ); 443 444 buffer_columns = 0; 445 buffer_rows = 0; 446 buffer_size = 0; 447 } 448 else 449 { 450 memset( buffer_attributes, ATTR_NONE, buffer_size ); 451 memset( buffer_characters, ' ', buffer_size ); 452 memset( buffer_colorcodes, COLOR_CODE_SET( 0, COLOR_FOREGROUND, TRUE ), buffer_size ); 453 memset( buffer_tab_stops, 0, buffer_columns ); 454 } 455 } 456 } 457 458 s = splhigh( ); 459 VCPUTC_LOCK_LOCK( ); 460 461 gc_buffer_attributes = buffer_attributes; 462 gc_buffer_characters = buffer_characters; 463 gc_buffer_colorcodes = buffer_colorcodes; 464 gc_buffer_tab_stops = buffer_tab_stops; 465 gc_buffer_columns = buffer_columns; 466 gc_buffer_rows = buffer_rows; 467 gc_buffer_size = buffer_size; 468 469 gc_reset_screen(); 470 471 VCPUTC_LOCK_UNLOCK( ); 472 splx( s ); 473 474 gc_ops.clear_screen(gc_x, gc_y, 0, vinfo.v_rows, 2); 475 gc_ops.show_cursor(gc_x, gc_y); 476 477 gc_ops.enable(TRUE); 478 gc_enabled = TRUE; 479 disableConsoleOutput = FALSE; 480 } 481} 482 483static void 484gc_hide_cursor(unsigned int xx, unsigned int yy) 485{ 486 if ( xx < gc_buffer_columns && yy < gc_buffer_rows ) 487 { 488 uint32_t index = (yy * gc_buffer_columns) + xx; 489 unsigned char attribute = gc_buffer_attributes[index]; 490 unsigned char character = gc_buffer_characters[index]; 491 unsigned char colorcode = gc_buffer_colorcodes[index]; 492 unsigned char colorcodesave = gc_color_code; 493 494 gc_update_color(COLOR_CODE_GET(colorcode, TRUE ), TRUE ); 495 gc_update_color(COLOR_CODE_GET(colorcode, FALSE), FALSE); 496 497 gc_ops.paint_char(xx, yy, character, attribute, 0, 0); 498 499 gc_update_color(COLOR_CODE_GET(colorcodesave, TRUE ), TRUE ); 500 gc_update_color(COLOR_CODE_GET(colorcodesave, FALSE), FALSE); 501 } 502 else 503 { 504 gc_ops.hide_cursor(xx, yy); 505 } 506} 507 508static void 509gc_initialize(struct vc_info * info) 510{ 511 if ( gc_initialized == FALSE ) 512 { 513 /* Init our lock */ 514 VCPUTC_LOCK_INIT(); 515 516 gc_initialized = TRUE; 517 } 518 519 gc_ops.initialize(info); 520 521 gc_reset_vt100(); 522 gc_x = gc_y = 0; 523} 524 525static void 526gc_paint_char(unsigned int xx, unsigned int yy, unsigned char ch, int attrs) 527{ 528 if ( xx < gc_buffer_columns && yy < gc_buffer_rows ) 529 { 530 uint32_t index = (yy * gc_buffer_columns) + xx; 531 532 gc_buffer_attributes[index] = attrs; 533 gc_buffer_characters[index] = ch; 534 gc_buffer_colorcodes[index] = gc_color_code; 535 } 536 537 gc_ops.paint_char(xx, yy, ch, attrs, 0, 0); 538} 539 540static void 541gc_putchar(char ch) 542{ 543 if (!ch) { 544 return; /* ignore null characters */ 545 } 546 switch (gc_vt100state) { 547 default:gc_vt100state = ESnormal; /* FALLTHROUGH */ 548 case ESnormal: 549 gc_putc_normal(ch); 550 break; 551 case ESesc: 552 gc_putc_esc(ch); 553 break; 554 case ESsquare: 555 gc_putc_square(ch); 556 break; 557 case ESgetpars: 558 gc_putc_getpars(ch); 559 break; 560 case ESgotpars: 561 gc_putc_gotpars(ch); 562 break; 563 case ESask: 564 gc_putc_askcmd(ch); 565 break; 566 case EScharsize: 567 gc_putc_charsizecmd(ch); 568 break; 569 case ESsetG0: 570 gc_putc_charsetcmd(0, ch); 571 break; 572 case ESsetG1: 573 gc_putc_charsetcmd(1, ch); 574 break; 575 } 576 577 if (gc_x >= vinfo.v_columns) { 578 if (0 == vinfo.v_columns) 579 gc_x = 0; 580 else 581 gc_x = vinfo.v_columns - 1; 582 } 583 if (gc_y >= vinfo.v_rows) { 584 if (0 == vinfo.v_rows) 585 gc_y = 0; 586 else 587 gc_y = vinfo.v_rows - 1; 588 } 589} 590 591static void 592gc_putc_askcmd(unsigned char ch) 593{ 594 if (ch >= '0' && ch <= '9') { 595 gc_par[gc_numpars] = (10*gc_par[gc_numpars]) + (ch-'0'); 596 return; 597 } 598 gc_vt100state = ESnormal; 599 600 switch (gc_par[0]) { 601 case 6: 602 gc_relative_origin = ch == 'h'; 603 break; 604 case 7: /* wrap around mode h=1, l=0*/ 605 gc_wrap_mode = ch == 'h'; 606 break; 607 default: 608 break; 609 } 610 611} 612 613static void 614gc_putc_charsetcmd(int charset, unsigned char ch) 615{ 616 gc_vt100state = ESnormal; 617 618 switch (ch) { 619 case 'A' : 620 case 'B' : 621 default: 622 gc_charset[charset] = 0; 623 break; 624 case '0' : /* Graphic characters */ 625 case '2' : 626 gc_charset[charset] = 0x21; 627 break; 628 } 629 630} 631 632static void 633gc_putc_charsizecmd(unsigned char ch) 634{ 635 gc_vt100state = ESnormal; 636 637 switch (ch) { 638 case '3' : 639 case '4' : 640 case '5' : 641 case '6' : 642 break; 643 case '8' : /* fill 'E's */ 644 { 645 unsigned int xx, yy; 646 for (yy = 0; yy < vinfo.v_rows; yy++) 647 for (xx = 0; xx < vinfo.v_columns; xx++) 648 gc_paint_char(xx, yy, 'E', ATTR_NONE); 649 } 650 break; 651 } 652 653} 654 655static void 656gc_putc_esc(unsigned char ch) 657{ 658 gc_vt100state = ESnormal; 659 660 switch (ch) { 661 case '[': 662 gc_vt100state = ESsquare; 663 break; 664 case 'c': /* Reset terminal */ 665 gc_reset_vt100(); 666 gc_clear_screen(gc_x, gc_y, 0, vinfo.v_rows, 2); 667 gc_x = gc_y = 0; 668 break; 669 case 'D': /* Line feed */ 670 case 'E': 671 if (gc_y >= gc_scrreg_bottom -1) { 672 gc_scroll_up(1, gc_scrreg_top, gc_scrreg_bottom); 673 gc_y = gc_scrreg_bottom - 1; 674 } else { 675 gc_y++; 676 } 677 if (ch == 'E') gc_x = 0; 678 break; 679 case 'H': /* Set tab stop */ 680 gc_set_tab_stop(gc_x, TRUE); 681 break; 682 case 'M': /* Cursor up */ 683 if (gc_y <= gc_scrreg_top) { 684 gc_scroll_down(1, gc_scrreg_top, gc_scrreg_bottom); 685 gc_y = gc_scrreg_top; 686 } else { 687 gc_y--; 688 } 689 break; 690 case '>': 691 gc_reset_vt100(); 692 break; 693 case '7': /* Save cursor */ 694 gc_savex = gc_x; 695 gc_savey = gc_y; 696 gc_saveattr = gc_attr; 697 gc_save_charset_s = gc_charset_select; 698 gc_charset_save[0] = gc_charset[0]; 699 gc_charset_save[1] = gc_charset[1]; 700 break; 701 case '8': /* Restore cursor */ 702 gc_x = gc_savex; 703 gc_y = gc_savey; 704 gc_attr = gc_saveattr; 705 gc_charset_select = gc_save_charset_s; 706 gc_charset[0] = gc_charset_save[0]; 707 gc_charset[1] = gc_charset_save[1]; 708 break; 709 case 'Z': /* return terminal ID */ 710 break; 711 case '#': /* change characters height */ 712 gc_vt100state = EScharsize; 713 break; 714 case '(': 715 gc_vt100state = ESsetG0; 716 break; 717 case ')': /* character set sequence */ 718 gc_vt100state = ESsetG1; 719 break; 720 case '=': 721 break; 722 default: 723 /* Rest not supported */ 724 break; 725 } 726 727} 728 729static void 730gc_putc_getpars(unsigned char ch) 731{ 732 if (ch == '?') { 733 gc_vt100state = ESask; 734 return; 735 } 736 if (ch == '[') { 737 gc_vt100state = ESnormal; 738 /* Not supported */ 739 return; 740 } 741 if (ch == ';' && gc_numpars < MAXPARS - 1) { 742 gc_numpars++; 743 } else 744 if (ch >= '0' && ch <= '9') { 745 gc_par[gc_numpars] *= 10; 746 gc_par[gc_numpars] += ch - '0'; 747 } else { 748 gc_numpars++; 749 gc_vt100state = ESgotpars; 750 gc_putc_gotpars(ch); 751 } 752} 753 754static void 755gc_putc_gotpars(unsigned char ch) 756{ 757 unsigned int i; 758 759 if (ch < ' ') { 760 /* special case for vttest for handling cursor 761 movement in escape sequences */ 762 gc_putc_normal(ch); 763 gc_vt100state = ESgotpars; 764 return; 765 } 766 gc_vt100state = ESnormal; 767 switch (ch) { 768 case 'A': /* Up */ 769 gc_y -= gc_par[0] ? gc_par[0] : 1; 770 if (gc_y < gc_scrreg_top) 771 gc_y = gc_scrreg_top; 772 break; 773 case 'B': /* Down */ 774 gc_y += gc_par[0] ? gc_par[0] : 1; 775 if (gc_y >= gc_scrreg_bottom) 776 gc_y = gc_scrreg_bottom - 1; 777 break; 778 case 'C': /* Right */ 779 gc_x += gc_par[0] ? gc_par[0] : 1; 780 if (gc_x >= vinfo.v_columns) 781 gc_x = vinfo.v_columns-1; 782 break; 783 case 'D': /* Left */ 784 if (gc_par[0] > gc_x) 785 gc_x = 0; 786 else if (gc_par[0]) 787 gc_x -= gc_par[0]; 788 else if (gc_x) 789 --gc_x; 790 break; 791 case 'H': /* Set cursor position */ 792 case 'f': 793 gc_x = gc_par[1] ? gc_par[1] - 1 : 0; 794 gc_y = gc_par[0] ? gc_par[0] - 1 : 0; 795 if (gc_relative_origin) 796 gc_y += gc_scrreg_top; 797 gc_hanging_cursor = 0; 798 break; 799 case 'X': /* clear p1 characters */ 800 if (gc_numpars) { 801 for (i = gc_x; i < gc_x + gc_par[0]; i++) 802 gc_paint_char(i, gc_y, ' ', ATTR_NONE); 803 } 804 break; 805 case 'J': /* Clear part of screen */ 806 gc_clear_screen(gc_x, gc_y, 0, vinfo.v_rows, gc_par[0]); 807 break; 808 case 'K': /* Clear part of line */ 809 gc_clear_line(gc_x, gc_y, gc_par[0]); 810 break; 811 case 'g': /* tab stops */ 812 switch (gc_par[0]) { 813 case 1: 814 case 2: /* reset tab stops */ 815 /* gc_reset_tabs(); */ 816 break; 817 case 3: /* Clear every tabs */ 818 { 819 for (i = 0; i <= vinfo.v_columns; i++) 820 gc_set_tab_stop(i, FALSE); 821 } 822 break; 823 case 0: 824 gc_set_tab_stop(gc_x, FALSE); 825 break; 826 } 827 break; 828 case 'm': /* Set attribute */ 829 for (i = 0; i < gc_numpars; i++) { 830 switch (gc_par[i]) { 831 case 0: 832 gc_attr = ATTR_NONE; 833 gc_update_color(COLOR_BACKGROUND, FALSE); 834 gc_update_color(COLOR_FOREGROUND, TRUE ); 835 break; 836 case 1: 837 gc_attr |= ATTR_BOLD; 838 break; 839 case 4: 840 gc_attr |= ATTR_UNDER; 841 break; 842 case 7: 843 gc_attr |= ATTR_REVERSE; 844 break; 845 case 22: 846 gc_attr &= ~ATTR_BOLD; 847 break; 848 case 24: 849 gc_attr &= ~ATTR_UNDER; 850 break; 851 case 27: 852 gc_attr &= ~ATTR_REVERSE; 853 break; 854 case 5: 855 case 25: /* blink/no blink */ 856 break; 857 default: 858 if (gc_par[i] >= 30 && gc_par[i] <= 37) 859 gc_update_color(gc_par[i] - 30, TRUE); 860 if (gc_par[i] >= 40 && gc_par[i] <= 47) 861 gc_update_color(gc_par[i] - 40, FALSE); 862 break; 863 } 864 } 865 break; 866 case 'r': /* Set scroll region */ 867 gc_x = gc_y = 0; 868 /* ensure top < bottom, and both within limits */ 869 if ((gc_numpars > 0) && (gc_par[0] < vinfo.v_rows)) { 870 gc_scrreg_top = gc_par[0] ? gc_par[0] - 1 : 0; 871 } else { 872 gc_scrreg_top = 0; 873 } 874 if ((gc_numpars > 1) && (gc_par[1] <= vinfo.v_rows) && (gc_par[1] > gc_par[0])) { 875 gc_scrreg_bottom = gc_par[1]; 876 if (gc_scrreg_bottom > vinfo.v_rows) 877 gc_scrreg_bottom = vinfo.v_rows; 878 } else { 879 gc_scrreg_bottom = vinfo.v_rows; 880 } 881 if (gc_relative_origin) 882 gc_y = gc_scrreg_top; 883 break; 884 } 885 886} 887 888static void 889gc_putc_normal(unsigned char ch) 890{ 891 switch (ch) { 892 case '\a': /* Beep */ 893 break; 894 case 127: /* Delete */ 895 case '\b': /* Backspace */ 896 if (gc_hanging_cursor) { 897 gc_hanging_cursor = 0; 898 } else 899 if (gc_x > 0) { 900 gc_x--; 901 } 902 break; 903 case '\t': /* Tab */ 904 if (gc_buffer_tab_stops) while (gc_x < vinfo.v_columns && !gc_is_tab_stop(++gc_x)); 905 906 if (gc_x >= vinfo.v_columns) 907 gc_x = vinfo.v_columns-1; 908 break; 909 case 0x0b: 910 case 0x0c: 911 case '\n': /* Line feed */ 912 if (gc_y >= gc_scrreg_bottom -1 ) { 913 gc_scroll_up(1, gc_scrreg_top, gc_scrreg_bottom); 914 gc_y = gc_scrreg_bottom - 1; 915 } else { 916 gc_y++; 917 } 918 break; 919 case '\r': /* Carriage return */ 920 gc_x = 0; 921 gc_hanging_cursor = 0; 922 break; 923 case 0x0e: /* Select G1 charset (Control-N) */ 924 gc_charset_select = 1; 925 break; 926 case 0x0f: /* Select G0 charset (Control-O) */ 927 gc_charset_select = 0; 928 break; 929 case 0x18 : /* CAN : cancel */ 930 case 0x1A : /* like cancel */ 931 /* well, i do nothing here, may be later */ 932 break; 933 case '\033': /* Escape */ 934 gc_vt100state = ESesc; 935 gc_hanging_cursor = 0; 936 break; 937 default: 938 if (ch >= ' ') { 939 if (gc_hanging_cursor) { 940 gc_x = 0; 941 if (gc_y >= gc_scrreg_bottom -1 ) { 942 gc_scroll_up(1, gc_scrreg_top, gc_scrreg_bottom); 943 gc_y = gc_scrreg_bottom - 1; 944 } else { 945 gc_y++; 946 } 947 gc_hanging_cursor = 0; 948 } 949 gc_paint_char(gc_x, gc_y, (ch >= 0x60 && ch <= 0x7f) ? ch + gc_charset[gc_charset_select] 950 : ch, gc_attr); 951 if (gc_x == vinfo.v_columns - 1) { 952 gc_hanging_cursor = gc_wrap_mode; 953 } else { 954 gc_x++; 955 } 956 } 957 break; 958 } 959 960} 961 962static void 963gc_putc_square(unsigned char ch) 964{ 965 int i; 966 967 for (i = 0; i < MAXPARS; i++) { 968 gc_par[i] = 0; 969 } 970 971 gc_numpars = 0; 972 gc_vt100state = ESgetpars; 973 974 gc_putc_getpars(ch); 975 976} 977 978static void 979gc_reset_screen(void) 980{ 981 gc_reset_vt100(); 982 gc_x = gc_y = 0; 983} 984 985static void 986gc_reset_tabs(void) 987{ 988 unsigned int i; 989 990 if (!gc_buffer_tab_stops) return; 991 992 for (i = 0; i < vinfo.v_columns; i++) { 993 gc_buffer_tab_stops[i] = ((i % 8) == 0); 994 } 995 996} 997 998static void 999gc_set_tab_stop(unsigned int column, boolean_t enabled) 1000{ 1001 if (gc_buffer_tab_stops && (column < vinfo.v_columns)) { 1002 gc_buffer_tab_stops[column] = enabled; 1003 } 1004} 1005 1006static boolean_t gc_is_tab_stop(unsigned int column) 1007{ 1008 if (gc_buffer_tab_stops == NULL) 1009 return ((column % 8) == 0); 1010 if (column < vinfo.v_columns) 1011 return gc_buffer_tab_stops[column]; 1012 else 1013 return FALSE; 1014} 1015 1016static void 1017gc_reset_vt100(void) 1018{ 1019 gc_reset_tabs(); 1020 gc_scrreg_top = 0; 1021 gc_scrreg_bottom = vinfo.v_rows; 1022 gc_attr = ATTR_NONE; 1023 gc_charset[0] = gc_charset[1] = 0; 1024 gc_charset_select = 0; 1025 gc_wrap_mode = 1; 1026 gc_relative_origin = 0; 1027 gc_update_color(COLOR_BACKGROUND, FALSE); 1028 gc_update_color(COLOR_FOREGROUND, TRUE); 1029} 1030 1031static void 1032gc_scroll_down(int num, unsigned int top, unsigned int bottom) 1033{ 1034 if (!gc_buffer_size) return; 1035 1036 if ( bottom <= gc_buffer_rows ) 1037 { 1038 unsigned char colorcodesave = gc_color_code; 1039 uint32_t column, row; 1040 uint32_t index, jump; 1041 1042 jump = num * gc_buffer_columns; 1043 1044 for ( row = bottom - 1 ; row >= top + num ; row-- ) 1045 { 1046 index = row * gc_buffer_columns; 1047 1048 for ( column = 0 ; column < gc_buffer_columns ; index++, column++ ) 1049 { 1050 if ( gc_buffer_attributes[index] != gc_buffer_attributes[index - jump] || 1051 gc_buffer_characters[index] != gc_buffer_characters[index - jump] || 1052 gc_buffer_colorcodes[index] != gc_buffer_colorcodes[index - jump] ) 1053 { 1054 if ( gc_color_code != gc_buffer_colorcodes[index - jump] ) 1055 { 1056 gc_update_color(COLOR_CODE_GET(gc_buffer_colorcodes[index - jump], TRUE ), TRUE ); 1057 gc_update_color(COLOR_CODE_GET(gc_buffer_colorcodes[index - jump], FALSE), FALSE); 1058 } 1059 1060 if ( gc_buffer_colorcodes[index] != gc_buffer_colorcodes[index - jump] ) 1061 { 1062 gc_ops.paint_char( /* xx */ column, 1063 /* yy */ row, 1064 /* ch */ gc_buffer_characters[index - jump], 1065 /* attrs */ gc_buffer_attributes[index - jump], 1066 /* ch_previous */ 0, 1067 /* attrs_previous */ 0 ); 1068 } 1069 else 1070 { 1071 gc_ops.paint_char( /* xx */ column, 1072 /* yy */ row, 1073 /* ch */ gc_buffer_characters[index - jump], 1074 /* attrs */ gc_buffer_attributes[index - jump], 1075 /* ch_previous */ gc_buffer_characters[index], 1076 /* attrs_previous */ gc_buffer_attributes[index] ); 1077 } 1078 1079 gc_buffer_attributes[index] = gc_buffer_attributes[index - jump]; 1080 gc_buffer_characters[index] = gc_buffer_characters[index - jump]; 1081 gc_buffer_colorcodes[index] = gc_buffer_colorcodes[index - jump]; 1082 } 1083 } 1084 } 1085 1086 if ( colorcodesave != gc_color_code ) 1087 { 1088 gc_update_color(COLOR_CODE_GET(colorcodesave, TRUE ), TRUE ); 1089 gc_update_color(COLOR_CODE_GET(colorcodesave, FALSE), FALSE); 1090 } 1091 1092 /* Now set the freed up lines to the background colour */ 1093 1094 for ( row = top ; row < top + num ; row++ ) 1095 { 1096 index = row * gc_buffer_columns; 1097 1098 for ( column = 0 ; column < gc_buffer_columns ; index++, column++ ) 1099 { 1100 if ( gc_buffer_attributes[index] != ATTR_NONE || 1101 gc_buffer_characters[index] != ' ' || 1102 gc_buffer_colorcodes[index] != gc_color_code ) 1103 { 1104 if ( gc_buffer_colorcodes[index] != gc_color_code ) 1105 { 1106 gc_ops.paint_char( /* xx */ column, 1107 /* yy */ row, 1108 /* ch */ ' ', 1109 /* attrs */ ATTR_NONE, 1110 /* ch_previous */ 0, 1111 /* attrs_previous */ 0 ); 1112 } 1113 else 1114 { 1115 gc_ops.paint_char( /* xx */ column, 1116 /* yy */ row, 1117 /* ch */ ' ', 1118 /* attrs */ ATTR_NONE, 1119 /* ch_previous */ gc_buffer_characters[index], 1120 /* attrs_previous */ gc_buffer_attributes[index] ); 1121 } 1122 1123 gc_buffer_attributes[index] = ATTR_NONE; 1124 gc_buffer_characters[index] = ' '; 1125 gc_buffer_colorcodes[index] = gc_color_code; 1126 } 1127 } 1128 } 1129 } 1130 else 1131 { 1132 gc_ops.scroll_down(num, top, bottom); 1133 1134 /* Now set the freed up lines to the background colour */ 1135 1136 gc_clear_screen(vinfo.v_columns - 1, top + num - 1, top, bottom, 1); 1137 } 1138} 1139 1140static void 1141gc_scroll_up(int num, unsigned int top, unsigned int bottom) 1142{ 1143 if (!gc_buffer_size) return; 1144 1145 if ( bottom <= gc_buffer_rows ) 1146 { 1147 unsigned char colorcodesave = gc_color_code; 1148 uint32_t column, row; 1149 uint32_t index, jump; 1150 1151 jump = num * gc_buffer_columns; 1152 1153 for ( row = top ; row < bottom - num ; row++ ) 1154 { 1155 index = row * gc_buffer_columns; 1156 1157 for ( column = 0 ; column < gc_buffer_columns ; index++, column++ ) 1158 { 1159 if ( gc_buffer_attributes[index] != gc_buffer_attributes[index + jump] || 1160 gc_buffer_characters[index] != gc_buffer_characters[index + jump] || 1161 gc_buffer_colorcodes[index] != gc_buffer_colorcodes[index + jump] ) 1162 { 1163 if ( gc_color_code != gc_buffer_colorcodes[index + jump] ) 1164 { 1165 gc_update_color(COLOR_CODE_GET(gc_buffer_colorcodes[index + jump], TRUE ), TRUE ); 1166 gc_update_color(COLOR_CODE_GET(gc_buffer_colorcodes[index + jump], FALSE), FALSE); 1167 } 1168 1169 if ( gc_buffer_colorcodes[index] != gc_buffer_colorcodes[index + jump] ) 1170 { 1171 gc_ops.paint_char( /* xx */ column, 1172 /* yy */ row, 1173 /* ch */ gc_buffer_characters[index + jump], 1174 /* attrs */ gc_buffer_attributes[index + jump], 1175 /* ch_previous */ 0, 1176 /* attrs_previous */ 0 ); 1177 } 1178 else 1179 { 1180 gc_ops.paint_char( /* xx */ column, 1181 /* yy */ row, 1182 /* ch */ gc_buffer_characters[index + jump], 1183 /* attrs */ gc_buffer_attributes[index + jump], 1184 /* ch_previous */ gc_buffer_characters[index], 1185 /* attrs_previous */ gc_buffer_attributes[index] ); 1186 } 1187 1188 gc_buffer_attributes[index] = gc_buffer_attributes[index + jump]; 1189 gc_buffer_characters[index] = gc_buffer_characters[index + jump]; 1190 gc_buffer_colorcodes[index] = gc_buffer_colorcodes[index + jump]; 1191 } 1192 } 1193 } 1194 1195 if ( colorcodesave != gc_color_code ) 1196 { 1197 gc_update_color(COLOR_CODE_GET(colorcodesave, TRUE ), TRUE ); 1198 gc_update_color(COLOR_CODE_GET(colorcodesave, FALSE), FALSE); 1199 } 1200 1201 /* Now set the freed up lines to the background colour */ 1202 1203 for ( row = bottom - num ; row < bottom ; row++ ) 1204 { 1205 index = row * gc_buffer_columns; 1206 1207 for ( column = 0 ; column < gc_buffer_columns ; index++, column++ ) 1208 { 1209 if ( gc_buffer_attributes[index] != ATTR_NONE || 1210 gc_buffer_characters[index] != ' ' || 1211 gc_buffer_colorcodes[index] != gc_color_code ) 1212 { 1213 if ( gc_buffer_colorcodes[index] != gc_color_code ) 1214 { 1215 gc_ops.paint_char( /* xx */ column, 1216 /* yy */ row, 1217 /* ch */ ' ', 1218 /* attrs */ ATTR_NONE, 1219 /* ch_previous */ 0, 1220 /* attrs_previous */ 0 ); 1221 } 1222 else 1223 { 1224 gc_ops.paint_char( /* xx */ column, 1225 /* yy */ row, 1226 /* ch */ ' ', 1227 /* attrs */ ATTR_NONE, 1228 /* ch_previous */ gc_buffer_characters[index], 1229 /* attrs_previous */ gc_buffer_attributes[index] ); 1230 } 1231 1232 gc_buffer_attributes[index] = ATTR_NONE; 1233 gc_buffer_characters[index] = ' '; 1234 gc_buffer_colorcodes[index] = gc_color_code; 1235 } 1236 } 1237 } 1238 } 1239 else 1240 { 1241 gc_ops.scroll_up(num, top, bottom); 1242 1243 /* Now set the freed up lines to the background colour */ 1244 1245 gc_clear_screen(0, bottom - num, top, bottom, 0); 1246 } 1247} 1248 1249static void 1250gc_show_cursor(unsigned int xx, unsigned int yy) 1251{ 1252 if ( xx < gc_buffer_columns && yy < gc_buffer_rows ) 1253 { 1254 uint32_t index = (yy * gc_buffer_columns) + xx; 1255 unsigned char attribute = gc_buffer_attributes[index]; 1256 unsigned char character = gc_buffer_characters[index]; 1257 unsigned char colorcode = gc_buffer_colorcodes[index]; 1258 unsigned char colorcodesave = gc_color_code; 1259 1260 gc_update_color(COLOR_CODE_GET(colorcode, FALSE), TRUE ); 1261 gc_update_color(COLOR_CODE_GET(colorcode, TRUE ), FALSE); 1262 1263 gc_ops.paint_char(xx, yy, character, attribute, 0, 0); 1264 1265 gc_update_color(COLOR_CODE_GET(colorcodesave, TRUE ), TRUE ); 1266 gc_update_color(COLOR_CODE_GET(colorcodesave, FALSE), FALSE); 1267 } 1268 else 1269 { 1270 gc_ops.show_cursor(xx, yy); 1271 } 1272} 1273 1274static void 1275gc_update_color(int color, boolean_t fore) 1276{ 1277 assert(gc_ops.update_color); 1278 1279 gc_color_code = COLOR_CODE_SET(gc_color_code, color, fore); 1280 gc_ops.update_color(color, fore); 1281} 1282 1283void 1284vcputc(__unused int l, __unused int u, int c) 1285{ 1286 if ( gc_initialized && ( gc_enabled || debug_mode ) ) 1287 { 1288 spl_t s; 1289 1290 s = splhigh(); 1291#if defined(__i386__) || defined(__x86_64__) 1292 x86_filter_TLB_coherency_interrupts(TRUE); 1293#endif 1294 VCPUTC_LOCK_LOCK(); 1295 if ( gc_enabled || debug_mode ) 1296 { 1297 gc_hide_cursor(gc_x, gc_y); 1298 gc_putchar(c); 1299 gc_show_cursor(gc_x, gc_y); 1300 } 1301 VCPUTC_LOCK_UNLOCK(); 1302#if defined(__i386__) || defined(__x86_64__) 1303 x86_filter_TLB_coherency_interrupts(FALSE); 1304#endif 1305 splx(s); 1306 } 1307} 1308 1309/* 1310 * Video Console (Back-End) 1311 * ------------------------ 1312 */ 1313 1314/* 1315 * For the color support (Michel Pollet) 1316 */ 1317static unsigned char vc_color_index_table[33] = 1318 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1319 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 2 }; 1320 1321static uint32_t vc_colors[8][4] = { 1322 { 0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000 }, /* black */ 1323 { 0x23232323, 0x7C007C00, 0x00FF0000, 0x3FF00000 }, /* red */ 1324 { 0xb9b9b9b9, 0x03e003e0, 0x0000FF00, 0x000FFC00 }, /* green */ 1325 { 0x05050505, 0x7FE07FE0, 0x00FFFF00, 0x3FFFFC00 }, /* yellow */ 1326 { 0xd2d2d2d2, 0x001f001f, 0x000000FF, 0x000003FF }, /* blue */ 1327// { 0x80808080, 0x31933193, 0x00666699, 0x00000000 }, /* blue */ 1328 { 0x18181818, 0x7C1F7C1F, 0x00FF00FF, 0x3FF003FF }, /* magenta */ 1329 { 0xb4b4b4b4, 0x03FF03FF, 0x0000FFFF, 0x000FFFFF }, /* cyan */ 1330 { 0x00000000, 0x7FFF7FFF, 0x00FFFFFF, 0x3FFFFFFF } /* white */ 1331}; 1332 1333static uint32_t vc_color_fore = 0; 1334static uint32_t vc_color_back = 0; 1335 1336/* 1337 * New Rendering code from Michel Pollet 1338 */ 1339 1340/* Rendered Font Buffer */ 1341static unsigned char *vc_rendered_font = NULL; 1342 1343/* Rendered Font Size */ 1344static uint32_t vc_rendered_font_size = 0; 1345 1346/* Size of a character in the table (bytes) */ 1347static int vc_rendered_char_size = 0; 1348 1349#define REN_MAX_DEPTH 32 1350static unsigned char vc_rendered_char[ISO_CHAR_HEIGHT * ((REN_MAX_DEPTH / 8) * ISO_CHAR_WIDTH)]; 1351 1352static void 1353internal_set_progressmeter(int new_value); 1354static void 1355internal_enable_progressmeter(int new_value); 1356 1357enum 1358{ 1359 kProgressMeterOff = FALSE, 1360 kProgressMeterUser = TRUE, 1361 kProgressMeterKernel = 3, 1362}; 1363enum 1364{ 1365 kProgressMeterMax = 1024, 1366 kProgressMeterEnd = 512, 1367}; 1368 1369 1370static boolean_t vc_progress_white = 1371#ifdef CONFIG_VC_PROGRESS_WHITE 1372 TRUE; 1373#else /* !CONFIG_VC_PROGRESS_WHITE */ 1374 FALSE; 1375#endif /* !CONFIG_VC_PROGRESS_WHITE */ 1376 1377static int vc_acquire_delay = kProgressAcquireDelay; 1378 1379static void 1380vc_clear_screen(unsigned int xx, unsigned int yy, unsigned int scrreg_top, 1381 unsigned int scrreg_bottom, int which) 1382{ 1383 uint32_t *p, *endp, *row; 1384 int linelongs, col; 1385 int rowline, rowlongs; 1386 1387 if(!vinfo.v_depth) 1388 return; 1389 1390 linelongs = vinfo.v_rowbytes * (ISO_CHAR_HEIGHT >> 2); 1391 rowline = vinfo.v_rowscanbytes >> 2; 1392 rowlongs = vinfo.v_rowbytes >> 2; 1393 1394 p = (uint32_t*) vinfo.v_baseaddr; 1395 endp = (uint32_t*) vinfo.v_baseaddr; 1396 1397 switch (which) { 1398 case 0: /* To end of screen */ 1399 gc_clear_line(xx, yy, 0); 1400 if (yy < scrreg_bottom - 1) { 1401 p += (yy + 1) * linelongs; 1402 endp += scrreg_bottom * linelongs; 1403 } 1404 break; 1405 case 1: /* To start of screen */ 1406 gc_clear_line(xx, yy, 1); 1407 if (yy > scrreg_top) { 1408 p += scrreg_top * linelongs; 1409 endp += yy * linelongs; 1410 } 1411 break; 1412 case 2: /* Whole screen */ 1413 p += scrreg_top * linelongs; 1414 if (scrreg_bottom == vinfo.v_rows) { 1415 endp += rowlongs * vinfo.v_height; 1416 } else { 1417 endp += scrreg_bottom * linelongs; 1418 } 1419 break; 1420 } 1421 1422 for (row = p ; row < endp ; row += rowlongs) { 1423 for (col = 0; col < rowline; col++) 1424 *(row+col) = vc_color_back; 1425 } 1426} 1427 1428static void 1429vc_render_char(unsigned char ch, unsigned char *renderptr, short newdepth) 1430{ 1431 union { 1432 unsigned char *charptr; 1433 unsigned short *shortptr; 1434 uint32_t *longptr; 1435 } current; /* current place in rendered font, multiple types. */ 1436 unsigned char *theChar; /* current char in iso_font */ 1437 int line; 1438 1439 current.charptr = renderptr; 1440 theChar = iso_font + (ch * ISO_CHAR_HEIGHT); 1441 1442 for (line = 0; line < ISO_CHAR_HEIGHT; line++) { 1443 unsigned char mask = 1; 1444 do { 1445 switch (newdepth) { 1446 case 8: 1447 *current.charptr++ = (*theChar & mask) ? 0xFF : 0; 1448 break; 1449 case 16: 1450 *current.shortptr++ = (*theChar & mask) ? 0xFFFF : 0; 1451 break; 1452 1453 case 30: 1454 case 32: 1455 *current.longptr++ = (*theChar & mask) ? 0xFFFFFFFF : 0; 1456 break; 1457 } 1458 mask <<= 1; 1459 } while (mask); /* while the single bit drops to the right */ 1460 theChar++; 1461 } 1462} 1463 1464static void 1465vc_paint_char_8(unsigned int xx, unsigned int yy, unsigned char ch, int attrs, 1466 __unused unsigned char ch_previous, __unused int attrs_previous) 1467{ 1468 uint32_t *theChar; 1469 uint32_t *where; 1470 int i; 1471 1472 if (vc_rendered_font) { 1473 theChar = (uint32_t*)(vc_rendered_font + (ch * vc_rendered_char_size)); 1474 } else { 1475 vc_render_char(ch, vc_rendered_char, 8); 1476 theChar = (uint32_t*)(vc_rendered_char); 1477 } 1478 where = (uint32_t*)(vinfo.v_baseaddr + 1479 (yy * ISO_CHAR_HEIGHT * vinfo.v_rowbytes) + 1480 (xx * ISO_CHAR_WIDTH)); 1481 1482 if (!attrs) for (i = 0; i < ISO_CHAR_HEIGHT; i++) { /* No attr? FLY !*/ 1483 uint32_t *store = where; 1484 int x; 1485 for (x = 0; x < 2; x++) { 1486 uint32_t val = *theChar++; 1487 val = (vc_color_back & ~val) | (vc_color_fore & val); 1488 *store++ = val; 1489 } 1490 1491 where = (uint32_t*)(((unsigned char*)where)+vinfo.v_rowbytes); 1492 } else for (i = 0; i < ISO_CHAR_HEIGHT; i++) { /* a little slower */ 1493 uint32_t *store = where, lastpixel = 0; 1494 int x; 1495 for (x = 0 ; x < 2; x++) { 1496 uint32_t val = *theChar++, save = val; 1497 if (attrs & ATTR_BOLD) { /* bold support */ 1498 if (lastpixel && !(save & 0xFF000000)) 1499 val |= 0xff000000; 1500 if ((save & 0xFFFF0000) == 0xFF000000) 1501 val |= 0x00FF0000; 1502 if ((save & 0x00FFFF00) == 0x00FF0000) 1503 val |= 0x0000FF00; 1504 if ((save & 0x0000FFFF) == 0x0000FF00) 1505 val |= 0x000000FF; 1506 } 1507 if (attrs & ATTR_REVERSE) val = ~val; 1508 if (attrs & ATTR_UNDER && i == ISO_CHAR_HEIGHT-1) val = ~val; 1509 1510 val = (vc_color_back & ~val) | (vc_color_fore & val); 1511 *store++ = val; 1512 lastpixel = save & 0xff; 1513 } 1514 1515 where = (uint32_t*)(((unsigned char*)where)+vinfo.v_rowbytes); 1516 } 1517 1518} 1519 1520static void 1521vc_paint_char_16(unsigned int xx, unsigned int yy, unsigned char ch, int attrs, 1522 __unused unsigned char ch_previous, 1523 __unused int attrs_previous) 1524{ 1525 uint32_t *theChar; 1526 uint32_t *where; 1527 int i; 1528 1529 if (vc_rendered_font) { 1530 theChar = (uint32_t*)(vc_rendered_font + (ch * vc_rendered_char_size)); 1531 } else { 1532 vc_render_char(ch, vc_rendered_char, 16); 1533 theChar = (uint32_t*)(vc_rendered_char); 1534 } 1535 where = (uint32_t*)(vinfo.v_baseaddr + 1536 (yy * ISO_CHAR_HEIGHT * vinfo.v_rowbytes) + 1537 (xx * ISO_CHAR_WIDTH * 2)); 1538 1539 if (!attrs) for (i = 0; i < ISO_CHAR_HEIGHT; i++) { /* No attrs ? FLY ! */ 1540 uint32_t *store = where; 1541 int x; 1542 for (x = 0; x < 4; x++) { 1543 uint32_t val = *theChar++; 1544 val = (vc_color_back & ~val) | (vc_color_fore & val); 1545 *store++ = val; 1546 } 1547 1548 where = (uint32_t*)(((unsigned char*)where)+vinfo.v_rowbytes); 1549 } else for (i = 0; i < ISO_CHAR_HEIGHT; i++) { /* a little bit slower */ 1550 uint32_t *store = where, lastpixel = 0; 1551 int x; 1552 for (x = 0 ; x < 4; x++) { 1553 uint32_t val = *theChar++, save = val; 1554 if (attrs & ATTR_BOLD) { /* bold support */ 1555 if (save == 0xFFFF0000) val |= 0xFFFF; 1556 else if (lastpixel && !(save & 0xFFFF0000)) 1557 val |= 0xFFFF0000; 1558 } 1559 if (attrs & ATTR_REVERSE) val = ~val; 1560 if (attrs & ATTR_UNDER && i == ISO_CHAR_HEIGHT-1) val = ~val; 1561 1562 val = (vc_color_back & ~val) | (vc_color_fore & val); 1563 1564 *store++ = val; 1565 lastpixel = save & 0x7fff; 1566 } 1567 1568 where = (uint32_t*)(((unsigned char*)where)+vinfo.v_rowbytes); 1569 } 1570 1571} 1572 1573static void 1574vc_paint_char_32(unsigned int xx, unsigned int yy, unsigned char ch, int attrs, 1575 unsigned char ch_previous, int attrs_previous) 1576{ 1577 uint32_t *theChar; 1578 uint32_t *theCharPrevious; 1579 uint32_t *where; 1580 int i; 1581 1582 if (vc_rendered_font) { 1583 theChar = (uint32_t*)(vc_rendered_font + (ch * vc_rendered_char_size)); 1584 theCharPrevious = (uint32_t*)(vc_rendered_font + (ch_previous * vc_rendered_char_size)); 1585 } else { 1586 vc_render_char(ch, vc_rendered_char, 32); 1587 theChar = (uint32_t*)(vc_rendered_char); 1588 theCharPrevious = NULL; 1589 } 1590 if (!ch_previous) { 1591 theCharPrevious = NULL; 1592 } 1593 if (attrs_previous) { 1594 theCharPrevious = NULL; 1595 } 1596 where = (uint32_t*)(vinfo.v_baseaddr + 1597 (yy * ISO_CHAR_HEIGHT * vinfo.v_rowbytes) + 1598 (xx * ISO_CHAR_WIDTH * 4)); 1599 1600 if (!attrs) for (i = 0; i < ISO_CHAR_HEIGHT; i++) { /* No attrs ? FLY ! */ 1601 uint32_t *store = where; 1602 int x; 1603 for (x = 0; x < 8; x++) { 1604 uint32_t val = *theChar++; 1605 if (theCharPrevious == NULL || val != *theCharPrevious++ ) { 1606 val = (vc_color_back & ~val) | (vc_color_fore & val); 1607 *store++ = val; 1608 } else { 1609 store++; 1610 } 1611 } 1612 1613 where = (uint32_t *)(((unsigned char*)where)+vinfo.v_rowbytes); 1614 } else for (i = 0; i < ISO_CHAR_HEIGHT; i++) { /* a little slower */ 1615 uint32_t *store = where, lastpixel = 0; 1616 int x; 1617 for (x = 0 ; x < 8; x++) { 1618 uint32_t val = *theChar++, save = val; 1619 if (attrs & ATTR_BOLD) { /* bold support */ 1620 if (lastpixel && !save) 1621 val = 0xFFFFFFFF; 1622 } 1623 if (attrs & ATTR_REVERSE) val = ~val; 1624 if (attrs & ATTR_UNDER && i == ISO_CHAR_HEIGHT-1) val = ~val; 1625 1626 val = (vc_color_back & ~val) | (vc_color_fore & val); 1627 *store++ = val; 1628 lastpixel = save; 1629 } 1630 1631 where = (uint32_t*)(((unsigned char*)where)+vinfo.v_rowbytes); 1632 } 1633 1634} 1635 1636static void 1637vc_paint_char(unsigned int xx, unsigned int yy, unsigned char ch, int attrs, 1638 unsigned char ch_previous, int attrs_previous) 1639{ 1640 if(!vinfo.v_depth) 1641 return; 1642 1643 switch(vinfo.v_depth) { 1644 case 8: 1645 vc_paint_char_8(xx, yy, ch, attrs, ch_previous, attrs_previous); 1646 break; 1647 case 16: 1648 vc_paint_char_16(xx, yy, ch, attrs, ch_previous, 1649 attrs_previous); 1650 break; 1651 case 30: 1652 case 32: 1653 vc_paint_char_32(xx, yy, ch, attrs, ch_previous, 1654 attrs_previous); 1655 break; 1656 } 1657} 1658 1659static void 1660vc_render_font(short newdepth) 1661{ 1662 static short olddepth = 0; 1663 1664 int charindex; /* index in ISO font */ 1665 unsigned char *rendered_font; 1666 unsigned int rendered_font_size; 1667 int rendered_char_size; 1668 spl_t s; 1669 1670 if (vm_initialized == FALSE) { 1671 return; /* nothing to do */ 1672 } 1673 if (olddepth == newdepth && vc_rendered_font) { 1674 return; /* nothing to do */ 1675 } 1676 1677 s = splhigh(); 1678 VCPUTC_LOCK_LOCK(); 1679 1680 rendered_font = vc_rendered_font; 1681 rendered_font_size = vc_rendered_font_size; 1682 rendered_char_size = vc_rendered_char_size; 1683 1684 vc_rendered_font = NULL; 1685 vc_rendered_font_size = 0; 1686 vc_rendered_char_size = 0; 1687 1688 VCPUTC_LOCK_UNLOCK(); 1689 splx(s); 1690 1691 if (rendered_font) { 1692 kfree(rendered_font, rendered_font_size); 1693 rendered_font = NULL; 1694 } 1695 1696 if (newdepth) { 1697 rendered_char_size = ISO_CHAR_HEIGHT * (((newdepth + 7) / 8) * ISO_CHAR_WIDTH); 1698 rendered_font_size = (ISO_CHAR_MAX-ISO_CHAR_MIN+1) * rendered_char_size; 1699 rendered_font = (unsigned char *) kalloc(rendered_font_size); 1700 } 1701 1702 if (rendered_font == NULL) { 1703 return; 1704 } 1705 1706 for (charindex = ISO_CHAR_MIN; charindex <= ISO_CHAR_MAX; charindex++) { 1707 vc_render_char(charindex, rendered_font + (charindex * rendered_char_size), newdepth); 1708 } 1709 1710 olddepth = newdepth; 1711 1712 s = splhigh(); 1713 VCPUTC_LOCK_LOCK(); 1714 1715 vc_rendered_font = rendered_font; 1716 vc_rendered_font_size = rendered_font_size; 1717 vc_rendered_char_size = rendered_char_size; 1718 1719 VCPUTC_LOCK_UNLOCK(); 1720 splx(s); 1721} 1722 1723static void 1724vc_enable(boolean_t enable) 1725{ 1726 vc_render_font(enable ? vinfo.v_depth : 0); 1727} 1728 1729static void 1730vc_reverse_cursor(unsigned int xx, unsigned int yy) 1731{ 1732 uint32_t *where; 1733 int line, col; 1734 1735 if(!vinfo.v_depth) 1736 return; 1737 1738 where = (uint32_t*)(vinfo.v_baseaddr + 1739 (yy * ISO_CHAR_HEIGHT * vinfo.v_rowbytes) + 1740 (xx /** ISO_CHAR_WIDTH*/ * vinfo.v_depth)); 1741 for (line = 0; line < ISO_CHAR_HEIGHT; line++) { 1742 switch (vinfo.v_depth) { 1743 case 8: 1744 where[0] = ~where[0]; 1745 where[1] = ~where[1]; 1746 break; 1747 case 16: 1748 for (col = 0; col < 4; col++) 1749 where[col] = ~where[col]; 1750 break; 1751 case 32: 1752 for (col = 0; col < 8; col++) 1753 where[col] = ~where[col]; 1754 break; 1755 } 1756 where = (uint32_t*)(((unsigned char*)where)+vinfo.v_rowbytes); 1757 } 1758} 1759 1760static void 1761vc_scroll_down(int num, unsigned int scrreg_top, unsigned int scrreg_bottom) 1762{ 1763 uint32_t *from, *to, linelongs, i, line, rowline, rowscanline; 1764 1765 if(!vinfo.v_depth) 1766 return; 1767 1768 linelongs = vinfo.v_rowbytes * (ISO_CHAR_HEIGHT >> 2); 1769 rowline = vinfo.v_rowbytes >> 2; 1770 rowscanline = vinfo.v_rowscanbytes >> 2; 1771 1772 to = (uint32_t *) vinfo.v_baseaddr + (linelongs * scrreg_bottom) 1773 - (rowline - rowscanline); 1774 from = to - (linelongs * num); /* handle multiple line scroll (Michel Pollet) */ 1775 1776 i = (scrreg_bottom - scrreg_top) - num; 1777 1778 while (i-- > 0) { 1779 for (line = 0; line < ISO_CHAR_HEIGHT; line++) { 1780 /* 1781 * Only copy what is displayed 1782 */ 1783 video_scroll_down(from, 1784 (from-(vinfo.v_rowscanbytes >> 2)), 1785 to); 1786 1787 from -= rowline; 1788 to -= rowline; 1789 } 1790 } 1791} 1792 1793static void 1794vc_scroll_up(int num, unsigned int scrreg_top, unsigned int scrreg_bottom) 1795{ 1796 uint32_t *from, *to, linelongs, i, line, rowline, rowscanline; 1797 1798 if(!vinfo.v_depth) 1799 return; 1800 1801 linelongs = vinfo.v_rowbytes * (ISO_CHAR_HEIGHT >> 2); 1802 rowline = vinfo.v_rowbytes >> 2; 1803 rowscanline = vinfo.v_rowscanbytes >> 2; 1804 1805 to = (uint32_t *) vinfo.v_baseaddr + (scrreg_top * linelongs); 1806 from = to + (linelongs * num); /* handle multiple line scroll (Michel Pollet) */ 1807 1808 i = (scrreg_bottom - scrreg_top) - num; 1809 1810 while (i-- > 0) { 1811 for (line = 0; line < ISO_CHAR_HEIGHT; line++) { 1812 /* 1813 * Only copy what is displayed 1814 */ 1815 video_scroll_up(from, 1816 (from+(vinfo.v_rowscanbytes >> 2)), 1817 to); 1818 1819 from += rowline; 1820 to += rowline; 1821 } 1822 } 1823} 1824 1825static void 1826vc_update_color(int color, boolean_t fore) 1827{ 1828 if (!vinfo.v_depth) 1829 return; 1830 if (fore) { 1831 vc_color_fore = vc_colors[color][vc_color_index_table[vinfo.v_depth]]; 1832 } else { 1833 vc_color_back = vc_colors[color][vc_color_index_table[vinfo.v_depth]]; 1834 } 1835} 1836 1837/* 1838 * Video Console (Back-End): Icon Control 1839 * -------------------------------------- 1840 */ 1841 1842static vc_progress_element * vc_progress; 1843enum { kMaxProgressData = 3 }; 1844static const unsigned char * vc_progress_data[kMaxProgressData]; 1845static const unsigned char * vc_progress_alpha; 1846static boolean_t vc_progress_enable; 1847static const unsigned char * vc_clut; 1848static const unsigned char * vc_clut8; 1849static unsigned char vc_revclut8[256]; 1850static uint32_t vc_progress_interval; 1851static uint32_t vc_progress_count; 1852static uint32_t vc_progress_angle; 1853static uint64_t vc_progress_deadline; 1854static thread_call_data_t vc_progress_call; 1855static boolean_t vc_needsave; 1856static void * vc_saveunder; 1857static vm_size_t vc_saveunder_len; 1858static int8_t vc_uiscale = 1; 1859decl_simple_lock_data(,vc_progress_lock) 1860 1861static int vc_progress_withmeter = 3; 1862int vc_progressmeter_enable; 1863static int vc_progressmeter_drawn; 1864int vc_progressmeter_value; 1865static uint32_t vc_progressmeter_count; 1866static uint64_t vc_progressmeter_interval; 1867static uint64_t vc_progressmeter_deadline; 1868static thread_call_data_t vc_progressmeter_call; 1869static void * vc_progressmeter_backbuffer; 1870static boolean_t vc_progressmeter_hold; 1871static uint32_t vc_progressmeter_diskspeed = 256; 1872 1873enum { 1874 kSave = 0x10, 1875 kDataIndexed = 0x20, 1876 kDataAlpha = 0x40, 1877 kDataBack = 0x80, 1878 kDataRotate = 0x03, 1879 kDataRotate0 = 0, 1880 kDataRotate90 = 1, 1881 kDataRotate180 = 2, 1882 kDataRotate270 = 3 1883}; 1884 1885static void vc_blit_rect(int x, int y, int bx, 1886 int width, int height, 1887 int sourceRow, int backRow, 1888 const unsigned char * dataPtr, 1889 void * backBuffer, 1890 unsigned int flags); 1891static void vc_blit_rect_8(int x, int y, int bx, 1892 int width, int height, 1893 int sourceRow, int backRow, 1894 const unsigned char * dataPtr, 1895 unsigned char * backBuffer, 1896 unsigned int flags); 1897static void vc_blit_rect_16(int x, int y, int bx, 1898 int width, int height, 1899 int sourceRow, int backRow, 1900 const unsigned char * dataPtr, 1901 unsigned short * backBuffer, 1902 unsigned int flags); 1903static void vc_blit_rect_32(int x, int y, int bx, 1904 int width, int height, 1905 int sourceRow, int backRow, 1906 const unsigned char * dataPtr, 1907 unsigned int * backBuffer, 1908 unsigned int flags); 1909static void vc_blit_rect_30(int x, int y, int bx, 1910 int width, int height, 1911 int sourceRow, int backRow, 1912 const unsigned char * dataPtr, 1913 unsigned int * backBuffer, 1914 unsigned int flags); 1915static void vc_progress_task( void * arg0, void * arg ); 1916static void vc_progressmeter_task( void * arg0, void * arg ); 1917 1918static void vc_blit_rect(int x, int y, int bx, 1919 int width, int height, 1920 int sourceRow, int backRow, 1921 const unsigned char * dataPtr, 1922 void * backBuffer, 1923 unsigned int flags) 1924{ 1925 if(!vinfo.v_depth) 1926 return; 1927 1928 switch( vinfo.v_depth) { 1929 case 8: 1930 if( vc_clut8 == vc_clut) 1931 vc_blit_rect_8( x, y, bx, width, height, sourceRow, backRow, dataPtr, (unsigned char *) backBuffer, flags ); 1932 break; 1933 case 16: 1934 vc_blit_rect_16( x, y, bx, width, height, sourceRow, backRow, dataPtr, (unsigned short *) backBuffer, flags ); 1935 break; 1936 case 32: 1937 vc_blit_rect_32( x, y, bx, width, height, sourceRow, backRow, dataPtr, (unsigned int *) backBuffer, flags ); 1938 break; 1939 case 30: 1940 vc_blit_rect_30( x, y, bx, width, height, sourceRow, backRow, dataPtr, (unsigned int *) backBuffer, flags ); 1941 break; 1942 } 1943} 1944 1945static void 1946vc_blit_rect_8(int x, int y, __unused int bx, 1947 int width, int height, 1948 int sourceRow, __unused int backRow, 1949 const unsigned char * dataPtr, 1950 __unused unsigned char * backBuffer, 1951 __unused unsigned int flags) 1952{ 1953 volatile unsigned short * dst; 1954 int line, col; 1955 unsigned int data = 0, out = 0; 1956 int sx, sy, a, b, c, d; 1957 int scale = 0x10000; 1958 1959 a = vc_rotate_matr[kDataRotate & flags][0][0] * scale; 1960 b = vc_rotate_matr[kDataRotate & flags][0][1] * scale; 1961 c = vc_rotate_matr[kDataRotate & flags][1][0] * scale; 1962 d = vc_rotate_matr[kDataRotate & flags][1][1] * scale; 1963 sx = ((a + b) < 0) ? ((width * scale) - 0x8000) : 0; 1964 sy = ((c + d) < 0) ? ((height * scale) - 0x8000) : 0; 1965 1966 if (!sourceRow) data = (unsigned int)(uintptr_t)dataPtr; 1967 else if (1 == sourceRow) a = 0; 1968 1969 dst = (volatile unsigned short *) (vinfo.v_baseaddr + 1970 (y * vinfo.v_rowbytes) + 1971 (x * 4)); 1972 1973 for( line = 0; line < height; line++) 1974 { 1975 for( col = 0; col < width; col++) 1976 { 1977 if (sourceRow) data = dataPtr[((sx + (col * a) + (line * b)) >> 16) 1978 + sourceRow * (((sy + (col * c) + (line * d)) >> 16))]; 1979 if (kDataAlpha & flags) 1980 out = vc_revclut8[data]; 1981 else 1982 out = data; 1983 *(dst + col) = out; 1984 } 1985 dst = (volatile unsigned short *) (((volatile char*)dst) + vinfo.v_rowbytes); 1986 } 1987} 1988 1989/* For ARM, 16-bit is 565 (RGB); it is 1555 (XRGB) on other platforms */ 1990 1991#define CLUT_MASK_R 0xf8 1992#define CLUT_MASK_G 0xf8 1993#define CLUT_MASK_B 0xf8 1994#define CLUT_SHIFT_R << 7 1995#define CLUT_SHIFT_G << 2 1996#define CLUT_SHIFT_B >> 3 1997#define MASK_R 0x7c00 1998#define MASK_G 0x03e0 1999#define MASK_B 0x001f 2000#define MASK_R_8 0x3fc00 2001#define MASK_G_8 0x01fe0 2002#define MASK_B_8 0x000ff 2003 2004static void vc_blit_rect_16( int x, int y, int bx, 2005 int width, int height, 2006 int sourceRow, int backRow, 2007 const unsigned char * dataPtr, 2008 unsigned short * backPtr, 2009 unsigned int flags) 2010{ 2011 volatile unsigned short * dst; 2012 int line, col; 2013 unsigned int data = 0, out = 0, back = 0; 2014 int sx, sy, a, b, c, d; 2015 int scale = 0x10000; 2016 2017 a = vc_rotate_matr[kDataRotate & flags][0][0] * scale; 2018 b = vc_rotate_matr[kDataRotate & flags][0][1] * scale; 2019 c = vc_rotate_matr[kDataRotate & flags][1][0] * scale; 2020 d = vc_rotate_matr[kDataRotate & flags][1][1] * scale; 2021 sx = ((a + b) < 0) ? ((width * scale) - 0x8000) : 0; 2022 sy = ((c + d) < 0) ? ((height * scale) - 0x8000) : 0; 2023 2024 if (!sourceRow) data = (unsigned int)(uintptr_t)dataPtr; 2025 else if (1 == sourceRow) a = 0; 2026 2027 if (backPtr) 2028 backPtr += bx; 2029 dst = (volatile unsigned short *) (vinfo.v_baseaddr + 2030 (y * vinfo.v_rowbytes) + 2031 (x * 2)); 2032 2033 for( line = 0; line < height; line++) 2034 { 2035 for( col = 0; col < width; col++) 2036 { 2037 if (sourceRow) data = dataPtr[((sx + (col * a) + (line * b)) >> 16) 2038 + sourceRow * (((sy + (col * c) + (line * d)) >> 16))]; 2039 if (backPtr) { 2040 if (kSave & flags) { 2041 back = *(dst + col); 2042 *backPtr++ = back; 2043 } else 2044 back = *backPtr++; 2045 } 2046 if (kDataIndexed & flags) { 2047 out = ( (CLUT_MASK_R & (vc_clut[data*3 + 0])) CLUT_SHIFT_R) 2048 | ( (CLUT_MASK_G & (vc_clut[data*3 + 1])) CLUT_SHIFT_G) 2049 | ( (CLUT_MASK_B & (vc_clut[data*3 + 2])) CLUT_SHIFT_B); 2050 } else if (kDataAlpha & flags) { 2051 out = (((((back & MASK_R) * data) + MASK_R_8) >> 8) & MASK_R) 2052 | (((((back & MASK_G) * data) + MASK_G_8) >> 8) & MASK_G) 2053 | (((((back & MASK_B) * data) + MASK_B_8) >> 8) & MASK_B); 2054 if (vc_progress_white) out += (((0xff - data) & CLUT_MASK_R) CLUT_SHIFT_R) 2055 | (((0xff - data) & CLUT_MASK_G) CLUT_SHIFT_G) 2056 | (((0xff - data) & CLUT_MASK_B) CLUT_SHIFT_B); 2057 } else if (kDataBack & flags) 2058 out = back; 2059 else 2060 out = data; 2061 *(dst + col) = out; 2062 } 2063 dst = (volatile unsigned short *) (((volatile char*)dst) + vinfo.v_rowbytes); 2064 if (backPtr) 2065 backPtr += backRow - width; 2066 } 2067} 2068 2069 2070static void vc_blit_rect_32(int x, int y, int bx, 2071 int width, int height, 2072 int sourceRow, int backRow, 2073 const unsigned char * dataPtr, 2074 unsigned int * backPtr, 2075 unsigned int flags) 2076{ 2077 volatile unsigned int * dst; 2078 int line, col; 2079 unsigned int data = 0, out = 0, back = 0; 2080 int sx, sy, a, b, c, d; 2081 int scale = 0x10000; 2082 2083 a = vc_rotate_matr[kDataRotate & flags][0][0] * scale; 2084 b = vc_rotate_matr[kDataRotate & flags][0][1] * scale; 2085 c = vc_rotate_matr[kDataRotate & flags][1][0] * scale; 2086 d = vc_rotate_matr[kDataRotate & flags][1][1] * scale; 2087 sx = ((a + b) < 0) ? ((width * scale) - 0x8000) : 0; 2088 sy = ((c + d) < 0) ? ((height * scale) - 0x8000) : 0; 2089 2090 if (!sourceRow) data = (unsigned int)(uintptr_t)dataPtr; 2091 else if (1 == sourceRow) a = 0; 2092 2093 if (backPtr) 2094 backPtr += bx; 2095 dst = (volatile unsigned int *) (vinfo.v_baseaddr + 2096 (y * vinfo.v_rowbytes) + 2097 (x * 4)); 2098 2099 for( line = 0; line < height; line++) 2100 { 2101 for( col = 0; col < width; col++) 2102 { 2103 if (sourceRow) data = dataPtr[((sx + (col * a) + (line * b)) >> 16) 2104 + sourceRow * (((sy + (col * c) + (line * d)) >> 16))]; 2105 if (backPtr) { 2106 if (kSave & flags) { 2107 back = *(dst + col); 2108 *backPtr++ = back; 2109 } else 2110 back = *backPtr++; 2111 } 2112 if (kDataIndexed & flags) { 2113 out = (vc_clut[data*3 + 0] << 16) 2114 | (vc_clut[data*3 + 1] << 8) 2115 | (vc_clut[data*3 + 2]); 2116 } else if (kDataAlpha & flags) { 2117 out = (((((back & 0x00ff00ff) * data) + 0x00ff00ff) >> 8) & 0x00ff00ff) 2118 | (((((back & 0x0000ff00) * data) + 0x0000ff00) >> 8) & 0x0000ff00); 2119 if (vc_progress_white) out += ((0xff - data) << 16) 2120 | ((0xff - data) << 8) 2121 | (0xff - data); 2122 } else if (kDataBack & flags) 2123 out = back; 2124 else 2125 out = data; 2126 *(dst + col) = out; 2127 } 2128 dst = (volatile unsigned int *) (((volatile char*)dst) + vinfo.v_rowbytes); 2129 if (backPtr) 2130 backPtr += backRow - width; 2131 } 2132} 2133 2134static void vc_blit_rect_30(int x, int y, int bx, 2135 int width, int height, 2136 int sourceRow, int backRow, 2137 const unsigned char * dataPtr, 2138 unsigned int * backPtr, 2139 unsigned int flags) 2140{ 2141 volatile unsigned int * dst; 2142 int line, col; 2143 unsigned int data = 0, out = 0, back = 0; 2144 unsigned long long exp; 2145 int sx, sy, a, b, c, d; 2146 int scale = 0x10000; 2147 2148 a = vc_rotate_matr[kDataRotate & flags][0][0] * scale; 2149 b = vc_rotate_matr[kDataRotate & flags][0][1] * scale; 2150 c = vc_rotate_matr[kDataRotate & flags][1][0] * scale; 2151 d = vc_rotate_matr[kDataRotate & flags][1][1] * scale; 2152 sx = ((a + b) < 0) ? ((width * scale) - 0x8000) : 0; 2153 sy = ((c + d) < 0) ? ((height * scale) - 0x8000) : 0; 2154 2155 if (!sourceRow) data = (unsigned int)(uintptr_t)dataPtr; 2156 else if (1 == sourceRow) a = 0; 2157 2158 if (backPtr) 2159 backPtr += bx; 2160 dst = (volatile unsigned int *) (vinfo.v_baseaddr + 2161 (y * vinfo.v_rowbytes) + 2162 (x * 4)); 2163 2164 for( line = 0; line < height; line++) 2165 { 2166 for( col = 0; col < width; col++) 2167 { 2168 if (col < sourceRow) 2169 data = *dataPtr++; 2170 2171 if (backPtr) { 2172 if (kSave & flags) { 2173 back = *(dst + col); 2174 *backPtr++ = back; 2175 } else 2176 back = *backPtr++; 2177 } 2178 if (kDataIndexed & flags) { 2179 out = (vc_clut[data*3 + 0] << 22) 2180 | (vc_clut[data*3 + 1] << 12) 2181 | (vc_clut[data*3 + 2] << 2); 2182 } else if (kDataAlpha & flags) { 2183 exp = back; 2184 exp = (((((exp & 0x3FF003FF) * data) + 0x0FF000FF) >> 8) & 0x3FF003FF) 2185 | (((((exp & 0x000FFC00) * data) + 0x0003FC00) >> 8) & 0x000FFC00); 2186 out = (unsigned int)exp; 2187 if (vc_progress_white) out += ((0xFF - data) << 22) 2188 | ((0xFF - data) << 12) 2189 | ((0xFF - data) << 2); 2190 } else if (kDataBack & flags) 2191 out = back; 2192 else 2193 out = data; 2194 *(dst + col) = out; 2195 } 2196 dst = (volatile unsigned int *) (((volatile char*)dst) + vinfo.v_rowbytes); 2197 if (backPtr) 2198 backPtr += backRow - width; 2199 } 2200} 2201 2202static void vc_clean_boot_graphics(void) 2203{ 2204 // clean up possible FDE login graphics 2205 vc_progress_set(FALSE, 0); 2206 const unsigned char * 2207 color = (typeof(color))(uintptr_t)(vc_progress_white ? 0x00000000 : 0xBFBFBFBF); 2208 vc_blit_rect(0, 0, 0, vinfo.v_width, vinfo.v_height, 0, 0, color, NULL, 0); 2209} 2210 2211/* 2212 * Routines to render the lzss image format 2213 */ 2214 2215struct lzss_image_state { 2216 uint32_t col; 2217 uint32_t row; 2218 uint32_t width; 2219 uint32_t height; 2220 uint32_t bytes_per_row; 2221 volatile uint32_t * row_start; 2222 const uint8_t* clut; 2223}; 2224typedef struct lzss_image_state lzss_image_state; 2225 2226// returns 0 if OK, 1 if error 2227static inline int 2228vc_decompress_lzss_next_pixel (int next_data, lzss_image_state* state) 2229{ 2230 uint32_t palette_index = 0; 2231 uint32_t pixel_value = 0; 2232 2233 palette_index = next_data * 3; 2234 2235 pixel_value = ( (uint32_t) state->clut[palette_index + 0] << 16) 2236 | ( (uint32_t) state->clut[palette_index + 1] << 8) 2237 | ( (uint32_t) state->clut[palette_index + 2]); 2238 2239 *(state->row_start + state->col) = pixel_value; 2240 2241 if (++state->col >= state->width) { 2242 state->col = 0; 2243 if (++state->row >= state->height) { 2244 return 1; 2245 } 2246 state->row_start = (volatile uint32_t *) (((uintptr_t)state->row_start) + state->bytes_per_row); 2247 } 2248 return 0; 2249} 2250 2251 2252/* 2253 * Blit an lzss compressed image to the framebuffer 2254 * Assumes 32 bit screen (which is everything we ship at the moment) 2255 * The function vc_display_lzss_icon was copied from libkern/mkext.c, then modified. 2256 */ 2257 2258/* 2259 * TODO: Does lzss use too much stack? 4096 plus bytes... 2260 * Can probably chop it down by 1/2. 2261 */ 2262 2263/************************************************************** 2264 LZSS.C -- A Data Compression Program 2265*************************************************************** 2266 4/6/1989 Haruhiko Okumura 2267 Use, distribute, and modify this program freely. 2268 Please send me your improved versions. 2269 PC-VAN SCIENCE 2270 NIFTY-Serve PAF01022 2271 CompuServe 74050,1022 2272 2273**************************************************************/ 2274 2275#define N 4096 /* size of ring buffer - must be power of 2 */ 2276#define F 18 /* upper limit for match_length */ 2277#define THRESHOLD 2 /* encode string into position and length 2278 if match_length is greater than this */ 2279 2280// returns 0 if OK, 1 if error 2281// x and y indicate upper left corner of image location on screen 2282int 2283vc_display_lzss_icon(uint32_t dst_x, uint32_t dst_y, 2284 uint32_t image_width, uint32_t image_height, 2285 const uint8_t *compressed_image, 2286 uint32_t compressed_size, 2287 const uint8_t *clut) 2288{ 2289 uint32_t* image_start; 2290 uint32_t bytes_per_pixel = 4; 2291 uint32_t bytes_per_row = vinfo.v_rowbytes; 2292 2293 vc_clean_boot_graphics(); 2294 2295 image_start = (uint32_t *) (vinfo.v_baseaddr + (dst_y * bytes_per_row) + (dst_x * bytes_per_pixel)); 2296 2297 lzss_image_state state = {0, 0, image_width, image_height, bytes_per_row, image_start, clut}; 2298 2299 int rval = 0; 2300 2301 const uint8_t *src = compressed_image; 2302 uint32_t srclen = compressed_size; 2303 2304 /* ring buffer of size N, with extra F-1 bytes to aid string comparison */ 2305 uint8_t text_buf[N + F - 1]; 2306 const uint8_t *srcend = src + srclen; 2307 int i, j, k, r, c; 2308 unsigned int flags; 2309 2310 srcend = src + srclen; 2311 for (i = 0; i < N - F; i++) 2312 text_buf[i] = ' '; 2313 r = N - F; 2314 flags = 0; 2315 for ( ; ; ) { 2316 if (((flags >>= 1) & 0x100) == 0) { 2317 if (src < srcend) c = *src++; else break; 2318 flags = c | 0xFF00; /* uses higher byte cleverly */ 2319 } /* to count eight */ 2320 if (flags & 1) { 2321 if (src < srcend) c = *src++; else break; 2322 rval = vc_decompress_lzss_next_pixel(c, &state); 2323 if (rval != 0) 2324 return rval; 2325 text_buf[r++] = c; 2326 r &= (N - 1); 2327 } else { 2328 if (src < srcend) i = *src++; else break; 2329 if (src < srcend) j = *src++; else break; 2330 i |= ((j & 0xF0) << 4); 2331 j = (j & 0x0F) + THRESHOLD; 2332 for (k = 0; k <= j; k++) { 2333 c = text_buf[(i + k) & (N - 1)]; 2334 rval = vc_decompress_lzss_next_pixel(c, &state); 2335 if (rval != 0 ) 2336 return rval; 2337 text_buf[r++] = c; 2338 r &= (N - 1); 2339 } 2340 } 2341 } 2342 return 0; 2343} 2344 2345void noroot_icon_test(void) { 2346 boolean_t o_vc_progress_enable = vc_progress_enable; 2347 2348 vc_progress_enable = 1; 2349 2350 PE_display_icon( 0, "noroot"); 2351 2352 vc_progress_enable = o_vc_progress_enable; 2353} 2354 2355 2356void vc_display_icon( vc_progress_element * desc, 2357 const unsigned char * data ) 2358{ 2359 int x, y, width, height; 2360 2361 if( vc_progress_enable && vc_clut) { 2362 2363 vc_clean_boot_graphics(); 2364 2365 width = desc->width; 2366 height = desc->height; 2367 x = desc->dx; 2368 y = desc->dy; 2369 if( 1 & desc->flags) { 2370 x += ((vinfo.v_width - width) / 2); 2371 y += ((vinfo.v_height - height) / 2); 2372 } 2373 vc_blit_rect( x, y, 0, width, height, width, 0, data, NULL, kDataIndexed ); 2374 } 2375} 2376 2377void 2378vc_progress_initialize( vc_progress_element * desc, 2379 const unsigned char * data1x, 2380 const unsigned char * data2x, 2381 const unsigned char * data3x, 2382 const unsigned char * clut ) 2383{ 2384 uint64_t abstime; 2385 2386 if( (!clut) || (!desc) || (!data1x)) 2387 return; 2388 vc_clut = clut; 2389 vc_clut8 = clut; 2390 2391 vc_progress = desc; 2392 vc_progress_data[0] = data1x; 2393 vc_progress_data[1] = data2x; 2394 vc_progress_data[2] = data3x; 2395 if( 2 & vc_progress->flags) 2396 vc_progress_alpha = data1x 2397 + vc_progress->count * vc_progress->width * vc_progress->height; 2398 else 2399 vc_progress_alpha = NULL; 2400 2401 thread_call_setup(&vc_progress_call, vc_progress_task, NULL); 2402 clock_interval_to_absolutetime_interval(vc_progress->time, 1000 * 1000, &abstime); 2403 vc_progress_interval = (uint32_t)abstime; 2404 2405 thread_call_setup(&vc_progressmeter_call, vc_progressmeter_task, NULL); 2406 clock_interval_to_absolutetime_interval(1000 / 8, 1000 * 1000, &abstime); 2407 vc_progressmeter_interval = (uint32_t)abstime; 2408 2409} 2410 2411void 2412vc_progress_set(boolean_t enable, uint32_t vc_delay) 2413{ 2414 spl_t s; 2415 void *saveBuf = NULL; 2416 vm_size_t saveLen = 0; 2417 unsigned int count; 2418 unsigned int index; 2419 unsigned char pdata8; 2420 unsigned short pdata16; 2421 unsigned short * buf16; 2422 unsigned int pdata32; 2423 unsigned int * buf32; 2424 2425 2426 if (kBootArgsFlagBlack & ((boot_args *) PE_state.bootArgs)->flags) return; 2427 2428 if (1 & vc_progress_withmeter) 2429 { 2430 if (enable) internal_enable_progressmeter(kProgressMeterKernel); 2431 2432 s = splhigh(); 2433 simple_lock(&vc_progress_lock); 2434 2435 if( vc_progress_enable != enable) { 2436 vc_progress_enable = enable; 2437 if( enable) 2438 { 2439 vc_progressmeter_count = 0; 2440 clock_interval_to_deadline(vc_delay, 2441 1000 * 1000 * 1000 /*second scale*/, 2442 &vc_progressmeter_deadline); 2443 thread_call_enter_delayed(&vc_progressmeter_call, vc_progressmeter_deadline); 2444 } 2445 else thread_call_cancel(&vc_progressmeter_call); 2446 } 2447 2448 simple_unlock(&vc_progress_lock); 2449 splx(s); 2450 2451 if (!enable) internal_enable_progressmeter(kProgressMeterOff); 2452 return; 2453 } 2454 2455 2456 if(!vc_progress) return; 2457 2458 if( enable) { 2459 saveLen = (vc_progress->width * vc_uiscale) * (vc_progress->height * vc_uiscale) * vinfo.v_depth / 8; 2460 saveBuf = kalloc( saveLen ); 2461 2462 switch( vinfo.v_depth) { 2463 case 8 : 2464 for( count = 0; count < 256; count++) { 2465 vc_revclut8[count] = vc_clut[0x01 * 3]; 2466 pdata8 = (vc_clut[0x01 * 3] * count + 0x0ff) >> 8; 2467 for( index = 0; index < 256; index++) { 2468 if( (pdata8 == vc_clut[index * 3 + 0]) && 2469 (pdata8 == vc_clut[index * 3 + 1]) && 2470 (pdata8 == vc_clut[index * 3 + 2])) { 2471 vc_revclut8[count] = index; 2472 break; 2473 } 2474 } 2475 } 2476 memset( saveBuf, 0x01, saveLen ); 2477 break; 2478 2479 case 16 : 2480 buf16 = (unsigned short *) saveBuf; 2481 pdata16 = ((vc_clut[0x01 * 3 + 0] & CLUT_MASK_R) CLUT_SHIFT_R) 2482 | ((vc_clut[0x01 * 3 + 0] & CLUT_MASK_G) CLUT_SHIFT_G) 2483 | ((vc_clut[0x01 * 3 + 0] & CLUT_MASK_B) CLUT_SHIFT_B); 2484 for( count = 0; count < saveLen / 2; count++) 2485 buf16[count] = pdata16; 2486 break; 2487 2488 case 32 : 2489 buf32 = (unsigned int *) saveBuf; 2490 pdata32 = ((vc_clut[0x01 * 3 + 0] & 0xff) << 16) 2491 | ((vc_clut[0x01 * 3 + 1] & 0xff) << 8) 2492 | ((vc_clut[0x01 * 3 + 2] & 0xff) << 0); 2493 for( count = 0; count < saveLen / 4; count++) 2494 buf32[count] = pdata32; 2495 break; 2496 } 2497 } 2498 2499 s = splhigh(); 2500 simple_lock(&vc_progress_lock); 2501 2502 if( vc_progress_enable != enable) { 2503 vc_progress_enable = enable; 2504 if( enable) { 2505 vc_needsave = TRUE; 2506 vc_saveunder = saveBuf; 2507 vc_saveunder_len = saveLen; 2508 saveBuf = NULL; 2509 saveLen = 0; 2510 vc_progress_count = 0; 2511 vc_progress_angle = 0; 2512 2513 clock_interval_to_deadline(vc_delay, 2514 1000 * 1000 * 1000 /*second scale*/, 2515 &vc_progress_deadline); 2516 thread_call_enter_delayed(&vc_progress_call, vc_progress_deadline); 2517 2518 } else { 2519 if( vc_saveunder) { 2520 saveBuf = vc_saveunder; 2521 saveLen = vc_saveunder_len; 2522 vc_saveunder = NULL; 2523 vc_saveunder_len = 0; 2524 } 2525 2526 thread_call_cancel(&vc_progress_call); 2527 } 2528 } 2529 2530 simple_unlock(&vc_progress_lock); 2531 splx(s); 2532 2533 if( saveBuf) 2534 kfree( saveBuf, saveLen ); 2535} 2536 2537 2538static void 2539vc_progressmeter_task(__unused void *arg0, __unused void *arg) 2540{ 2541 spl_t s; 2542 uint64_t interval; 2543 2544 s = splhigh(); 2545 simple_lock(&vc_progress_lock); 2546 if (vc_progressmeter_enable) 2547 { 2548 uint32_t pos = (vc_progressmeter_count >> 13); 2549 internal_set_progressmeter(pos); 2550 if (pos < kProgressMeterEnd) 2551 { 2552 static uint16_t incr[8] = { 10000, 10000, 8192, 4096, 2048, 384, 384, 64 }; 2553 vc_progressmeter_count += incr[(pos * 8) / kProgressMeterEnd]; 2554 2555 interval = vc_progressmeter_interval; 2556 interval = ((interval * 256) / vc_progressmeter_diskspeed); 2557 2558 clock_deadline_for_periodic_event(interval, mach_absolute_time(), &vc_progressmeter_deadline); 2559 thread_call_enter_delayed(&vc_progressmeter_call, vc_progressmeter_deadline); 2560 } 2561 } 2562 simple_unlock(&vc_progress_lock); 2563 splx(s); 2564} 2565 2566void vc_progress_setdiskspeed(uint32_t speed) 2567{ 2568 vc_progressmeter_diskspeed = speed; 2569} 2570 2571 2572static void 2573vc_progress_task(__unused void *arg0, __unused void *arg) 2574{ 2575 spl_t s; 2576 int x, y, width, height; 2577 const unsigned char * data; 2578 2579 s = splhigh(); 2580 simple_lock(&vc_progress_lock); 2581 2582 if( vc_progress_enable) { 2583 2584 vc_progress_count++; 2585 if( vc_progress_count >= vc_progress->count) { 2586 vc_progress_count = 0; 2587 vc_progress_angle++; 2588 } 2589 2590 width = (vc_progress->width * vc_uiscale); 2591 height = (vc_progress->height * vc_uiscale); 2592 x = (vc_progress->dx * vc_uiscale); 2593 y = (vc_progress->dy * vc_uiscale); 2594 data = vc_progress_data[vc_uiscale - 1]; 2595 if (data) 2596 { 2597 data += vc_progress_count * width * height; 2598 if( 1 & vc_progress->flags) { 2599 x += ((vinfo.v_width - width) / 2); 2600 y += ((vinfo.v_height - height) / 2); 2601 } 2602 2603 assert(((x + width) < (int)vinfo.v_width) && 2604 ((y + height) < (int)vinfo.v_height)); 2605 2606 vc_blit_rect( x, y, 0, 2607 width, height, width, width, 2608 data, vc_saveunder, 2609 kDataAlpha 2610 | (vc_progress_angle & kDataRotate) 2611 | (vc_needsave ? kSave : 0) ); 2612 vc_needsave = FALSE; 2613 2614 clock_deadline_for_periodic_event(vc_progress_interval, mach_absolute_time(), &vc_progress_deadline); 2615 thread_call_enter_delayed(&vc_progress_call, vc_progress_deadline); 2616 } 2617 } 2618 simple_unlock(&vc_progress_lock); 2619 splx(s); 2620} 2621 2622/* 2623 * Generic Console (Front-End): Master Control 2624 * ------------------------------------------- 2625 */ 2626 2627#if defined (__i386__) || defined (__x86_64__) 2628#include <pexpert/i386/boot.h> 2629#endif 2630 2631static boolean_t gc_acquired = FALSE; 2632static boolean_t gc_graphics_boot = FALSE; 2633static boolean_t gc_desire_text = FALSE; 2634static boolean_t gc_paused_progress; 2635 2636static uint64_t lastVideoPhys = 0; 2637static vm_offset_t lastVideoVirt = 0; 2638static vm_size_t lastVideoSize = 0; 2639static boolean_t lastVideoMapped = FALSE; 2640static void 2641gc_pause( boolean_t pause, boolean_t graphics_now ) 2642{ 2643 spl_t s; 2644 2645 s = splhigh( ); 2646 VCPUTC_LOCK_LOCK( ); 2647 2648 disableConsoleOutput = (pause && !console_is_serial()); 2649 gc_enabled = (!pause && !graphics_now); 2650 2651 VCPUTC_LOCK_UNLOCK( ); 2652 2653 simple_lock(&vc_progress_lock); 2654 2655 if (pause) 2656 { 2657 gc_paused_progress = vc_progress_enable; 2658 vc_progress_enable = FALSE; 2659 } 2660 else vc_progress_enable = gc_paused_progress; 2661 2662 if (vc_progress_enable) 2663 { 2664 if (1 & vc_progress_withmeter) thread_call_enter_delayed(&vc_progressmeter_call, vc_progressmeter_deadline); 2665 else 2666 thread_call_enter_delayed(&vc_progress_call, vc_progress_deadline); 2667 } 2668 2669 simple_unlock(&vc_progress_lock); 2670 splx(s); 2671} 2672 2673static void 2674vc_initialize(__unused struct vc_info * vinfo_p) 2675{ 2676 2677 vinfo.v_rows = vinfo.v_height / ISO_CHAR_HEIGHT; 2678 vinfo.v_columns = vinfo.v_width / ISO_CHAR_WIDTH; 2679 vinfo.v_rowscanbytes = ((vinfo.v_depth + 7) / 8) * vinfo.v_width; 2680 vc_uiscale = vinfo.v_scale; 2681 if (vc_uiscale > kMaxProgressData) vc_uiscale = kMaxProgressData; 2682 else if (!vc_uiscale) vc_uiscale = 1; 2683} 2684 2685void 2686initialize_screen(PE_Video * boot_vinfo, unsigned int op) 2687{ 2688 unsigned int fbsize = 0; 2689 vm_offset_t newVideoVirt = 0; 2690 boolean_t graphics_now; 2691 ppnum_t fbppage; 2692 2693 if ( boot_vinfo ) 2694 { 2695 struct vc_info new_vinfo = vinfo; 2696 /* 2697 * First, check if we are changing the size and/or location of the framebuffer 2698 */ 2699 new_vinfo.v_name[0] = 0; 2700 new_vinfo.v_physaddr = boot_vinfo->v_baseAddr & ~3; /* Get the physical address */ 2701#ifndef __LP64__ 2702 new_vinfo.v_physaddr |= (((uint64_t) boot_vinfo->v_baseAddrHigh) << 32); 2703#endif 2704 if (kPEBaseAddressChange != op) 2705 { 2706 new_vinfo.v_width = (unsigned int)boot_vinfo->v_width; 2707 new_vinfo.v_height = (unsigned int)boot_vinfo->v_height; 2708 new_vinfo.v_depth = (unsigned int)boot_vinfo->v_depth; 2709 new_vinfo.v_rowbytes = (unsigned int)boot_vinfo->v_rowBytes; 2710#if defined(__i386__) || defined(__x86_64__) 2711 new_vinfo.v_type = (unsigned int)boot_vinfo->v_display; 2712#else 2713 new_vinfo.v_type = 0; 2714#endif 2715 unsigned int scale = (unsigned int)boot_vinfo->v_scale; 2716 if (scale == kPEScaleFactor1x ) 2717 new_vinfo.v_scale = kPEScaleFactor1x; 2718 else if (scale == kPEScaleFactor2x) 2719 new_vinfo.v_scale = kPEScaleFactor2x; 2720 else /* Scale factor not set, default to 1x */ 2721 new_vinfo.v_scale = kPEScaleFactor1x; 2722 2723 } 2724 2725 if (!lastVideoMapped) 2726 kprintf("initialize_screen: b=%08llX, w=%08X, h=%08X, r=%08X, d=%08X\n", /* (BRINGUP) */ 2727 new_vinfo.v_physaddr, new_vinfo.v_width, new_vinfo.v_height, new_vinfo.v_rowbytes, new_vinfo.v_type); /* (BRINGUP) */ 2728 2729 if (!new_vinfo.v_physaddr) /* Check to see if we have a framebuffer */ 2730 { 2731 kprintf("initialize_screen: No video - forcing serial mode\n"); /* (BRINGUP) */ 2732 new_vinfo.v_depth = 0; /* vc routines are nop */ 2733 (void)switch_to_serial_console(); /* Switch into serial mode */ 2734 gc_graphics_boot = FALSE; /* Say we are not in graphics mode */ 2735 disableConsoleOutput = FALSE; /* Allow printfs to happen */ 2736 gc_acquired = TRUE; 2737 } 2738 else 2739 { 2740 /* 2741 * If VM is up, we are given a virtual address, unless b0 is set to indicate physical. 2742 */ 2743 if ((kernel_map != VM_MAP_NULL) && (0 == (1 & boot_vinfo->v_baseAddr))) 2744 { 2745 fbppage = pmap_find_phys(kernel_pmap, (addr64_t)boot_vinfo->v_baseAddr); /* Get the physical address of frame buffer */ 2746 if(!fbppage) /* Did we find it? */ 2747 { 2748 panic("initialize_screen: Strange framebuffer - addr = %08X\n", (uint32_t)boot_vinfo->v_baseAddr); 2749 } 2750 new_vinfo.v_physaddr = (((uint64_t)fbppage) << PAGE_SHIFT) | (boot_vinfo->v_baseAddr & PAGE_MASK); /* Get the physical address */ 2751 } 2752 2753 if (boot_vinfo->v_length != 0) 2754 fbsize = (unsigned int) round_page(boot_vinfo->v_length); 2755 else 2756 fbsize = (unsigned int) round_page(new_vinfo.v_height * new_vinfo.v_rowbytes); /* Remember size */ 2757 2758 2759 if ((lastVideoPhys != new_vinfo.v_physaddr) || (fbsize > lastVideoSize)) /* Did framebuffer change location or get bigger? */ 2760 { 2761 unsigned int flags = VM_WIMG_IO; 2762 newVideoVirt = io_map_spec((vm_map_offset_t)new_vinfo.v_physaddr, fbsize, flags); /* Allocate address space for framebuffer */ 2763 } 2764 } 2765 2766 if (newVideoVirt != 0) 2767 new_vinfo.v_baseaddr = newVideoVirt + boot_vinfo->v_offset; /* Set the new framebuffer address */ 2768 else 2769 new_vinfo.v_baseaddr = lastVideoVirt + boot_vinfo->v_offset; /* Set the new framebuffer address */ 2770 2771#if defined(__x86_64__) 2772 // Adjust the video buffer pointer to point to where it is in high virtual (above the hole) 2773 new_vinfo.v_baseaddr |= (VM_MIN_KERNEL_ADDRESS & ~LOW_4GB_MASK); 2774#endif 2775 2776 /* Update the vinfo structure atomically with respect to the vc_progress task if running */ 2777 if (vc_progress) 2778 { 2779 simple_lock(&vc_progress_lock); 2780 vinfo = new_vinfo; 2781 simple_unlock(&vc_progress_lock); 2782 } 2783 else 2784 { 2785 vinfo = new_vinfo; 2786 } 2787 2788 // If we changed the virtual address, remove the old mapping 2789 if (newVideoVirt != 0) 2790 { 2791 if (lastVideoVirt) /* Was the framebuffer mapped before? */ 2792 { 2793 /* XXX why did this ever succeed? */ 2794 /* TODO: Consider this. */ 2795 if (!TEST_PAGE_SIZE_4K && lastVideoMapped) /* Was this not a special pre-VM mapping? */ 2796 { 2797 pmap_remove(kernel_pmap, trunc_page_64(lastVideoVirt), 2798 round_page_64(lastVideoVirt + lastVideoSize)); /* Toss mappings */ 2799 } 2800 if(lastVideoMapped) /* Was this not a special pre-VM mapping? */ 2801 { 2802 kmem_free(kernel_map, lastVideoVirt, lastVideoSize); /* Toss kernel addresses */ 2803 } 2804 } 2805 lastVideoPhys = new_vinfo.v_physaddr; /* Remember the framebuffer address */ 2806 lastVideoSize = fbsize; /* Remember the size */ 2807 lastVideoVirt = newVideoVirt; /* Remember the virtual framebuffer address */ 2808 lastVideoMapped = (NULL != kernel_map); 2809 } 2810 2811 if (kPEBaseAddressChange != op) 2812 { 2813 // Graphics mode setup by the booter. 2814 2815 gc_ops.initialize = vc_initialize; 2816 gc_ops.enable = vc_enable; 2817 gc_ops.paint_char = vc_paint_char; 2818 gc_ops.scroll_down = vc_scroll_down; 2819 gc_ops.scroll_up = vc_scroll_up; 2820 gc_ops.clear_screen = vc_clear_screen; 2821 gc_ops.hide_cursor = vc_reverse_cursor; 2822 gc_ops.show_cursor = vc_reverse_cursor; 2823 gc_ops.update_color = vc_update_color; 2824 gc_initialize(&vinfo); 2825 } 2826 } 2827 2828 graphics_now = gc_graphics_boot && !gc_desire_text; 2829 switch ( op ) 2830 { 2831 case kPEGraphicsMode: 2832 gc_graphics_boot = TRUE; 2833 gc_desire_text = FALSE; 2834 break; 2835 2836 case kPETextMode: 2837 disable_debug_output = FALSE; 2838 gc_graphics_boot = FALSE; 2839 break; 2840 2841 case kPEAcquireScreen: 2842 if ( gc_acquired ) break; 2843 vc_progress_set( graphics_now, vc_acquire_delay ); 2844 gc_enable( !graphics_now ); 2845 gc_acquired = TRUE; 2846 gc_desire_text = FALSE; 2847 break; 2848 2849 case kPEDisableScreen: 2850 if (gc_acquired) 2851 { 2852 gc_pause( TRUE, graphics_now ); 2853 } 2854 break; 2855 2856 case kPEEnableScreen: 2857 if (gc_acquired) 2858 { 2859 gc_pause( FALSE, graphics_now ); 2860 } 2861 break; 2862 2863 case kPETextScreen: 2864 if ( console_is_serial() ) break; 2865 2866 disable_debug_output = FALSE; 2867 if ( gc_acquired == FALSE ) 2868 { 2869 gc_desire_text = TRUE; 2870 break; 2871 } 2872 if ( gc_graphics_boot == FALSE ) break; 2873 2874 vc_progress_set( FALSE, 0 ); 2875 vc_enable_progressmeter( FALSE ); 2876 gc_enable( TRUE ); 2877 break; 2878 2879 case kPEReleaseScreen: 2880 gc_acquired = FALSE; 2881 gc_desire_text = FALSE; 2882 gc_enable( FALSE ); 2883 if ( gc_graphics_boot == FALSE ) break; 2884 2885 vc_progress_set( FALSE, 0 ); 2886 vc_acquire_delay = kProgressReacquireDelay; 2887 vc_enable_progressmeter(FALSE); 2888 vc_progress_white = TRUE; 2889 vc_progress_withmeter &= ~1; 2890 vc_clut8 = NULL; 2891 break; 2892 2893 2894 case kPERefreshBootGraphics: 2895 { 2896 spl_t s; 2897 boolean_t save; 2898 2899 if (kBootArgsFlagBlack & ((boot_args *) PE_state.bootArgs)->flags) break; 2900 2901 save = vc_progress_white; 2902 vc_progress_white = (0 != (kBootArgsFlagBlackBg & ((boot_args *) PE_state.bootArgs)->flags)); 2903 2904 internal_enable_progressmeter(kProgressMeterKernel); 2905 2906 s = splhigh(); 2907 simple_lock(&vc_progress_lock); 2908 2909 vc_progressmeter_drawn = 0; 2910 internal_set_progressmeter(vc_progressmeter_count >> 13); 2911 2912 simple_unlock(&vc_progress_lock); 2913 splx(s); 2914 2915 internal_enable_progressmeter(kProgressMeterOff); 2916 vc_progress_white = save; 2917 } 2918 } 2919} 2920 2921void 2922dim_screen(void) 2923{ 2924 unsigned int *p, *endp, *row; 2925 int col, rowline, rowlongs; 2926 register unsigned int mask; 2927 2928 if(!vinfo.v_depth) 2929 return; 2930 2931 if ( vinfo.v_depth == 32 ) 2932 mask = 0x007F7F7F; 2933 else if ( vinfo.v_depth == 30 ) 2934 mask = (0x1ff<<20) | (0x1ff<<10) | 0x1ff; 2935 else if ( vinfo.v_depth == 16 ) 2936 mask = 0x3DEF3DEF; 2937 else 2938 return; 2939 2940 rowline = (int)(vinfo.v_rowscanbytes / 4); 2941 rowlongs = (int)(vinfo.v_rowbytes / 4); 2942 2943 p = (unsigned int*) vinfo.v_baseaddr; 2944 endp = p + (rowlongs * vinfo.v_height); 2945 2946 for (row = p ; row < endp ; row += rowlongs) { 2947 for (p = &row[0], col = 0; col < rowline; col++) { 2948 *p = (*p >> 1) & mask; 2949 ++p; 2950 } 2951 } 2952} 2953 2954void vcattach(void); /* XXX gcc 4 warning cleanup */ 2955 2956void 2957vcattach(void) 2958{ 2959 vm_initialized = TRUE; 2960 2961 vc_progress_white = (0 != ((kBootArgsFlagBlackBg | kBootArgsFlagLoginUI) 2962 & ((boot_args *) PE_state.bootArgs)->flags)); 2963 PE_parse_boot_argn("meter", &vc_progress_withmeter, sizeof(vc_progress_withmeter)); 2964 simple_lock_init(&vc_progress_lock, 0); 2965 2966 if ( gc_graphics_boot == FALSE ) 2967 { 2968 long index; 2969 2970 if ( gc_acquired ) 2971 { 2972 initialize_screen(NULL, kPEReleaseScreen); 2973 } 2974 2975 initialize_screen(NULL, kPEAcquireScreen); 2976 2977 for ( index = 0 ; index < msgbufp->msg_bufx ; index++ ) 2978 { 2979 if (msgbufp->msg_bufc[index] == '\0') { 2980 continue; 2981 } 2982 2983 vcputc( 0, 0, msgbufp->msg_bufc[index] ); 2984 2985 if ( msgbufp->msg_bufc[index] == '\n' ) 2986 { 2987 vcputc( 0, 0,'\r' ); 2988 } 2989 } 2990 } 2991} 2992 2993 2994// redraw progress meter between pixels x1, x2, position at x3 2995static void 2996vc_draw_progress_meter(unsigned int flags, int x1, int x2, int x3) 2997{ 2998 const unsigned char * data; 2999 int x, w; 3000 int ox, oy; 3001 int endCapPos; 3002 int onoff; 3003 // 1 rounded fill, 0 square end 3004 int style = (0 == (2 & vc_progress_withmeter)); 3005 3006 ox = ((vinfo.v_width - (kProgressBarWidth * vc_uiscale)) / 2); 3007 oy = vinfo.v_height - (vinfo.v_height / 3) - ((kProgressBarHeight * vc_uiscale) / 2); 3008 3009 if (kDataBack == flags) 3010 { 3011 // restore back bits 3012 vc_blit_rect(ox + x1, oy, x1, 3013 x2, (kProgressBarHeight * vc_uiscale), 0, (kProgressBarWidth * vc_uiscale), 3014 NULL, vc_progressmeter_backbuffer, flags); 3015 return; 3016 } 3017 3018 for (x = x1; x < x2; x += w) 3019 { 3020 onoff = (x < x3); 3021 endCapPos = ((style && onoff) ? x3 : (kProgressBarWidth * vc_uiscale)); 3022 if (x < (kProgressBarCapWidth * vc_uiscale)) 3023 { 3024 if (x2 < (kProgressBarCapWidth * vc_uiscale)) 3025 w = x2 - x; 3026 else 3027 w = (kProgressBarCapWidth * vc_uiscale) - x; 3028 data = progressmeter_leftcap[vc_uiscale >= 2][onoff]; 3029 data += x; 3030 vc_blit_rect(ox + x, oy, x, w, 3031 (kProgressBarHeight * vc_uiscale), 3032 (kProgressBarCapWidth * vc_uiscale), 3033 (kProgressBarWidth * vc_uiscale), 3034 data, vc_progressmeter_backbuffer, flags); 3035 } 3036 else if (x < (endCapPos - (kProgressBarCapWidth * vc_uiscale))) 3037 { 3038 if (x2 < (endCapPos - (kProgressBarCapWidth * vc_uiscale))) 3039 w = x2 - x; 3040 else 3041 w = (endCapPos - (kProgressBarCapWidth * vc_uiscale)) - x; 3042 data = progressmeter_middle[vc_uiscale >= 2][onoff]; 3043 vc_blit_rect(ox + x, oy, x, w, 3044 (kProgressBarHeight * vc_uiscale), 3045 1, 3046 (kProgressBarWidth * vc_uiscale), 3047 data, vc_progressmeter_backbuffer, flags); 3048 } 3049 else 3050 { 3051 w = endCapPos - x; 3052 data = progressmeter_rightcap[vc_uiscale >= 2][onoff]; 3053 data += x - (endCapPos - (kProgressBarCapWidth * vc_uiscale)); 3054 vc_blit_rect(ox + x, oy, x, w, 3055 (kProgressBarHeight * vc_uiscale), 3056 (kProgressBarCapWidth * vc_uiscale), 3057 (kProgressBarWidth * vc_uiscale), 3058 data, vc_progressmeter_backbuffer, flags); 3059 } 3060 } 3061} 3062 3063extern void IORecordProgressBackbuffer(void * buffer, size_t size, uint32_t theme); 3064 3065static void 3066internal_enable_progressmeter(int new_value) 3067{ 3068 spl_t s; 3069 void * new_buffer; 3070 boolean_t stashBackbuffer; 3071 3072 stashBackbuffer = FALSE; 3073 new_buffer = NULL; 3074 if (new_value) 3075 { 3076 new_buffer = kalloc((kProgressBarWidth * vc_uiscale) 3077 * (kProgressBarHeight * vc_uiscale) * sizeof(int)); 3078 } 3079 3080 s = splhigh(); 3081 simple_lock(&vc_progress_lock); 3082 3083 if (kProgressMeterUser == new_value) 3084 { 3085 if (gc_enabled || !gc_acquired || !gc_graphics_boot 3086 || (kProgressMeterKernel == vc_progressmeter_enable)) new_value = vc_progressmeter_enable; 3087 } 3088 3089 if (new_value != vc_progressmeter_enable) 3090 { 3091 if (new_value) 3092 { 3093 if (kProgressMeterOff == vc_progressmeter_enable) 3094 { 3095 vc_progressmeter_backbuffer = new_buffer; 3096 vc_draw_progress_meter(kDataAlpha | kSave, 0, (kProgressBarWidth * vc_uiscale), 0); 3097 new_buffer = NULL; 3098 vc_progressmeter_drawn = 0; 3099 } 3100 vc_progressmeter_enable = new_value; 3101 } 3102 else if (vc_progressmeter_backbuffer) 3103 { 3104 if (kProgressMeterUser == vc_progressmeter_enable) 3105 { 3106 vc_draw_progress_meter(kDataBack, 0, (kProgressBarWidth * vc_uiscale), vc_progressmeter_drawn); 3107 } 3108 else stashBackbuffer = TRUE; 3109 new_buffer = vc_progressmeter_backbuffer; 3110 vc_progressmeter_backbuffer = NULL; 3111 vc_progressmeter_enable = FALSE; 3112 } 3113 } 3114 3115 simple_unlock(&vc_progress_lock); 3116 splx(s); 3117 3118 if (new_buffer) 3119 { 3120 if (stashBackbuffer) IORecordProgressBackbuffer(new_buffer, 3121 (kProgressBarWidth * vc_uiscale) 3122 * (kProgressBarHeight * vc_uiscale) 3123 * sizeof(int), 3124 vc_progress_white); 3125 kfree(new_buffer, (kProgressBarWidth * vc_uiscale) 3126 * (kProgressBarHeight * vc_uiscale) * sizeof(int)); 3127 } 3128} 3129 3130static void 3131internal_set_progressmeter(int new_value) 3132{ 3133 int x1, x3; 3134 int capRedraw; 3135 // 1 rounded fill, 0 square end 3136 int style = (0 == (2 & vc_progress_withmeter)); 3137 3138 if ((new_value < 0) || (new_value > kProgressMeterMax)) return; 3139 3140 if (vc_progressmeter_enable) 3141 { 3142 vc_progressmeter_value = new_value; 3143 3144 capRedraw = (style ? (kProgressBarCapWidth * vc_uiscale) : 0); 3145 x3 = (((kProgressBarWidth * vc_uiscale) - 2 * capRedraw) * vc_progressmeter_value) / kProgressMeterMax; 3146 x3 += (2 * capRedraw); 3147 3148 if (x3 > vc_progressmeter_drawn) 3149 { 3150 x1 = capRedraw; 3151 if (x1 > vc_progressmeter_drawn) x1 = vc_progressmeter_drawn; 3152 vc_draw_progress_meter(kDataAlpha, vc_progressmeter_drawn - x1, x3, x3); 3153 } 3154 else 3155 { 3156 vc_draw_progress_meter(kDataAlpha, x3 - capRedraw, vc_progressmeter_drawn, x3); 3157 } 3158 vc_progressmeter_drawn = x3; 3159 } 3160} 3161 3162void 3163vc_enable_progressmeter(int new_value) 3164{ 3165 if (kProgressMeterKernel == vc_progressmeter_enable) 3166 { 3167 vc_progressmeter_hold = new_value; 3168 } 3169 else 3170 { 3171 internal_enable_progressmeter(new_value ? kProgressMeterUser : kProgressMeterOff); 3172 } 3173} 3174 3175void 3176vc_set_progressmeter(int new_value) 3177{ 3178 spl_t s; 3179 3180 s = splhigh(); 3181 simple_lock(&vc_progress_lock); 3182 3183 if (vc_progressmeter_enable && (kProgressMeterKernel != vc_progressmeter_enable)) 3184 { 3185 internal_set_progressmeter((new_value * kProgressMeterMax) / 100); 3186 } 3187 3188 simple_unlock(&vc_progress_lock); 3189 splx(s); 3190} 3191 3192 3193