Print this page
NEX-16819 loader UEFI support
Includes work by Toomas Soome <tsoome@me.com>
Upstream commits:
    loader: pxe receive cleanup
    9475 libefi: Do not return only if ReceiveFilter
    installboot: should support efi system partition
    8931 boot1.efi: scan all display modes rather than
    loader: spinconsole updates
    loader: gfx experiment to try GOP Blt() function.
    sha1 build test
    loader: add sha1 hash calculation
    common/sha1: update for loader build
    loader: biosdisk rework
    uts: 32-bit kernel FB needs mapping in low memory
    uts: add diag-device
    uts: boot console mirror with diag-device
    uts: enable very early console on ttya
    kmdb: add diag-device as input/output device
    uts: test VGA memory exclusion from mapping
    uts: clear boot mapping and protect boot pages test
    uts: add dboot map debug printf
    uts: need to release FB pages in release_bootstrap()
    uts: add screenmap ioctl
    uts: update sys/queue.h
    loader: add illumos uts/common to include path
    loader: tem/gfx font cleanup
    loader: vbe checks
    uts: gfx_private set KD_TEXT when KD_RESETTEXT is
    uts: gfx 8-bit update
    loader: gfx 8-bit fix
    loader: always set media size from partition.
    uts: MB2 support for 32-bit kernel
    loader: x86 should have tem 80x25
    uts: x86 should have tem 80x25
    uts: font update
    loader: font update
    uts: tem attributes
    loader: tem.c comment added
    uts: use font module
    loader: add font module
    loader: build rules for new font setup
    uts: gfx_private update for new font structure
    uts: early boot update for new font structure
    uts: font update
    uts: font build rules update for new fonts
    uts: tem update to new font structure
    loader: module.c needs to include tem_impl.h
    uts: gfx_private 8x16 font rework
    uts: make font_lookup public
    loader: font rework
    uts: font rework
    9259 libefi: efi_alloc_and_read should check for PMBR
    uts: tem utf-8 support
    loader: implement tem utf-8 support
    loader: tem should be able to display UTF-8
    7784 uts: console input should support utf-8
    7796 uts: ldterm default to utf-8
    uts: do not reset serial console
    uts: set up colors even if tem is not console
    uts: add type for early boot properties
    uts: gfx_private experiment with drm and vga
    uts: gfx_private should use setmode drm callback.
    uts: identify FB types and set up gfx_private based
    loader: replace gop and vesa with framebuffer
    uts: boot needs simple tem to support mdb
    uts: boot_keyboard should emit esc sequences for
    uts: gfx_private FB showuld be written by line
    kmdb: set terminal window size
    uts: gfx_private needs to keep track of early boot FB
    pnglite: move pnglite to usr/src/common
    loader: gfx_fb
    ficl-sys: add gfx primitives
    loader: add illumos.png logo
    ficl: add fb-putimage
    loader: add png support
    loader: add alpha blending for gfx_fb
    loader: use term-drawrect for menu frame
    ficl: add simple gfx words
    uts: provide fb_info via fbgattr dev_specific array.
    uts: gfx_private add alpha blending
    uts: update sys/ascii.h
    uts: tem OSC support (incomplete)
    uts: implement env module support and use data from
    uts: tem get colors from early boot data
    loader: use crc32 from libstand (libz)
    loader: optimize for size
    loader: pass tem info to the environment
    loader: import tem for loader console
    loader: UEFI loader needs to set ISADIR based on
    loader: need UEFI32 support
    8918 loader.efi: add vesa edid support
    uts: tem_safe_pix_clear_prom_output() should only
    uts: tem_safe_pix_clear_entire_screen() should use
    uts: tem_safe_check_first_time() should query cursor
    uts: tem implement cls callback & visual_io v4
    uts: gfx_vgatext use block cursor for vgatext
    uts: gfx_private implement cls callback & visual_io
    uts: gfx_private bitmap framebuffer implementation
    uts: early start frame buffer console support
    uts: font functions should check the input char
    uts: font rendering should support 16/24/32bit depths
    uts: use smallest font as fallback default.
    uts: update terminal dimensions based on selected
    7834 uts: vgatext should use gfx_private
    uts: add spacing property to 8859-1.bdf
    terminfo: add underline for sun-color
    terminfo: sun-color has 16 colors
    uts: add font load callback type
    loader: do not repeat int13 calls with error 0x20 and
    8905 loader: add skein/edonr support
    8904 common/crypto: make skein and edonr loader
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Revert "NEX-16819 loader UEFI support"
This reverts commit ec06b9fc617b99234e538bf2e7e4d02a24993e0c.
Reverting due to failures in the zfs-tests and the sharefs-tests
NEX-16819 loader UEFI support
Includes work by Toomas Soome <tsoome@me.com>
Upstream commits:
    loader: pxe receive cleanup
    9475 libefi: Do not return only if ReceiveFilter
    installboot: should support efi system partition
    8931 boot1.efi: scan all display modes rather than
    loader: spinconsole updates
    loader: gfx experiment to try GOP Blt() function.
    sha1 build test
    loader: add sha1 hash calculation
    common/sha1: update for loader build
    loader: biosdisk rework
    uts: 32-bit kernel FB needs mapping in low memory
    uts: add diag-device
    uts: boot console mirror with diag-device
    uts: enable very early console on ttya
    kmdb: add diag-device as input/output device
    uts: test VGA memory exclusion from mapping
    uts: clear boot mapping and protect boot pages test
    uts: add dboot map debug printf
    uts: need to release FB pages in release_bootstrap()
    uts: add screenmap ioctl
    uts: update sys/queue.h
    loader: add illumos uts/common to include path
    loader: tem/gfx font cleanup
    loader: vbe checks
    uts: gfx_private set KD_TEXT when KD_RESETTEXT is
    uts: gfx 8-bit update
    loader: gfx 8-bit fix
    loader: always set media size from partition.
    uts: MB2 support for 32-bit kernel
    loader: x86 should have tem 80x25
    uts: x86 should have tem 80x25
    uts: font update
    loader: font update
    uts: tem attributes
    loader: tem.c comment added
    uts: use font module
    loader: add font module
    loader: build rules for new font setup
    uts: gfx_private update for new font structure
    uts: early boot update for new font structure
    uts: font update
    uts: font build rules update for new fonts
    uts: tem update to new font structure
    loader: module.c needs to include tem_impl.h
    uts: gfx_private 8x16 font rework
    uts: make font_lookup public
    loader: font rework
    uts: font rework
    libefi: efi_alloc_and_read should check for PMBR
    uts: tem utf-8 support
    loader: implement tem utf-8 support
    loader: tem should be able to display UTF-8
    7784 uts: console input should support utf-8
    7796 uts: ldterm default to utf-8
    uts: do not reset serial console
    uts: set up colors even if tem is not console
    uts: add type for early boot properties
    uts: gfx_private experiment with drm and vga
    uts: gfx_private should use setmode drm callback.
    uts: identify FB types and set up gfx_private based
    loader: replace gop and vesa with framebuffer
    uts: boot needs simple tem to support mdb
    uts: boot_keyboard should emit esc sequences for
    uts: gfx_private FB showuld be written by line
    kmdb: set terminal window size
    uts: gfx_private needs to keep track of early boot FB
    pnglite: move pnglite to usr/src/common
    loader: gfx_fb
    ficl-sys: add gfx primitives
    loader: add illumos.png logo
    ficl: add fb-putimage
    loader: add png support
    loader: add alpha blending for gfx_fb
    loader: use term-drawrect for menu frame
    ficl: add simple gfx words
    uts: provide fb_info via fbgattr dev_specific array.
    uts: gfx_private add alpha blending
    uts: update sys/ascii.h
    uts: tem OSC support (incomplete)
    uts: implement env module support and use data from
    uts: tem get colors from early boot data
    loader: use crc32 from libstand (libz)
    loader: optimize for size
    loader: pass tem info to the environment
    loader: import tem for loader console
    loader: UEFI loader needs to set ISADIR based on
    loader: need UEFI32 support
    8918 loader.efi: add vesa edid support
    uts: tem_safe_pix_clear_prom_output() should only
    uts: tem_safe_pix_clear_entire_screen() should use
    uts: tem_safe_check_first_time() should query cursor
    uts: tem implement cls callback & visual_io v4
    uts: gfx_vgatext use block cursor for vgatext
    uts: gfx_private implement cls callback & visual_io
    uts: gfx_private bitmap framebuffer implementation
    uts: early start frame buffer console support
    uts: font functions should check the input char
    uts: font rendering should support 16/24/32bit depths
    uts: use smallest font as fallback default.
    uts: update terminal dimensions based on selected
    7834 uts: vgatext should use gfx_private
    uts: add spacing property to 8859-1.bdf
    terminfo: add underline for sun-color
    terminfo: sun-color has 16 colors
    uts: add font load callback type
    loader: do not repeat int13 calls with error 0x20 and
    8905 loader: add skein/edonr support
    8904 common/crypto: make skein and edonr loader
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>


  70 #include <sys/sysmacros.h>
  71 #include <sys/mutex.h>
  72 #include <sys/note.h>
  73 #include <sys/t_lock.h>
  74 
  75 tem_safe_callbacks_t tem_safe_text_callbacks = {
  76         &tem_safe_text_display,
  77         &tem_safe_text_copy,
  78         &tem_safe_text_cursor,
  79         NULL,
  80         &tem_safe_text_cls
  81 };
  82 tem_safe_callbacks_t tem_safe_pix_callbacks = {
  83         &tem_safe_pix_display,
  84         &tem_safe_pix_copy,
  85         &tem_safe_pix_cursor,
  86         &tem_safe_pix_bit2pix,
  87         &tem_safe_pix_cls
  88 };
  89 
  90 
  91 static void     tem_safe_control(struct tem_vt_state *, uchar_t,
  92                         cred_t *, enum called_from);
  93 static void     tem_safe_setparam(struct tem_vt_state *, int, int);
  94 static void     tem_safe_selgraph(struct tem_vt_state *);
  95 static void     tem_safe_chkparam(struct tem_vt_state *, uchar_t,
  96                         cred_t *, enum called_from);
  97 static void     tem_safe_getparams(struct tem_vt_state *, uchar_t,
  98                         cred_t *, enum called_from);
  99 static void     tem_safe_outch(struct tem_vt_state *, uchar_t,
 100                         cred_t *, enum called_from);
 101 static void     tem_safe_parse(struct tem_vt_state *, uchar_t,
 102                         cred_t *, enum called_from);
 103 
 104 static void     tem_safe_new_line(struct tem_vt_state *,
 105                         cred_t *, enum called_from);
 106 static void     tem_safe_cr(struct tem_vt_state *);
 107 static void     tem_safe_lf(struct tem_vt_state *,
 108                         cred_t *, enum called_from);
 109 static void     tem_safe_send_data(struct tem_vt_state *, cred_t *,
 110                         enum called_from);
 111 static void     tem_safe_cls(struct tem_vt_state *,
 112                         cred_t *, enum called_from);
 113 static void     tem_safe_tab(struct tem_vt_state *,
 114                         cred_t *, enum called_from);
 115 static void     tem_safe_back_tab(struct tem_vt_state *,
 116                         cred_t *, enum called_from);
 117 static void     tem_safe_clear_tabs(struct tem_vt_state *, int);
 118 static void     tem_safe_set_tab(struct tem_vt_state *);
 119 static void     tem_safe_mv_cursor(struct tem_vt_state *, int, int,
 120                         cred_t *, enum called_from);
 121 static void     tem_safe_shift(struct tem_vt_state *, int, int,
 122                         cred_t *, enum called_from);
 123 static void     tem_safe_scroll(struct tem_vt_state *, int, int,
 124                         int, int, cred_t *, enum called_from);
 125 static void     tem_safe_clear_chars(struct tem_vt_state *tem,
 126                         int count, screen_pos_t row, screen_pos_t col,
 127                         cred_t *credp, enum called_from called_from);
 128 static void     tem_safe_copy_area(struct tem_vt_state *tem,
 129                         screen_pos_t s_col, screen_pos_t s_row,
 130                         screen_pos_t e_col, screen_pos_t e_row,
 131                         screen_pos_t t_col, screen_pos_t t_row,
 132                         cred_t *credp, enum called_from called_from);
 133 static void     tem_safe_image_display(struct tem_vt_state *, uchar_t *,
 134                         int, int, screen_pos_t, screen_pos_t,
 135                         cred_t *, enum called_from);
 136 static void     tem_safe_bell(struct tem_vt_state *tem,
 137                         enum called_from called_from);
 138 static void     tem_safe_pix_clear_prom_output(struct tem_vt_state *tem,
 139                         cred_t *credp, enum called_from called_from);

 140 
 141 static void     tem_safe_virtual_cls(struct tem_vt_state *, int, screen_pos_t,
 142                     screen_pos_t);
 143 static void     tem_safe_virtual_display(struct tem_vt_state *,
 144                     unsigned char *, int, screen_pos_t, screen_pos_t,
 145                     text_color_t, text_color_t);
 146 static void     tem_safe_virtual_copy(struct tem_vt_state *, screen_pos_t,
 147                     screen_pos_t, screen_pos_t, screen_pos_t,
 148                     screen_pos_t, screen_pos_t);
 149 static void     tem_safe_align_cursor(struct tem_vt_state *tem);
 150 static void     bit_to_pix4(struct tem_vt_state *tem, uchar_t c,
 151                     text_color_t fg_color, text_color_t bg_color);
 152 static void     bit_to_pix8(struct tem_vt_state *tem, uchar_t c,
 153                     text_color_t fg_color, text_color_t bg_color);
 154 static void     bit_to_pix24(struct tem_vt_state *tem, uchar_t c,
 155                     text_color_t fg_color, text_color_t bg_color);




 156 
 157 /* BEGIN CSTYLED */
 158 /*                                  Bk  Rd  Gr  Br  Bl  Mg  Cy  Wh */
 159 static text_color_t dim_xlate[] = {  1,  5,  3,  7,  2,  6,  4,  8 };
 160 static text_color_t brt_xlate[] = {  9, 13, 11, 15, 10, 14, 12,  0 };
 161 /* END CSTYLED */
 162 
 163 
 164 text_cmap_t cmap4_to_24 = {
 165 /* BEGIN CSTYLED */
 166 /* 0    1    2    3    4    5    6    7    8    9   10   11   12   13   14   15
 167   Wh+  Bk   Bl   Gr   Cy   Rd   Mg   Br   Wh   Bk+  Bl+  Gr+  Cy+  Rd+  Mg+  Yw */
 168   0xff,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x40,0x00,0x00,0x00,0xff,0xff,0xff,
 169   0xff,0x00,0x00,0x80,0x80,0x00,0x00,0x80,0x80,0x40,0x00,0xff,0xff,0x00,0x00,0xff,
 170   0xff,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x40,0xff,0x00,0xff,0x00,0xff,0x00
 171 /* END CSTYLED */
 172 };
 173 
 174 #define PIX4TO32(pix4) (uint32_t)(  \
 175     cmap4_to_24.red[pix4] << 16 |  \
 176     cmap4_to_24.green[pix4] << 8 | \
 177     cmap4_to_24.blue[pix4])
 178 
 179 #define INVERSE(ch) (ch ^ 0xff)
 180 
 181 #define tem_safe_callback_display       (*tems.ts_callbacks->tsc_display)
 182 #define tem_safe_callback_copy          (*tems.ts_callbacks->tsc_copy)
 183 #define tem_safe_callback_cursor        (*tems.ts_callbacks->tsc_cursor)
 184 #define tem_safe_callback_cls           (*tems.ts_callbacks->tsc_cls)
 185 #define tem_safe_callback_bit2pix(tem, c, fg, bg)       {               \
 186         ASSERT(tems.ts_callbacks->tsc_bit2pix != NULL);                      \
 187         (void) (*tems.ts_callbacks->tsc_bit2pix)((tem), (c), (fg), (bg));\
 188 }
 189 
 190 void
 191 tem_safe_check_first_time(
 192     struct tem_vt_state *tem,
 193     cred_t *credp,
 194     enum called_from called_from)
 195 {
 196         static int first_time = 1;
 197 
 198         ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
 199             called_from == CALLED_FROM_STANDALONE);
 200 
 201         /*
 202          * Realign the console cursor. We did this in tem_init().
 203          * However, drivers in the console stream may emit additional
 204          * messages before we are ready. This causes text overwrite
 205          * on the screen. This is a workaround.
 206          */
 207         if (!first_time)
 208                 return;
 209 
 210         first_time = 0;
 211         if (tems.ts_display_mode == VIS_TEXT) {
 212                 tem_safe_text_cursor(tem, VIS_GET_CURSOR, credp, called_from);


 213                 tem_safe_align_cursor(tem);
 214         }
 215 }
 216 
 217 /*
 218  * This entry point handles output requests from restricted contexts like
 219  * kmdb, where services like mutexes are not available. This function
 220  * is entered when OBP or when a kernel debugger (such as kmdb)
 221  * are generating console output.  In those cases, power management
 222  * concerns are handled by the abort sequence initiation (ie. when
 223  * the user hits L1+A or the equivalent to enter OBP or the debugger.).
 224  * It is also entered when the kernel is panicing.
 225  */
 226 void
 227 tem_safe_polled_write(
 228     tem_vt_state_t tem_arg,
 229     uchar_t *buf,
 230     int len)
 231 {
 232         struct tem_vt_state *tem = (struct tem_vt_state *)tem_arg;
 233 
 234 #ifdef  __lock_lint
 235         _NOTE(NO_COMPETING_THREADS_NOW)
 236         _NOTE(NO_COMPETING_THREADS_AS_SIDE_EFFECT)
 237 #endif
 238 
 239         if (!tem->tvs_initialized) {
 240                 return;
 241         }
 242 
 243         tem_safe_check_first_time(tem, kcred, CALLED_FROM_STANDALONE);
 244         tem_safe_terminal_emulate(tem, buf, len, NULL, CALLED_FROM_STANDALONE);
 245 }
 246 
 247 /* Process partial UTF-8 sequence. */
 248 static void
 249 tem_safe_input_partial(struct tem_vt_state *tem, cred_t *credp,
 250     enum called_from called_from)
 251 {
 252         int i;
 253         uint8_t c;
 254 
 255         if (tem->tvs_utf8_left == 0)
 256                 return;
 257 
 258         for (i = 0; i < sizeof (tem->tvs_utf8_partial); i++) {
 259                 c = (tem->tvs_utf8_partial >> (24 - (i << 3))) & 0xff;
 260                 if (c != 0) {
 261                         tem_safe_parse(tem, c, credp, called_from);
 262                 }
 263         }
 264         tem->tvs_utf8_left = 0;
 265         tem->tvs_utf8_partial = 0;
 266 }
 267 
 268 /*
 269  * Handle UTF-8 sequences.
 270  */
 271 static void
 272 tem_safe_input_byte(struct tem_vt_state *tem, uchar_t c, cred_t *credp,


 327                         if (b != 0) {           /* Four-byte sequence */
 328                                 v = b & 0x07;
 329                                 b = (u >> 16) & 0xff;
 330                                 v = (v << 6) | (b & 0x3f);
 331                                 b = (u >> 8) & 0xff;
 332                                 v = (v << 6) | (b & 0x3f);
 333                                 b = u & 0xff;
 334                                 v = (v << 6) | (b & 0x3f);
 335                         } else if ((b = (u >> 16) & 0xff) != 0) {
 336                                 v = b & 0x0f;       /* Three-byte sequence */
 337                                 b = (u >> 8) & 0xff;
 338                                 v = (v << 6) | (b & 0x3f);
 339                                 b = u & 0xff;
 340                                 v = (v << 6) | (b & 0x3f);
 341                         } else if ((b = (u >> 8) & 0xff) != 0) {
 342                                 v = b & 0x1f;       /* Two-byte sequence */
 343                                 b = u & 0xff;
 344                                 v = (v << 6) | (b & 0x3f);
 345                         }
 346 
 347                         /* Use '?' as replacement if needed. */
 348                         if (v > 0xff)
 349                                 v = '?';
 350                         tem_safe_parse(tem, v, credp, called_from);
 351                         tem->tvs_utf8_partial = 0;
 352                 }
 353                 return;
 354         }
 355         /* Anything left is illegal in UTF-8 sequence. */
 356         tem_safe_input_partial(tem, credp, called_from);
 357         tem_safe_parse(tem, c, credp, called_from);
 358 }
 359 
 360 /*
 361  * This is the main entry point into the terminal emulator.
 362  *
 363  * For each data message coming downstream, ANSI assumes that it is composed
 364  * of ASCII characters, which are treated as a byte-stream input to the
 365  * parsing state machine. All data is parsed immediately -- there is
 366  * no enqueing.
 367  */
 368 void
 369 tem_safe_terminal_emulate(


 429  * at a specific location on frame buffer* using the mechanism
 430  * appropriate for the system state being called from, quisced or
 431  * normal (ie. use polled I/O vs. layered ioctls).
 432  */
 433 static void
 434 tems_safe_cursor(struct vis_conscursor *pca, cred_t *credp,
 435     enum called_from called_from)
 436 {
 437         if (called_from == CALLED_FROM_STANDALONE)
 438                 tems.ts_fb_polledio->cursor(tems.ts_fb_polledio->arg, pca);
 439         else
 440                 tems_cursor_layered(pca, credp);
 441 }
 442 
 443 /*
 444  * send the appropriate control message or set state based on the
 445  * value of the control character ch
 446  */
 447 
 448 static void
 449 tem_safe_control(struct tem_vt_state *tem, uchar_t ch, cred_t *credp,
 450     enum called_from called_from)
 451 {
 452         tem->tvs_state = A_STATE_START;
 453         switch (ch) {
 454         case A_BEL:
 455                 tem_safe_bell(tem, called_from);
 456                 break;
 457 
 458         case A_BS:
 459                 tem_safe_mv_cursor(tem,
 460                     tem->tvs_c_cursor.row,
 461                     tem->tvs_c_cursor.col - 1,
 462                     credp, called_from);
 463                 break;
 464 
 465         case A_HT:
 466                 tem_safe_tab(tem, credp, called_from);
 467                 break;
 468 
 469         case A_NL:


 488                 tem_safe_cr(tem);
 489                 break;
 490 
 491         case A_ESC:
 492                 tem->tvs_state = A_STATE_ESC;
 493                 break;
 494 
 495         case A_CSI:
 496                 {
 497                         int i;
 498                         tem->tvs_curparam = 0;
 499                         tem->tvs_paramval = 0;
 500                         tem->tvs_gotparam = B_FALSE;
 501                         /* clear the parameters */
 502                         for (i = 0; i < TEM_MAXPARAMS; i++)
 503                                 tem->tvs_params[i] = -1;
 504                         tem->tvs_state = A_STATE_CSI;
 505                 }
 506                 break;
 507 













 508         case A_GS:
 509                 tem_safe_back_tab(tem, credp, called_from);
 510                 break;
 511 
 512         default:
 513                 break;
 514         }
 515 }
 516 
 517 
 518 /*
 519  * if parameters [0..count - 1] are not set, set them to the value
 520  * of newparam.
 521  */
 522 
 523 static void
 524 tem_safe_setparam(struct tem_vt_state *tem, int count, int newparam)
 525 {
 526         int i;
 527 


 548         do {
 549                 param = tem->tvs_params[count];
 550 
 551                 switch (param) {
 552                 case -1:
 553                 case 0:
 554                         /* reset to initial normal settings */
 555                         tem->tvs_fg_color = tems.ts_init_color.fg_color;
 556                         tem->tvs_bg_color = tems.ts_init_color.bg_color;
 557                         tem->tvs_flags = tems.ts_init_color.a_flags;
 558                         break;
 559 
 560                 case 1: /* Bold Intense */
 561                         tem->tvs_flags |= TEM_ATTR_BOLD;
 562                         break;
 563 
 564                 case 2: /* Faint Intense */
 565                         tem->tvs_flags &= ~TEM_ATTR_BOLD;
 566                         break;
 567 



 568                 case 5: /* Blink */
 569                         tem->tvs_flags |= TEM_ATTR_BLINK;
 570                         break;
 571 
 572                 case 7: /* Reverse video */
 573                         if (tem->tvs_flags & TEM_ATTR_SCREEN_REVERSE) {
 574                                 tem->tvs_flags &= ~TEM_ATTR_REVERSE;
 575                         } else {
 576                                 tem->tvs_flags |= TEM_ATTR_REVERSE;
 577                         }
 578                         break;
 579 




















 580                 case 30: /* black       (grey)          foreground */
 581                 case 31: /* red         (light red)     foreground */
 582                 case 32: /* green       (light green)   foreground */
 583                 case 33: /* brown       (yellow)        foreground */
 584                 case 34: /* blue        (light blue)    foreground */
 585                 case 35: /* magenta     (light magenta) foreground */
 586                 case 36: /* cyan        (light cyan)    foreground */
 587                 case 37: /* white       (bright white)  foreground */
 588                         tem->tvs_fg_color = param - 30;
 589                         tem->tvs_flags &= ~TEM_ATTR_BRIGHT_FG;
 590                         break;
 591 
 592                 case 39:
 593                         /*
 594                          * Reset the foreground colour and brightness.
 595                          */
 596                         tem->tvs_fg_color = tems.ts_init_color.fg_color;
 597                         if (tems.ts_init_color.a_flags & TEM_ATTR_BRIGHT_FG)
 598                                 tem->tvs_flags |= TEM_ATTR_BRIGHT_FG;
 599                         else


 646                         tem->tvs_bg_color = param - 100;
 647                         tem->tvs_flags |= TEM_ATTR_BRIGHT_BG;
 648                         break;
 649 
 650                 default:
 651                         break;
 652                 }
 653                 count++;
 654                 curparam--;
 655 
 656         } while (curparam > 0);
 657 }
 658 
 659 /*
 660  * perform the appropriate action for the escape sequence
 661  *
 662  * General rule:  This code does not validate the arguments passed.
 663  *                It assumes that the next lower level will do so.
 664  */
 665 static void
 666 tem_safe_chkparam(struct tem_vt_state *tem, uchar_t ch, cred_t *credp,
 667     enum called_from called_from)
 668 {
 669         int     i;
 670         int     row;
 671         int     col;
 672 
 673         ASSERT((called_from == CALLED_FROM_STANDALONE) ||
 674             MUTEX_HELD(&tem->tvs_lock));
 675 
 676         row = tem->tvs_c_cursor.row;
 677         col = tem->tvs_c_cursor.col;
 678 
 679         switch (ch) {
 680 
 681         case 'm': /* select terminal graphics mode */
 682                 tem_safe_send_data(tem, credp, called_from);
 683                 tem_safe_selgraph(tem);
 684                 break;
 685 
 686         case '@':               /* insert char */


 909                  *
 910                  * Restrict the count to a sane value to keep from
 911                  * looping for a long time.  There can't be more than one
 912                  * tab stop per column, so use that as a limit.
 913                  */
 914                 if (tem->tvs_params[0] > tems.ts_c_dimension.width)
 915                         tem->tvs_params[0] = tems.ts_c_dimension.width;
 916 
 917                 for (i = 0; i < tem->tvs_params[0]; i++)
 918                         tem_safe_back_tab(tem, credp, called_from);
 919                 break;
 920         }
 921         tem->tvs_state = A_STATE_START;
 922 }
 923 
 924 
 925 /*
 926  * Gather the parameters of an ANSI escape sequence
 927  */
 928 static void
 929 tem_safe_getparams(struct tem_vt_state *tem, uchar_t ch,
 930     cred_t *credp, enum called_from called_from)
 931 {
 932         ASSERT((called_from == CALLED_FROM_STANDALONE) ||
 933             MUTEX_HELD(&tem->tvs_lock));
 934 
 935         if (ch >= '0' && ch <= '9') {
 936                 tem->tvs_paramval = ((tem->tvs_paramval * 10) + (ch - '0'));
 937                 tem->tvs_gotparam = B_TRUE;  /* Remember got parameter */
 938                 return; /* Return immediately */
 939         } else if (tem->tvs_state == A_STATE_CSI_EQUAL ||
 940             tem->tvs_state == A_STATE_CSI_QMARK) {
 941                 tem->tvs_state = A_STATE_START;
 942         } else {
 943                 if (tem->tvs_curparam < TEM_MAXPARAMS) {
 944                         if (tem->tvs_gotparam) {
 945                                 /* get the parameter value */
 946                                 tem->tvs_params[tem->tvs_curparam] =
 947                                     tem->tvs_paramval;
 948                         }
 949                         tem->tvs_curparam++;
 950                 }
 951 
 952                 if (ch == ';') {
 953                         /* Restart parameter search */
 954                         tem->tvs_gotparam = B_FALSE;
 955                         tem->tvs_paramval = 0; /* No parame value yet */
 956                 } else {
 957                         /* Handle escape sequence */
 958                         tem_safe_chkparam(tem, ch, credp, called_from);
 959                 }
 960         }
 961 }
 962 
 963 /*























































 964  * Add character to internal buffer.
 965  * When its full, send it to the next layer.
 966  */
 967 
 968 static void
 969 tem_safe_outch(struct tem_vt_state *tem, uchar_t ch,
 970     cred_t *credp, enum called_from called_from)
 971 {



 972 
 973         ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
 974             called_from == CALLED_FROM_STANDALONE);
 975 
 976         /* buffer up the character until later */
 977 
 978         tem->tvs_outbuf[tem->tvs_outindex++] = ch;



 979         tem->tvs_c_cursor.col++;
 980         if (tem->tvs_c_cursor.col >= tems.ts_c_dimension.width) {
 981                 tem_safe_send_data(tem, credp, called_from);
 982                 tem_safe_new_line(tem, credp, called_from);
 983         }
 984 }
 985 
 986 static void
 987 tem_safe_new_line(struct tem_vt_state *tem,
 988     cred_t *credp, enum called_from called_from)
 989 {
 990         tem_safe_cr(tem);
 991         tem_safe_lf(tem, credp, called_from);
 992 }
 993 
 994 static void
 995 tem_safe_cr(struct tem_vt_state *tem)
 996 {
 997         tem->tvs_c_cursor.col = 0;
 998         tem_safe_align_cursor(tem);


1037             credp, called_from);
1038 
1039         if (tem->tvs_nscroll == 0) {
1040                 /* erase rest of cursor line */
1041                 tem_safe_clear_chars(tem,
1042                     tems.ts_c_dimension.width -
1043                     tem->tvs_c_cursor.col,
1044                     tem->tvs_c_cursor.row,
1045                     tem->tvs_c_cursor.col,
1046                     credp, called_from);
1047 
1048         }
1049 
1050         tem_safe_align_cursor(tem);
1051 }
1052 
1053 static void
1054 tem_safe_send_data(struct tem_vt_state *tem, cred_t *credp,
1055     enum called_from called_from)
1056 {
1057         text_color_t fg_color;
1058         text_color_t bg_color;
1059 
1060         ASSERT((called_from == CALLED_FROM_STANDALONE) ||
1061             MUTEX_HELD(&tem->tvs_lock));
1062 
1063         if (tem->tvs_outindex == 0) {
1064                 tem_safe_align_cursor(tem);
1065                 return;
1066         }
1067 
1068         tem_safe_get_color(tem, &fg_color, &bg_color, TEM_ATTR_REVERSE);
1069         tem_safe_virtual_display(tem,
1070             tem->tvs_outbuf, tem->tvs_outindex,
1071             tem->tvs_s_cursor.row, tem->tvs_s_cursor.col,
1072             fg_color, bg_color);
1073 
1074         if (tem->tvs_isactive) {
1075                 /*
1076                  * Call the primitive to render this data.
1077                  */
1078                 tem_safe_callback_display(tem,
1079                     tem->tvs_outbuf, tem->tvs_outindex,
1080                     tem->tvs_s_cursor.row, tem->tvs_s_cursor.col,
1081                     fg_color, bg_color,
1082                     credp, called_from);
1083         }
1084 
1085         tem->tvs_outindex = 0;
1086 
1087         tem_safe_align_cursor(tem);
1088 }
1089 
1090 
1091 /*
1092  * We have just done something to the current output point.  Reset the start
1093  * point for the buffered data in a_outbuf.  There shouldn't be any data
1094  * buffered yet.
1095  */
1096 static void
1097 tem_safe_align_cursor(struct tem_vt_state *tem)
1098 {
1099         tem->tvs_s_cursor.row = tem->tvs_c_cursor.row;
1100         tem->tvs_s_cursor.col = tem->tvs_c_cursor.col;
1101 }
1102 
1103 /*
1104  * State machine parser based on the current state and character input
1105  * major terminations are to control character or normal character
1106  */
1107 
1108 static void
1109 tem_safe_parse(struct tem_vt_state *tem, uchar_t ch,
1110     cred_t *credp, enum called_from called_from)
1111 {
1112         int     i;
1113 
1114         ASSERT((called_from == CALLED_FROM_STANDALONE) ||
1115             MUTEX_HELD(&tem->tvs_lock));
1116 
1117         if (tem->tvs_state == A_STATE_START) {       /* Normal state? */
1118                 if (ch == A_CSI || ch == A_ESC || ch < ' ') {
1119                         /* Control */
1120                         tem_safe_control(tem, ch, credp, called_from);
1121                 } else {
1122                         /* Display */
1123                         tem_safe_outch(tem, ch, credp, called_from);
1124                 }
1125                 return;
1126         }
1127 
1128         /* In <ESC> sequence */
1129         if (tem->tvs_state != A_STATE_ESC) { /* Need to get parameters? */





1130                 if (tem->tvs_state != A_STATE_CSI) {
1131                         tem_safe_getparams(tem, ch, credp, called_from);
1132                         return;
1133                 }
1134 
1135                 switch (ch) {
1136                 case '?':
1137                         tem->tvs_state = A_STATE_CSI_QMARK;
1138                         return;
1139                 case '=':
1140                         tem->tvs_state = A_STATE_CSI_EQUAL;
1141                         return;
1142                 case 's':
1143                         /*
1144                          * As defined below, this sequence
1145                          * saves the cursor.  However, Sun
1146                          * defines ESC[s as reset.  We resolved
1147                          * the conflict by selecting reset as it
1148                          * is exported in the termcap file for
1149                          * sun-mon, while the "save cursor"


1220                                 tem->tvs_nscroll = tems.ts_c_dimension.height;
1221                         if (tem->tvs_nscroll < 0)
1222                                 tem->tvs_nscroll = 1;
1223                         tem->tvs_state = A_STATE_START;
1224                         return;
1225                 default:
1226                         tem_safe_getparams(tem, ch, credp, called_from);
1227                         return;
1228                 }
1229         }
1230 
1231         /* Previous char was <ESC> */
1232         if (ch == '[') {
1233                 tem->tvs_curparam = 0;
1234                 tem->tvs_paramval = 0;
1235                 tem->tvs_gotparam = B_FALSE;
1236                 /* clear the parameters */
1237                 for (i = 0; i < TEM_MAXPARAMS; i++)
1238                         tem->tvs_params[i] = -1;
1239                 tem->tvs_state = A_STATE_CSI;








1240         } else if (ch == 'Q') { /* <ESC>Q ? */
1241                 tem->tvs_state = A_STATE_START;
1242         } else if (ch == 'C') { /* <ESC>C ? */
1243                 tem->tvs_state = A_STATE_START;
1244         } else {
1245                 tem->tvs_state = A_STATE_START;
1246                 if (ch == 'c') {
1247                         /* ESC c resets display */
1248                         tem_safe_reset_display(tem, credp, called_from,
1249                             B_TRUE, B_TRUE);
1250                 } else if (ch == 'H') {
1251                         /* ESC H sets a tab */
1252                         tem_safe_set_tab(tem);
1253                 } else if (ch == '7') {
1254                         /* ESC 7 Save Cursor position */
1255                         tem->tvs_r_cursor.row = tem->tvs_c_cursor.row;
1256                         tem->tvs_r_cursor.col = tem->tvs_c_cursor.col;
1257                 } else if (ch == '8') {
1258                         /* ESC 8 Restore Cursor position */
1259                         tem_safe_mv_cursor(tem, tem->tvs_r_cursor.row,


1380                 return;
1381 
1382         /*
1383          * Note that very large values of "count" could cause col+count
1384          * to overflow, so we check "count" independently.
1385          */
1386         if (count > tems.ts_c_dimension.width ||
1387             col + count > tems.ts_c_dimension.width)
1388                 count = tems.ts_c_dimension.width - col;
1389 
1390         tem_safe_virtual_cls(tem, count, row, col);
1391 
1392         if (!tem->tvs_isactive)
1393                 return;
1394 
1395         tem_safe_callback_cls(tem, count, row, col, credp, called_from);
1396 }
1397 
1398 /*ARGSUSED*/
1399 void
1400 tem_safe_text_display(struct tem_vt_state *tem, uchar_t *string,
1401     int count, screen_pos_t row, screen_pos_t col,
1402     text_color_t fg_color, text_color_t bg_color,
1403     cred_t *credp, enum called_from called_from)
1404 {
1405         struct vis_consdisplay da;


1406 
1407         ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
1408             called_from == CALLED_FROM_STANDALONE);
1409 
1410         da.data = string;
1411         da.width = (screen_size_t)count;
1412         da.row = row;
1413         da.col = col;
1414 
1415         da.fg_color = fg_color;
1416         da.bg_color = bg_color;
1417 
1418         tems_safe_display(&da, credp, called_from);


1419 }
1420 
1421 /*
1422  * This function is used to blit a rectangular color image,
1423  * unperturbed on the underlying framebuffer, to render
1424  * icons and pictures.  The data is a pixel pattern that
1425  * fills a rectangle bounded to the width and height parameters.
1426  * The color pixel data must to be pre-adjusted by the caller
1427  * for the current video depth.
1428  *
1429  * This function is unused now.
1430  */
1431 /*ARGSUSED*/
1432 static void
1433 tem_safe_image_display(struct tem_vt_state *tem, uchar_t *image,
1434     int height, int width, screen_pos_t row, screen_pos_t col,
1435     cred_t *credp, enum called_from called_from)
1436 {
1437         struct vis_consdisplay da;
1438 
1439         mutex_enter(&tems.ts_lock);
1440         mutex_enter(&tem->tvs_lock);
1441 
1442         da.data = image;
1443         da.width = (screen_size_t)width;
1444         da.height = (screen_size_t)height;
1445         da.row = row;
1446         da.col = col;
1447 
1448         tems_safe_display(&da, credp, called_from);
1449 
1450         mutex_exit(&tem->tvs_lock);
1451         mutex_exit(&tems.ts_lock);
1452 }
1453 
1454 
1455 /*ARGSUSED*/
1456 void
1457 tem_safe_text_copy(struct tem_vt_state *tem,
1458     screen_pos_t s_col, screen_pos_t s_row,
1459     screen_pos_t e_col, screen_pos_t e_row,
1460     screen_pos_t t_col, screen_pos_t t_row,
1461     cred_t *credp, enum called_from called_from)
1462 {
1463         struct vis_conscopy da;
1464 
1465         ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
1466             called_from == CALLED_FROM_STANDALONE);
1467 
1468         da.s_row = s_row;
1469         da.s_col = s_col;
1470         da.e_row = e_row;
1471         da.e_col = e_col;
1472         da.t_row = t_row;
1473         da.t_col = t_col;
1474 
1475         tems_safe_copy(&da, credp, called_from);
1476 }
1477 
1478 void
1479 tem_safe_text_cls(struct tem_vt_state *tem,
1480     int count, screen_pos_t row, screen_pos_t col, cred_t *credp,
1481     enum called_from called_from)
1482 {
1483         struct vis_consdisplay da;


1484 
1485         ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
1486             called_from == CALLED_FROM_STANDALONE);
1487 
1488         da.data = tems.ts_blank_line;
1489         da.width = (screen_size_t)count;
1490         da.row = row;
1491         da.col = col;
1492 
1493         tem_safe_get_color(tem, &da.fg_color, &da.bg_color,
1494             TEM_ATTR_SCREEN_REVERSE);
1495         tems_safe_display(&da, credp, called_from);










1496 }
1497 
1498 void
1499 tem_safe_pix_display(struct tem_vt_state *tem,
1500     uchar_t *string, int count,
1501     screen_pos_t row, screen_pos_t col,
1502     text_color_t fg_color, text_color_t bg_color,
1503     cred_t *credp, enum called_from called_from)
1504 {
1505         struct vis_consdisplay da;
1506         int     i;
1507 
1508         ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
1509             called_from == CALLED_FROM_STANDALONE);
1510 
1511         da.data = (uchar_t *)tem->tvs_pix_data;
1512         da.width = tems.ts_font.width;
1513         da.height = tems.ts_font.height;
1514         da.row = (row * da.height) + tems.ts_p_offset.y;
1515         da.col = (col * da.width) + tems.ts_p_offset.x;
1516 
1517         for (i = 0; i < count; i++) {
1518                 tem_safe_callback_bit2pix(tem, string[i], fg_color, bg_color);
1519                 tems_safe_display(&da, credp, called_from);
1520                 da.col += da.width;
1521         }
1522 }
1523 
1524 void
1525 tem_safe_pix_copy(struct tem_vt_state *tem,
1526     screen_pos_t s_col, screen_pos_t s_row,
1527     screen_pos_t e_col, screen_pos_t e_row,
1528     screen_pos_t t_col, screen_pos_t t_row,
1529     cred_t *credp,
1530     enum called_from called_from)
1531 {
1532         struct vis_conscopy ma;
1533         static boolean_t need_clear = B_TRUE;
1534 
1535         ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
1536             called_from == CALLED_FROM_STANDALONE);
1537 
1538         if (need_clear && tem->tvs_first_line > 0) {
1539                 /*
1540                  * Clear OBP output above our kernel console term
1541                  * when our kernel console term begins to scroll up,
1542                  * we hope it is user friendly.
1543                  * (Also see comments on tem_safe_pix_clear_prom_output)
1544                  *
1545                  * This is only one time call.
1546                  */
1547                 tem_safe_pix_clear_prom_output(tem, credp, called_from);
1548         }
1549         need_clear = B_FALSE;
1550 
1551         ma.s_row = s_row * tems.ts_font.height + tems.ts_p_offset.y;
1552         ma.e_row = (e_row + 1) * tems.ts_font.height + tems.ts_p_offset.y - 1;
1553         ma.t_row = t_row * tems.ts_font.height + tems.ts_p_offset.y;

1554 
1555         /*
1556          * Check if we're in process of clearing OBP's columns area,
1557          * which only happens when term scrolls up a whole line.
1558          */
1559         if (tem->tvs_first_line > 0 && t_row < s_row && t_col == 0 &&
1560             e_col == tems.ts_c_dimension.width - 1) {
1561                 /*
1562                  * We need to clear OBP's columns area outside our kernel
1563                  * console term. So that we set ma.e_col to entire row here.
1564                  */
1565                 ma.s_col = s_col * tems.ts_font.width;
1566                 ma.e_col = tems.ts_p_dimension.width - 1;
1567 
1568                 ma.t_col = t_col * tems.ts_font.width;
1569         } else {
1570                 ma.s_col = s_col * tems.ts_font.width + tems.ts_p_offset.x;
1571                 ma.e_col = (e_col + 1) * tems.ts_font.width +
1572                     tems.ts_p_offset.x - 1;
1573                 ma.t_col = t_col * tems.ts_font.width + tems.ts_p_offset.x;
1574         }
1575 
1576         tems_safe_copy(&ma, credp, called_from);
1577 
1578         if (tem->tvs_first_line > 0 && t_row < s_row) {
1579                 /* We have scrolled up (s_row - t_row) rows. */
1580                 tem->tvs_first_line -= (s_row - t_row);
1581                 if (tem->tvs_first_line <= 0) {
1582                         /* All OBP rows have been cleared. */
1583                         tem->tvs_first_line = 0;
1584                 }
1585         }
1586 
1587 }
1588 
1589 void
1590 tem_safe_pix_bit2pix(struct tem_vt_state *tem, unsigned char c,
1591     unsigned char fg, unsigned char bg)
1592 {
1593         void (*fp)(struct tem_vt_state *, unsigned char,

1594             unsigned char, unsigned char);
1595 

1596         switch (tems.ts_pdepth) {
1597         case 4:
1598                 fp = bit_to_pix4;
1599                 break;
1600         case 8:
1601                 fp = bit_to_pix8;
1602                 break;




1603         case 24:
1604         case 32:
1605                 fp = bit_to_pix24;






1606         }
1607 
1608         fp(tem, c, fg, bg);
1609 }
1610 
1611 
1612 /*
1613  * This function only clears count of columns in one row
1614  */
1615 void
1616 tem_safe_pix_cls(struct tem_vt_state *tem, int count,
1617     screen_pos_t row, screen_pos_t col, cred_t *credp,
1618     enum called_from called_from)
1619 {
1620         ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
1621             called_from == CALLED_FROM_STANDALONE);
1622 
1623         tem_safe_pix_cls_range(tem, row, 1, tems.ts_p_offset.y,
1624             col, count, tems.ts_p_offset.x, B_FALSE, credp, called_from);
1625 }
1626 
1627 /*
1628  * This function clears OBP output above our kernel console term area


1634  *      _________________________________
1635  *      |   _____________________       |  ---> OBP's bigger term window
1636  *      |   |                   |       |
1637  *      |___|                   |       |
1638  *      | | |                   |       |
1639  *      | | |                   |       |
1640  *      |_|_|___________________|_______|
1641  *        | |                   |          ---> first line
1642  *        | |___________________|---> our kernel console term window
1643  *        |
1644  *        |---> columns area to be cleared
1645  *
1646  * This function only takes care of the output above our kernel console term,
1647  * and tem_prom_scroll_up takes care of columns area outside of our kernel
1648  * console term.
1649  */
1650 static void
1651 tem_safe_pix_clear_prom_output(struct tem_vt_state *tem, cred_t *credp,
1652     enum called_from called_from)
1653 {
1654         int     nrows, ncols, width, height;
1655 
1656         ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
1657             called_from == CALLED_FROM_STANDALONE);
1658 
1659         width = tems.ts_font.width;
1660         height = tems.ts_font.height;

1661 
1662         nrows = (tems.ts_p_offset.y + (height - 1))/ height;
1663         ncols = (tems.ts_p_dimension.width + (width - 1))/ width;
1664 
1665         tem_safe_pix_cls_range(tem, 0, nrows, 0, 0, ncols, 0,

1666             B_FALSE, credp, called_from);
1667 }
1668 
1669 /*
1670  * clear the whole screen for pixel mode, just clear the
1671  * physical screen.
1672  */
1673 void
1674 tem_safe_pix_clear_entire_screen(struct tem_vt_state *tem, cred_t *credp,
1675     enum called_from called_from)
1676 {





1677         int     nrows, ncols, width, height;
1678 
1679         ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
1680             called_from == CALLED_FROM_STANDALONE);
1681 
1682         width = tems.ts_font.width;
1683         height = tems.ts_font.height;


1684 








1685         nrows = (tems.ts_p_dimension.height + (height - 1))/ height;
1686         ncols = (tems.ts_p_dimension.width + (width - 1))/ width;
1687 
1688         tem_safe_pix_cls_range(tem, 0, nrows, 0, 0, ncols, 0,
1689             B_FALSE, credp, called_from);
1690 
1691         /*
1692          * Since the whole screen is cleared, we don't need
1693          * to clear OBP output later.
1694          */
1695         if (tem->tvs_first_line > 0)
1696                 tem->tvs_first_line = 0;
1697 }
1698 
1699 /*
1700  * clear the whole screen, including the virtual screen buffer,
1701  * and reset the cursor to start point.
1702  */
1703 static void
1704 tem_safe_cls(struct tem_vt_state *tem,
1705     cred_t *credp, enum called_from called_from)
1706 {
1707         int     row;
1708 
1709         ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||


1987         ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
1988             called_from == CALLED_FROM_STANDALONE);
1989 
1990         ca.row = tem->tvs_c_cursor.row;
1991         ca.col = tem->tvs_c_cursor.col;
1992         ca.action = action;
1993 
1994         tems_safe_cursor(&ca, credp, called_from);
1995 
1996         if (action == VIS_GET_CURSOR) {
1997                 tem->tvs_c_cursor.row = ca.row;
1998                 tem->tvs_c_cursor.col = ca.col;
1999         }
2000 }
2001 
2002 void
2003 tem_safe_pix_cursor(struct tem_vt_state *tem, short action,
2004     cred_t *credp, enum called_from called_from)
2005 {
2006         struct vis_conscursor   ca;




2007 
2008         ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
2009             called_from == CALLED_FROM_STANDALONE);
2010 
2011         ca.row = tem->tvs_c_cursor.row * tems.ts_font.height +
2012             tems.ts_p_offset.y;
2013         ca.col = tem->tvs_c_cursor.col * tems.ts_font.width +
2014             tems.ts_p_offset.x;
2015         ca.width = tems.ts_font.width;
2016         ca.height = tems.ts_font.height;
2017         if (tems.ts_pdepth == 8 || tems.ts_pdepth == 4) {




























2018                 if (tem->tvs_flags & TEM_ATTR_REVERSE) {
2019                         ca.fg_color.mono = TEM_TEXT_WHITE;
2020                         ca.bg_color.mono = TEM_TEXT_BLACK;
2021                 } else {
2022                         ca.fg_color.mono = TEM_TEXT_BLACK;
2023                         ca.bg_color.mono = TEM_TEXT_WHITE;
2024                 }
2025         } else if (tems.ts_pdepth == 24 || tems.ts_pdepth == 32) {
2026                 if (tem->tvs_flags & TEM_ATTR_REVERSE) {
2027                         ca.fg_color.twentyfour[0] = TEM_TEXT_WHITE24_RED;
2028                         ca.fg_color.twentyfour[1] = TEM_TEXT_WHITE24_GREEN;
2029                         ca.fg_color.twentyfour[2] = TEM_TEXT_WHITE24_BLUE;
2030 
2031                         ca.bg_color.twentyfour[0] = TEM_TEXT_BLACK24_RED;
2032                         ca.bg_color.twentyfour[1] = TEM_TEXT_BLACK24_GREEN;
2033                         ca.bg_color.twentyfour[2] = TEM_TEXT_BLACK24_BLUE;
2034                 } else {
2035                         ca.fg_color.twentyfour[0] = TEM_TEXT_BLACK24_RED;
2036                         ca.fg_color.twentyfour[1] = TEM_TEXT_BLACK24_GREEN;
2037                         ca.fg_color.twentyfour[2] = TEM_TEXT_BLACK24_BLUE;
2038 
2039                         ca.bg_color.twentyfour[0] = TEM_TEXT_WHITE24_RED;
2040                         ca.bg_color.twentyfour[1] = TEM_TEXT_WHITE24_GREEN;
2041                         ca.bg_color.twentyfour[2] = TEM_TEXT_WHITE24_BLUE;
2042                 }











2043         }
2044 
2045         ca.action = action;
2046 
2047         tems_safe_cursor(&ca, credp, called_from);














2048 }
2049 
2050 static void
2051 bit_to_pix4(struct tem_vt_state *tem, uchar_t c, text_color_t fg_color,
2052     text_color_t bg_color)
2053 {
2054         uint8_t *dest = (uint8_t *)tem->tvs_pix_data;
2055         font_bit_to_pix4(&tems.ts_font, dest, c, fg_color, bg_color);
2056 }
2057 
2058 static void
2059 bit_to_pix8(struct tem_vt_state *tem, uchar_t c, text_color_t fg_color,
2060     text_color_t bg_color)
2061 {
2062         uint8_t *dest = (uint8_t *)tem->tvs_pix_data;



2063         font_bit_to_pix8(&tems.ts_font, dest, c, fg_color, bg_color);
2064 }
2065 
2066 static void
2067 bit_to_pix24(struct tem_vt_state *tem, uchar_t c, text_color_t fg_color4,
2068     text_color_t bg_color4)
2069 {
2070         uint32_t fg_color32, bg_color32, *dest;

2071 
2072         ASSERT(fg_color4 < 16 && bg_color4 < 16);
2073 

















2074         fg_color32 = PIX4TO32(fg_color4);
2075         bg_color32 = PIX4TO32(bg_color4);




2076 
2077         dest = (uint32_t *)tem->tvs_pix_data;
2078         font_bit_to_pix24(&tems.ts_font, dest, c, fg_color32, bg_color32);
2079 }
2080 
2081 static text_color_t
2082 ansi_bg_to_solaris(struct tem_vt_state *tem, int ansi)

2083 {
2084         if (tem->tvs_flags & TEM_ATTR_BRIGHT_BG)
2085                 return (brt_xlate[ansi]);
2086         else
2087                 return (dim_xlate[ansi]);
2088 }
2089 
2090 static text_color_t
2091 ansi_fg_to_solaris(struct tem_vt_state *tem, int ansi)
2092 {
2093         if (tem->tvs_flags & TEM_ATTR_BRIGHT_FG ||
2094             tem->tvs_flags & TEM_ATTR_BOLD) {
2095                 return (brt_xlate[ansi]);
2096         } else {
2097                 return (dim_xlate[ansi]);
2098         }



2099 }
2100 
2101 /*
2102  * flag: TEM_ATTR_SCREEN_REVERSE or TEM_ATTR_REVERSE
2103  */
2104 void
2105 tem_safe_get_color(struct tem_vt_state *tem, text_color_t *fg,
2106     text_color_t *bg, uint8_t flag)
2107 {
2108         if (tem->tvs_flags & flag) {
2109                 *fg = ansi_fg_to_solaris(tem,
2110                     tem->tvs_bg_color);
2111                 *bg = ansi_bg_to_solaris(tem,
2112                     tem->tvs_fg_color);
2113         } else {
2114                 *fg = ansi_fg_to_solaris(tem,
2115                     tem->tvs_fg_color);
2116                 *bg = ansi_bg_to_solaris(tem,
2117                     tem->tvs_bg_color);
2118         }





2119 }
2120 














2121 /*
2122  * Clear a rectangle of screen for pixel mode.
2123  *
2124  * arguments:
2125  *    row:      start row#
2126  *    nrows:    the number of rows to clear
2127  *    offset_y: the offset of height in pixels to begin clear
2128  *    col:      start col#
2129  *    ncols:    the number of cols to clear
2130  *    offset_x: the offset of width in pixels to begin clear
2131  *    scroll_up: whether this function is called during sroll up,
2132  *               which is called only once.
2133  */
2134 void
2135 tem_safe_pix_cls_range(struct tem_vt_state *tem,
2136     screen_pos_t row, int nrows, int offset_y,
2137     screen_pos_t col, int ncols, int offset_x,
2138     boolean_t sroll_up, cred_t *credp,
2139     enum called_from called_from)
2140 {
2141         struct vis_consdisplay da;
2142         int     i, j;
2143         int     row_add = 0;
2144         text_color_t fg_color;
2145         text_color_t bg_color;
2146 
2147         ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
2148             called_from == CALLED_FROM_STANDALONE);
2149 
2150         if (sroll_up)
2151                 row_add = tems.ts_c_dimension.height - 1;
2152 
2153         da.width = tems.ts_font.width;
2154         da.height = tems.ts_font.height;
2155 
2156         tem_safe_get_color(tem, &fg_color, &bg_color, TEM_ATTR_SCREEN_REVERSE);



2157 
2158         tem_safe_callback_bit2pix(tem, ' ', fg_color, bg_color);
2159         da.data = (uchar_t *)tem->tvs_pix_data;
2160 
2161         for (i = 0; i < nrows; i++, row++) {
2162                 da.row = (row + row_add) * da.height + offset_y;
2163                 da.col = col * da.width + offset_x;
2164                 for (j = 0; j < ncols; j++) {
2165                         tems_safe_display(&da, credp, called_from);
2166                         da.col += da.width;
2167                 }
2168         }
2169 }
2170 
2171 /*
2172  * virtual screen operations
2173  */
2174 static void
2175 tem_safe_virtual_display(struct tem_vt_state *tem, unsigned char *string,
2176     int count, screen_pos_t row, screen_pos_t col,
2177     text_color_t fg_color, text_color_t bg_color)
2178 {
2179         int i, width;
2180         unsigned char *addr;
2181         text_color_t *pfgcolor;
2182         text_color_t *pbgcolor;
2183 
2184         if (row < 0 || row >= tems.ts_c_dimension.height ||
2185             col < 0 || col >= tems.ts_c_dimension.width ||
2186             col + count > tems.ts_c_dimension.width)
2187                 return;
2188 
2189         width = tems.ts_c_dimension.width;
2190         addr = tem->tvs_screen_buf +  (row * width + col);
2191         pfgcolor = tem->tvs_fg_buf + (row * width + col);
2192         pbgcolor = tem->tvs_bg_buf + (row * width + col);
2193         for (i = 0; i < count; i++) {
2194                 *addr++ = string[i];
2195                 *pfgcolor++ = fg_color;
2196                 *pbgcolor++ = bg_color;
2197         }
2198 }
2199 
2200 static void
2201 i_virtual_copy(unsigned char *base,
2202     screen_pos_t s_col, screen_pos_t s_row,
2203     screen_pos_t e_col, screen_pos_t e_row,
2204     screen_pos_t t_col, screen_pos_t t_row)
2205 {
2206         unsigned char   *from;
2207         unsigned char   *to;
2208         int             cnt;
2209         screen_size_t chars_per_row;
2210         unsigned char   *to_row_start;
2211         unsigned char   *from_row_start;
2212         screen_size_t   rows_to_move;
2213         int             cols = tems.ts_c_dimension.width;
2214 
2215         chars_per_row = e_col - s_col + 1;
2216         rows_to_move = e_row - s_row + 1;
2217 
2218         to_row_start = base + ((t_row * cols) + t_col);
2219         from_row_start = base + ((s_row * cols) + s_col);
2220 
2221         if (to_row_start < from_row_start) {
2222                 while (rows_to_move-- > 0) {
2223                         to = to_row_start;
2224                         from = from_row_start;
2225                         to_row_start += cols;
2226                         from_row_start += cols;
2227                         for (cnt = chars_per_row; cnt-- > 0; )
2228                                 *to++ = *from++;
2229                 }
2230         } else {
2231                 /*


2258         int             cols = tems.ts_c_dimension.width;
2259 
2260         if (s_col < 0 || s_col >= cols ||
2261             s_row < 0 || s_row >= rows ||
2262             e_col < 0 || e_col >= cols ||
2263             e_row < 0 || e_row >= rows ||
2264             t_col < 0 || t_col >= cols ||
2265             t_row < 0 || t_row >= rows ||
2266             s_col > e_col ||
2267             s_row > e_row)
2268                 return;
2269 
2270         chars_per_row = e_col - s_col + 1;
2271         rows_to_move = e_row - s_row + 1;
2272 
2273         /* More sanity checks. */
2274         if (t_row + rows_to_move > rows ||
2275             t_col + chars_per_row > cols)
2276                 return;
2277 
2278         i_virtual_copy(tem->tvs_screen_buf, s_col, s_row,
2279             e_col, e_row, t_col, t_row);
2280 
2281         /* text_color_t is the same size as char */
2282         i_virtual_copy((unsigned char *)tem->tvs_fg_buf,
2283             s_col, s_row, e_col, e_row, t_col, t_row);
2284         i_virtual_copy((unsigned char *)tem->tvs_bg_buf,
2285             s_col, s_row, e_col, e_row, t_col, t_row);
2286 
2287 }
2288 
2289 static void
2290 tem_safe_virtual_cls(struct tem_vt_state *tem,
2291     int count, screen_pos_t row, screen_pos_t col)
2292 {
2293         text_color_t fg_color;
2294         text_color_t bg_color;

2295 
2296         tem_safe_get_color(tem, &fg_color, &bg_color, TEM_ATTR_SCREEN_REVERSE);
2297         tem_safe_virtual_display(tem, tems.ts_blank_line, count, row, col,
2298             fg_color, bg_color);





2299 }
2300 
2301 /*
2302  * only blank screen, not clear our screen buffer
2303  */
2304 void
2305 tem_safe_blank_screen(struct tem_vt_state *tem, cred_t *credp,
2306     enum called_from called_from)
2307 {
2308         int     row;
2309 
2310         ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
2311             called_from == CALLED_FROM_STANDALONE);
2312 
2313         if (tems.ts_display_mode == VIS_PIXEL) {
2314                 tem_safe_pix_clear_entire_screen(tem, credp, called_from);
2315                 return;
2316         }
2317 
2318         for (row = 0; row < tems.ts_c_dimension.height; row++) {
2319                 tem_safe_callback_cls(tem,
2320                     tems.ts_c_dimension.width,
2321                     row, 0, credp, called_from);
2322         }
2323 }
2324 
2325 /*
2326  * unblank screen with associated tem from its screen buffer
2327  */
2328 void
2329 tem_safe_unblank_screen(struct tem_vt_state *tem, cred_t *credp,
2330     enum called_from called_from)
2331 {
2332         text_color_t fg_color, fg_last;
2333         text_color_t bg_color, bg_last;
2334         size_t  tc_size = sizeof (text_color_t);
2335         int     row, col, count, col_start;
2336         int     width;
2337         unsigned char *buf;
2338 
2339         ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
2340             called_from == CALLED_FROM_STANDALONE);
2341 
2342         if (tems.ts_display_mode == VIS_PIXEL)
2343                 tem_safe_pix_clear_entire_screen(tem, credp, called_from);
2344 
2345         tem_safe_callback_cursor(tem, VIS_HIDE_CURSOR, credp, called_from);
2346 
2347         width = tems.ts_c_dimension.width;
2348 
2349         /*
2350          * Display data in tvs_screen_buf to the actual framebuffer in a
2351          * row by row way.
2352          * When dealing with one row, output data with the same foreground
2353          * and background color all together.
2354          */
2355         for (row = 0; row < tems.ts_c_dimension.height; row++) {
2356                 buf = tem->tvs_screen_buf + (row * width);
2357                 count = col_start = 0;
2358                 for (col = 0; col < width; col++) {
2359                         fg_color =
2360                             tem->tvs_fg_buf[(row * width + col) * tc_size];
2361                         bg_color =
2362                             tem->tvs_bg_buf[(row * width + col) * tc_size];
2363                         if (col == 0) {
2364                                 fg_last = fg_color;
2365                                 bg_last = bg_color;
2366                         }
2367 
2368                         if ((fg_color != fg_last) || (bg_color != bg_last)) {
2369                                 /*
2370                                  * Call the primitive to render this data.
2371                                  */
2372                                 tem_safe_callback_display(tem,
2373                                     buf, count, row, col_start,
2374                                     fg_last, bg_last, credp, called_from);
2375                                 buf += count;
2376                                 count = 1;
2377                                 col_start = col;
2378                                 fg_last = fg_color;
2379                                 bg_last = bg_color;
2380                         } else {
2381                                 count++;
2382                         }
2383                 }
2384 
2385                 if (col_start == (width - 1))
2386                         continue;
2387 
2388                 /*
2389                  * Call the primitive to render this data.
2390                  */
2391                 tem_safe_callback_display(tem,
2392                     buf, count, row, col_start,
2393                     fg_last, bg_last, credp, called_from);
2394         }
2395 
2396         tem_safe_callback_cursor(tem, VIS_DISPLAY_CURSOR, credp, called_from);
2397 }


  70 #include <sys/sysmacros.h>
  71 #include <sys/mutex.h>
  72 #include <sys/note.h>
  73 #include <sys/t_lock.h>
  74 
  75 tem_safe_callbacks_t tem_safe_text_callbacks = {
  76         &tem_safe_text_display,
  77         &tem_safe_text_copy,
  78         &tem_safe_text_cursor,
  79         NULL,
  80         &tem_safe_text_cls
  81 };
  82 tem_safe_callbacks_t tem_safe_pix_callbacks = {
  83         &tem_safe_pix_display,
  84         &tem_safe_pix_copy,
  85         &tem_safe_pix_cursor,
  86         &tem_safe_pix_bit2pix,
  87         &tem_safe_pix_cls
  88 };
  89 
  90 static void     tem_safe_control(struct tem_vt_state *, tem_char_t,

  91                         cred_t *, enum called_from);
  92 static void     tem_safe_setparam(struct tem_vt_state *, int, int);
  93 static void     tem_safe_selgraph(struct tem_vt_state *);
  94 static void     tem_safe_chkparam(struct tem_vt_state *, tem_char_t,
  95                         cred_t *, enum called_from);
  96 static void     tem_safe_getparams(struct tem_vt_state *, tem_char_t,
  97                         cred_t *, enum called_from);
  98 static void     tem_safe_outch(struct tem_vt_state *, tem_char_t,
  99                         cred_t *, enum called_from);
 100 static void     tem_safe_parse(struct tem_vt_state *, tem_char_t,
 101                         cred_t *, enum called_from);
 102 
 103 static void     tem_safe_new_line(struct tem_vt_state *,
 104                         cred_t *, enum called_from);
 105 static void     tem_safe_cr(struct tem_vt_state *);
 106 static void     tem_safe_lf(struct tem_vt_state *,
 107                         cred_t *, enum called_from);
 108 static void     tem_safe_send_data(struct tem_vt_state *, cred_t *,
 109                         enum called_from);
 110 static void     tem_safe_cls(struct tem_vt_state *,
 111                         cred_t *, enum called_from);
 112 static void     tem_safe_tab(struct tem_vt_state *,
 113                         cred_t *, enum called_from);
 114 static void     tem_safe_back_tab(struct tem_vt_state *,
 115                         cred_t *, enum called_from);
 116 static void     tem_safe_clear_tabs(struct tem_vt_state *, int);
 117 static void     tem_safe_set_tab(struct tem_vt_state *);
 118 static void     tem_safe_mv_cursor(struct tem_vt_state *, int, int,
 119                         cred_t *, enum called_from);
 120 static void     tem_safe_shift(struct tem_vt_state *, int, int,
 121                         cred_t *, enum called_from);
 122 static void     tem_safe_scroll(struct tem_vt_state *, int, int,
 123                         int, int, cred_t *, enum called_from);
 124 static void     tem_safe_clear_chars(struct tem_vt_state *tem,
 125                         int count, screen_pos_t row, screen_pos_t col,
 126                         cred_t *credp, enum called_from called_from);
 127 static void     tem_safe_copy_area(struct tem_vt_state *tem,
 128                         screen_pos_t s_col, screen_pos_t s_row,
 129                         screen_pos_t e_col, screen_pos_t e_row,
 130                         screen_pos_t t_col, screen_pos_t t_row,
 131                         cred_t *credp, enum called_from called_from);
 132 static void     tem_safe_image_display(struct tem_vt_state *, uchar_t *,
 133                         int, int, screen_pos_t, screen_pos_t,
 134                         cred_t *, enum called_from);
 135 static void     tem_safe_bell(struct tem_vt_state *tem,
 136                         enum called_from called_from);
 137 static void     tem_safe_pix_clear_prom_output(struct tem_vt_state *tem,
 138                         cred_t *credp, enum called_from called_from);
 139 static void     tem_safe_get_color(text_color_t *, text_color_t *, term_char_t);
 140 
 141 static void     tem_safe_virtual_cls(struct tem_vt_state *, int, screen_pos_t,
 142                     screen_pos_t);
 143 static void     tem_safe_virtual_display(struct tem_vt_state *,
 144                     term_char_t *, int, screen_pos_t, screen_pos_t);

 145 static void     tem_safe_virtual_copy(struct tem_vt_state *, screen_pos_t,
 146                     screen_pos_t, screen_pos_t, screen_pos_t,
 147                     screen_pos_t, screen_pos_t);
 148 static void     tem_safe_align_cursor(struct tem_vt_state *tem);
 149 static void     bit_to_pix4(struct tem_vt_state *tem, tem_char_t c,
 150                     text_color_t fg_color, text_color_t bg_color);
 151 static void     bit_to_pix8(struct tem_vt_state *tem, tem_char_t c,
 152                     text_color_t fg_color, text_color_t bg_color);
 153 static void     bit_to_pix16(struct tem_vt_state *tem, tem_char_t c,
 154                     text_color_t fg_color, text_color_t bg_color);
 155 static void     bit_to_pix24(struct tem_vt_state *tem, tem_char_t c,
 156                     text_color_t fg_color, text_color_t bg_color);
 157 static void     bit_to_pix32(struct tem_vt_state *tem, tem_char_t c,
 158                     text_color_t fg_color, text_color_t bg_color);
 159 

















 160 #define PIX4TO32(pix4) (uint32_t)(  \
 161     cmap4_to_24.red[pix4] << 16 |  \
 162     cmap4_to_24.green[pix4] << 8 | \
 163     cmap4_to_24.blue[pix4])
 164 
 165 #define INVERSE(ch) (ch ^ 0xff)
 166 
 167 #define tem_safe_callback_display       (*tems.ts_callbacks->tsc_display)
 168 #define tem_safe_callback_copy          (*tems.ts_callbacks->tsc_copy)
 169 #define tem_safe_callback_cursor        (*tems.ts_callbacks->tsc_cursor)
 170 #define tem_safe_callback_cls           (*tems.ts_callbacks->tsc_cls)
 171 #define tem_safe_callback_bit2pix(tem, c)       {               \
 172         ASSERT(tems.ts_callbacks->tsc_bit2pix != NULL);                      \
 173         (void) (*tems.ts_callbacks->tsc_bit2pix)((tem), (c));\
 174 }
 175 
 176 void
 177 tem_safe_check_first_time(
 178     struct tem_vt_state *tem,
 179     cred_t *credp,
 180     enum called_from called_from)
 181 {
 182         static int first_time = 1;
 183 
 184         ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
 185             called_from == CALLED_FROM_STANDALONE);
 186 
 187         /*
 188          * Realign the console cursor. We did this in tem_init().
 189          * However, drivers in the console stream may emit additional
 190          * messages before we are ready. This causes text overwrite
 191          * on the screen. This is a workaround.
 192          */
 193         if (!first_time)
 194                 return;
 195 
 196         first_time = 0;
 197         if (tems.ts_display_mode == VIS_TEXT)
 198                 tem_safe_text_cursor(tem, VIS_GET_CURSOR, credp, called_from);
 199         else
 200                 tem_safe_pix_cursor(tem, VIS_GET_CURSOR, credp, called_from);
 201         tem_safe_align_cursor(tem);

 202 }
 203 
 204 /*
 205  * This entry point handles output requests from restricted contexts like
 206  * kmdb, where services like mutexes are not available. This function
 207  * is entered when OBP or when a kernel debugger (such as kmdb)
 208  * are generating console output.  In those cases, power management
 209  * concerns are handled by the abort sequence initiation (ie. when
 210  * the user hits L1+A or the equivalent to enter OBP or the debugger.).
 211  * It is also entered when the kernel is panicing.
 212  */
 213 void
 214 tem_safe_polled_write(
 215     tem_vt_state_t tem_arg,
 216     uchar_t *buf,
 217     int len)
 218 {
 219         struct tem_vt_state *tem = (struct tem_vt_state *)tem_arg;
 220 
 221 #ifdef  __lock_lint
 222         _NOTE(NO_COMPETING_THREADS_NOW)
 223         _NOTE(NO_COMPETING_THREADS_AS_SIDE_EFFECT)
 224 #endif
 225 
 226         if (!tem->tvs_initialized) {
 227                 return;
 228         }
 229 
 230         tem_safe_check_first_time(tem, kcred, CALLED_FROM_STANDALONE);
 231         tem_safe_terminal_emulate(tem, buf, len, NULL, CALLED_FROM_STANDALONE);
 232 }
 233 
 234 /* Process partial UTF-8 sequence. */
 235 static void
 236 tem_safe_input_partial(struct tem_vt_state *tem, cred_t *credp,
 237     enum called_from called_from)
 238 {
 239         unsigned i;
 240         uint8_t c;
 241 
 242         if (tem->tvs_utf8_left == 0)
 243                 return;
 244 
 245         for (i = 0; i < sizeof (tem->tvs_utf8_partial); i++) {
 246                 c = (tem->tvs_utf8_partial >> (24 - (i << 3))) & 0xff;
 247                 if (c != 0) {
 248                         tem_safe_parse(tem, c, credp, called_from);
 249                 }
 250         }
 251         tem->tvs_utf8_left = 0;
 252         tem->tvs_utf8_partial = 0;
 253 }
 254 
 255 /*
 256  * Handle UTF-8 sequences.
 257  */
 258 static void
 259 tem_safe_input_byte(struct tem_vt_state *tem, uchar_t c, cred_t *credp,


 314                         if (b != 0) {           /* Four-byte sequence */
 315                                 v = b & 0x07;
 316                                 b = (u >> 16) & 0xff;
 317                                 v = (v << 6) | (b & 0x3f);
 318                                 b = (u >> 8) & 0xff;
 319                                 v = (v << 6) | (b & 0x3f);
 320                                 b = u & 0xff;
 321                                 v = (v << 6) | (b & 0x3f);
 322                         } else if ((b = (u >> 16) & 0xff) != 0) {
 323                                 v = b & 0x0f;       /* Three-byte sequence */
 324                                 b = (u >> 8) & 0xff;
 325                                 v = (v << 6) | (b & 0x3f);
 326                                 b = u & 0xff;
 327                                 v = (v << 6) | (b & 0x3f);
 328                         } else if ((b = (u >> 8) & 0xff) != 0) {
 329                                 v = b & 0x1f;       /* Two-byte sequence */
 330                                 b = u & 0xff;
 331                                 v = (v << 6) | (b & 0x3f);
 332                         }
 333 



 334                         tem_safe_parse(tem, v, credp, called_from);
 335                         tem->tvs_utf8_partial = 0;
 336                 }
 337                 return;
 338         }
 339         /* Anything left is illegal in UTF-8 sequence. */
 340         tem_safe_input_partial(tem, credp, called_from);
 341         tem_safe_parse(tem, c, credp, called_from);
 342 }
 343 
 344 /*
 345  * This is the main entry point into the terminal emulator.
 346  *
 347  * For each data message coming downstream, ANSI assumes that it is composed
 348  * of ASCII characters, which are treated as a byte-stream input to the
 349  * parsing state machine. All data is parsed immediately -- there is
 350  * no enqueing.
 351  */
 352 void
 353 tem_safe_terminal_emulate(


 413  * at a specific location on frame buffer* using the mechanism
 414  * appropriate for the system state being called from, quisced or
 415  * normal (ie. use polled I/O vs. layered ioctls).
 416  */
 417 static void
 418 tems_safe_cursor(struct vis_conscursor *pca, cred_t *credp,
 419     enum called_from called_from)
 420 {
 421         if (called_from == CALLED_FROM_STANDALONE)
 422                 tems.ts_fb_polledio->cursor(tems.ts_fb_polledio->arg, pca);
 423         else
 424                 tems_cursor_layered(pca, credp);
 425 }
 426 
 427 /*
 428  * send the appropriate control message or set state based on the
 429  * value of the control character ch
 430  */
 431 
 432 static void
 433 tem_safe_control(struct tem_vt_state *tem, tem_char_t ch, cred_t *credp,
 434     enum called_from called_from)
 435 {
 436         tem->tvs_state = A_STATE_START;
 437         switch (ch) {
 438         case A_BEL:
 439                 tem_safe_bell(tem, called_from);
 440                 break;
 441 
 442         case A_BS:
 443                 tem_safe_mv_cursor(tem,
 444                     tem->tvs_c_cursor.row,
 445                     tem->tvs_c_cursor.col - 1,
 446                     credp, called_from);
 447                 break;
 448 
 449         case A_HT:
 450                 tem_safe_tab(tem, credp, called_from);
 451                 break;
 452 
 453         case A_NL:


 472                 tem_safe_cr(tem);
 473                 break;
 474 
 475         case A_ESC:
 476                 tem->tvs_state = A_STATE_ESC;
 477                 break;
 478 
 479         case A_CSI:
 480                 {
 481                         int i;
 482                         tem->tvs_curparam = 0;
 483                         tem->tvs_paramval = 0;
 484                         tem->tvs_gotparam = B_FALSE;
 485                         /* clear the parameters */
 486                         for (i = 0; i < TEM_MAXPARAMS; i++)
 487                                 tem->tvs_params[i] = -1;
 488                         tem->tvs_state = A_STATE_CSI;
 489                 }
 490                 break;
 491 
 492         case A_OSC:
 493                 {
 494                         int i;
 495                         tem->tvs_curparam = 0;
 496                         tem->tvs_paramval = 0;
 497                         tem->tvs_gotparam = B_FALSE;
 498                         /* clear the parameters */
 499                         for (i = 0; i < TEM_MAXPARAMS; i++)
 500                                 tem->tvs_params[i] = -1;
 501                         tem->tvs_state = A_STATE_OSC;
 502                 }
 503                 break;
 504 
 505         case A_GS:
 506                 tem_safe_back_tab(tem, credp, called_from);
 507                 break;
 508 
 509         default:
 510                 break;
 511         }
 512 }
 513 
 514 
 515 /*
 516  * if parameters [0..count - 1] are not set, set them to the value
 517  * of newparam.
 518  */
 519 
 520 static void
 521 tem_safe_setparam(struct tem_vt_state *tem, int count, int newparam)
 522 {
 523         int i;
 524 


 545         do {
 546                 param = tem->tvs_params[count];
 547 
 548                 switch (param) {
 549                 case -1:
 550                 case 0:
 551                         /* reset to initial normal settings */
 552                         tem->tvs_fg_color = tems.ts_init_color.fg_color;
 553                         tem->tvs_bg_color = tems.ts_init_color.bg_color;
 554                         tem->tvs_flags = tems.ts_init_color.a_flags;
 555                         break;
 556 
 557                 case 1: /* Bold Intense */
 558                         tem->tvs_flags |= TEM_ATTR_BOLD;
 559                         break;
 560 
 561                 case 2: /* Faint Intense */
 562                         tem->tvs_flags &= ~TEM_ATTR_BOLD;
 563                         break;
 564 
 565                 case 4: /* Underline */
 566                         tem->tvs_flags |= TEM_ATTR_UNDERLINE;
 567                         break;
 568                 case 5: /* Blink */
 569                         tem->tvs_flags |= TEM_ATTR_BLINK;
 570                         break;
 571 
 572                 case 7: /* Reverse video */
 573                         if (tem->tvs_flags & TEM_ATTR_SCREEN_REVERSE) {
 574                                 tem->tvs_flags &= ~TEM_ATTR_REVERSE;
 575                         } else {
 576                                 tem->tvs_flags |= TEM_ATTR_REVERSE;
 577                         }
 578                         break;
 579 
 580                 case 22: /* Remove Bold */
 581                         tem->tvs_flags &= ~TEM_ATTR_BOLD;
 582                         break;
 583 
 584                 case 24: /* Remove Underline */
 585                         tem->tvs_flags &= ~TEM_ATTR_UNDERLINE;
 586                         break;
 587 
 588                 case 25: /* Remove Blink */
 589                         tem->tvs_flags &= ~TEM_ATTR_BLINK;
 590                         break;
 591 
 592                 case 27: /* Remove Reverse */
 593                         if (tem->tvs_flags & TEM_ATTR_SCREEN_REVERSE) {
 594                                 tem->tvs_flags |= TEM_ATTR_REVERSE;
 595                         } else {
 596                                 tem->tvs_flags &= ~TEM_ATTR_REVERSE;
 597                         }
 598                         break;
 599 
 600                 case 30: /* black       (grey)          foreground */
 601                 case 31: /* red         (light red)     foreground */
 602                 case 32: /* green       (light green)   foreground */
 603                 case 33: /* brown       (yellow)        foreground */
 604                 case 34: /* blue        (light blue)    foreground */
 605                 case 35: /* magenta     (light magenta) foreground */
 606                 case 36: /* cyan        (light cyan)    foreground */
 607                 case 37: /* white       (bright white)  foreground */
 608                         tem->tvs_fg_color = param - 30;
 609                         tem->tvs_flags &= ~TEM_ATTR_BRIGHT_FG;
 610                         break;
 611 
 612                 case 39:
 613                         /*
 614                          * Reset the foreground colour and brightness.
 615                          */
 616                         tem->tvs_fg_color = tems.ts_init_color.fg_color;
 617                         if (tems.ts_init_color.a_flags & TEM_ATTR_BRIGHT_FG)
 618                                 tem->tvs_flags |= TEM_ATTR_BRIGHT_FG;
 619                         else


 666                         tem->tvs_bg_color = param - 100;
 667                         tem->tvs_flags |= TEM_ATTR_BRIGHT_BG;
 668                         break;
 669 
 670                 default:
 671                         break;
 672                 }
 673                 count++;
 674                 curparam--;
 675 
 676         } while (curparam > 0);
 677 }
 678 
 679 /*
 680  * perform the appropriate action for the escape sequence
 681  *
 682  * General rule:  This code does not validate the arguments passed.
 683  *                It assumes that the next lower level will do so.
 684  */
 685 static void
 686 tem_safe_chkparam(struct tem_vt_state *tem, tem_char_t ch, cred_t *credp,
 687     enum called_from called_from)
 688 {
 689         int     i;
 690         int     row;
 691         int     col;
 692 
 693         ASSERT((called_from == CALLED_FROM_STANDALONE) ||
 694             MUTEX_HELD(&tem->tvs_lock));
 695 
 696         row = tem->tvs_c_cursor.row;
 697         col = tem->tvs_c_cursor.col;
 698 
 699         switch (ch) {
 700 
 701         case 'm': /* select terminal graphics mode */
 702                 tem_safe_send_data(tem, credp, called_from);
 703                 tem_safe_selgraph(tem);
 704                 break;
 705 
 706         case '@':               /* insert char */


 929                  *
 930                  * Restrict the count to a sane value to keep from
 931                  * looping for a long time.  There can't be more than one
 932                  * tab stop per column, so use that as a limit.
 933                  */
 934                 if (tem->tvs_params[0] > tems.ts_c_dimension.width)
 935                         tem->tvs_params[0] = tems.ts_c_dimension.width;
 936 
 937                 for (i = 0; i < tem->tvs_params[0]; i++)
 938                         tem_safe_back_tab(tem, credp, called_from);
 939                 break;
 940         }
 941         tem->tvs_state = A_STATE_START;
 942 }
 943 
 944 
 945 /*
 946  * Gather the parameters of an ANSI escape sequence
 947  */
 948 static void
 949 tem_safe_getparams(struct tem_vt_state *tem, tem_char_t ch,
 950     cred_t *credp, enum called_from called_from)
 951 {
 952         ASSERT((called_from == CALLED_FROM_STANDALONE) ||
 953             MUTEX_HELD(&tem->tvs_lock));
 954 
 955         if (ch >= '0' && ch <= '9') {
 956                 tem->tvs_paramval = ((tem->tvs_paramval * 10) + (ch - '0'));
 957                 tem->tvs_gotparam = B_TRUE;  /* Remember got parameter */
 958                 return; /* Return immediately */
 959         } else if (tem->tvs_state == A_STATE_CSI_EQUAL ||
 960             tem->tvs_state == A_STATE_CSI_QMARK) {
 961                 tem->tvs_state = A_STATE_START;
 962         } else {
 963                 if (tem->tvs_curparam < TEM_MAXPARAMS) {
 964                         if (tem->tvs_gotparam) {
 965                                 /* get the parameter value */
 966                                 tem->tvs_params[tem->tvs_curparam] =
 967                                     tem->tvs_paramval;
 968                         }
 969                         tem->tvs_curparam++;
 970                 }
 971 
 972                 if (ch == ';') {
 973                         /* Restart parameter search */
 974                         tem->tvs_gotparam = B_FALSE;
 975                         tem->tvs_paramval = 0; /* No parame value yet */
 976                 } else {
 977                         /* Handle escape sequence */
 978                         tem_safe_chkparam(tem, ch, credp, called_from);
 979                 }
 980         }
 981 }
 982 
 983 /*
 984  * Gather the OSC string.
 985  * OSC Ps ; Pt ST
 986  * OSC Ps ; Pt BEL
 987  * Ps is number sequence identifying the function. We only support
 988  * Ps = 4 and Ps = 104.
 989  * Quite obviously this is nowhere close to be done;)
 990  */
 991 /* ARGSUSED */
 992 static void
 993 tem_safe_get_oscstring(struct tem_vt_state *tem, uchar_t ch,
 994     cred_t *credp __unused, enum called_from called_from)
 995 {
 996         ASSERT((called_from == CALLED_FROM_STANDALONE) ||
 997             MUTEX_HELD(&tem->tvs_lock));
 998 
 999         /* Should we cancel? */
1000         if (ch == A_CAN || ch == A_SUB || ch == A_ESC) {
1001                 tem->tvs_state = A_STATE_START;
1002                 return;
1003         }
1004 
1005         /* following two if statements will read in the numeric parameter */
1006         if (ch >= '0' && ch <= '9') {
1007                 tem->tvs_paramval = ((tem->tvs_paramval * 10) + (ch - '0'));
1008                 tem->tvs_gotparam = B_TRUE;  /* Remember got parameter */
1009                 return; /* Return immediately */
1010         }
1011 
1012         if (tem->tvs_gotparam && ch == ';') {
1013                 /* get the parameter value */
1014                 tem->tvs_params[tem->tvs_curparam] = tem->tvs_paramval;
1015                 tem->tvs_curparam++;
1016                 tem->tvs_gotparam = B_FALSE;
1017                 tem->tvs_paramval = 0;
1018         }
1019 
1020         if (tem->tvs_curparam == 0) {
1021                 /* bad sequence */
1022                 tem->tvs_state = A_STATE_START;
1023                 return;
1024         }
1025         if (tem->tvs_gotparam == B_FALSE && tem->tvs_curparam > 0) {
1026                 if (tem->tvs_params[0] != 4 && tem->tvs_params[0] != 104) {
1027                         /* make sure tvs_params will not get filled up */
1028                         tem->tvs_curparam = 1;
1029                 }
1030         }
1031         if (ch == A_ST || ch == A_BEL) {
1032                 /* done */
1033                 tem->tvs_state = A_STATE_START;
1034                 return;
1035         }
1036 }
1037 
1038 /*
1039  * Add character to internal buffer.
1040  * When its full, send it to the next layer.
1041  */
1042 
1043 static void
1044 tem_safe_outch(struct tem_vt_state *tem, tem_char_t ch,
1045     cred_t *credp, enum called_from called_from)
1046 {
1047         text_color_t fg;
1048         text_color_t bg;
1049         text_attr_t attr;
1050 
1051         ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
1052             called_from == CALLED_FROM_STANDALONE);
1053 
1054         /* buffer up the character until later */
1055         tem_safe_get_attr(tem, &fg, &bg, &attr, TEM_ATTR_REVERSE);
1056         tem->tvs_outbuf[tem->tvs_outindex].tc_char = ch | TEM_ATTR(attr);
1057         tem->tvs_outbuf[tem->tvs_outindex].tc_fg_color = fg;
1058         tem->tvs_outbuf[tem->tvs_outindex].tc_bg_color = bg;
1059         tem->tvs_outindex++;
1060         tem->tvs_c_cursor.col++;
1061         if (tem->tvs_c_cursor.col >= tems.ts_c_dimension.width) {
1062                 tem_safe_send_data(tem, credp, called_from);
1063                 tem_safe_new_line(tem, credp, called_from);
1064         }
1065 }
1066 
1067 static void
1068 tem_safe_new_line(struct tem_vt_state *tem,
1069     cred_t *credp, enum called_from called_from)
1070 {
1071         tem_safe_cr(tem);
1072         tem_safe_lf(tem, credp, called_from);
1073 }
1074 
1075 static void
1076 tem_safe_cr(struct tem_vt_state *tem)
1077 {
1078         tem->tvs_c_cursor.col = 0;
1079         tem_safe_align_cursor(tem);


1118             credp, called_from);
1119 
1120         if (tem->tvs_nscroll == 0) {
1121                 /* erase rest of cursor line */
1122                 tem_safe_clear_chars(tem,
1123                     tems.ts_c_dimension.width -
1124                     tem->tvs_c_cursor.col,
1125                     tem->tvs_c_cursor.row,
1126                     tem->tvs_c_cursor.col,
1127                     credp, called_from);
1128 
1129         }
1130 
1131         tem_safe_align_cursor(tem);
1132 }
1133 
1134 static void
1135 tem_safe_send_data(struct tem_vt_state *tem, cred_t *credp,
1136     enum called_from called_from)
1137 {



1138         ASSERT((called_from == CALLED_FROM_STANDALONE) ||
1139             MUTEX_HELD(&tem->tvs_lock));
1140 
1141         if (tem->tvs_outindex == 0) {
1142                 tem_safe_align_cursor(tem);
1143                 return;
1144         }
1145 

1146         tem_safe_virtual_display(tem,
1147             tem->tvs_outbuf, tem->tvs_outindex,
1148             tem->tvs_s_cursor.row, tem->tvs_s_cursor.col);

1149 
1150         if (tem->tvs_isactive) {
1151                 /*
1152                  * Call the primitive to render this data.
1153                  */
1154                 tem_safe_callback_display(tem,
1155                     tem->tvs_outbuf, tem->tvs_outindex,
1156                     tem->tvs_s_cursor.row, tem->tvs_s_cursor.col,

1157                     credp, called_from);
1158         }
1159 
1160         tem->tvs_outindex = 0;
1161 
1162         tem_safe_align_cursor(tem);
1163 }
1164 
1165 
1166 /*
1167  * We have just done something to the current output point.  Reset the start
1168  * point for the buffered data in a_outbuf.  There shouldn't be any data
1169  * buffered yet.
1170  */
1171 static void
1172 tem_safe_align_cursor(struct tem_vt_state *tem)
1173 {
1174         tem->tvs_s_cursor.row = tem->tvs_c_cursor.row;
1175         tem->tvs_s_cursor.col = tem->tvs_c_cursor.col;
1176 }
1177 
1178 /*
1179  * State machine parser based on the current state and character input
1180  * major terminations are to control character or normal character
1181  */
1182 
1183 static void
1184 tem_safe_parse(struct tem_vt_state *tem, tem_char_t ch,
1185     cred_t *credp, enum called_from called_from)
1186 {
1187         int     i;
1188 
1189         ASSERT((called_from == CALLED_FROM_STANDALONE) ||
1190             MUTEX_HELD(&tem->tvs_lock));
1191 
1192         if (tem->tvs_state == A_STATE_START) {       /* Normal state? */
1193                 if (ch == A_CSI || ch == A_OSC || ch == A_ESC || ch < ' ') {
1194                         /* Control */
1195                         tem_safe_control(tem, ch, credp, called_from);
1196                 } else {
1197                         /* Display */
1198                         tem_safe_outch(tem, ch, credp, called_from);
1199                 }
1200                 return;
1201         }
1202 
1203         /* In <ESC> sequence */
1204         if (tem->tvs_state != A_STATE_ESC) { /* Need to get parameters? */
1205                 if (tem->tvs_state == A_STATE_OSC) {
1206                         tem_safe_get_oscstring(tem, ch, credp, called_from);
1207                         return;
1208                 }
1209 
1210                 if (tem->tvs_state != A_STATE_CSI) {
1211                         tem_safe_getparams(tem, ch, credp, called_from);
1212                         return;
1213                 }
1214 
1215                 switch (ch) {
1216                 case '?':
1217                         tem->tvs_state = A_STATE_CSI_QMARK;
1218                         return;
1219                 case '=':
1220                         tem->tvs_state = A_STATE_CSI_EQUAL;
1221                         return;
1222                 case 's':
1223                         /*
1224                          * As defined below, this sequence
1225                          * saves the cursor.  However, Sun
1226                          * defines ESC[s as reset.  We resolved
1227                          * the conflict by selecting reset as it
1228                          * is exported in the termcap file for
1229                          * sun-mon, while the "save cursor"


1300                                 tem->tvs_nscroll = tems.ts_c_dimension.height;
1301                         if (tem->tvs_nscroll < 0)
1302                                 tem->tvs_nscroll = 1;
1303                         tem->tvs_state = A_STATE_START;
1304                         return;
1305                 default:
1306                         tem_safe_getparams(tem, ch, credp, called_from);
1307                         return;
1308                 }
1309         }
1310 
1311         /* Previous char was <ESC> */
1312         if (ch == '[') {
1313                 tem->tvs_curparam = 0;
1314                 tem->tvs_paramval = 0;
1315                 tem->tvs_gotparam = B_FALSE;
1316                 /* clear the parameters */
1317                 for (i = 0; i < TEM_MAXPARAMS; i++)
1318                         tem->tvs_params[i] = -1;
1319                 tem->tvs_state = A_STATE_CSI;
1320         } else if (ch == ']') {
1321                 tem->tvs_curparam = 0;
1322                 tem->tvs_paramval = 0;
1323                 tem->tvs_gotparam = B_FALSE;
1324                 /* clear the parameters */
1325                 for (i = 0; i < TEM_MAXPARAMS; i++)
1326                         tem->tvs_params[i] = -1;
1327                 tem->tvs_state = A_STATE_OSC;
1328         } else if (ch == 'Q') { /* <ESC>Q ? */
1329                 tem->tvs_state = A_STATE_START;
1330         } else if (ch == 'C') { /* <ESC>C ? */
1331                 tem->tvs_state = A_STATE_START;
1332         } else {
1333                 tem->tvs_state = A_STATE_START;
1334                 if (ch == 'c') {
1335                         /* ESC c resets display */
1336                         tem_safe_reset_display(tem, credp, called_from,
1337                             B_TRUE, B_TRUE);
1338                 } else if (ch == 'H') {
1339                         /* ESC H sets a tab */
1340                         tem_safe_set_tab(tem);
1341                 } else if (ch == '7') {
1342                         /* ESC 7 Save Cursor position */
1343                         tem->tvs_r_cursor.row = tem->tvs_c_cursor.row;
1344                         tem->tvs_r_cursor.col = tem->tvs_c_cursor.col;
1345                 } else if (ch == '8') {
1346                         /* ESC 8 Restore Cursor position */
1347                         tem_safe_mv_cursor(tem, tem->tvs_r_cursor.row,


1468                 return;
1469 
1470         /*
1471          * Note that very large values of "count" could cause col+count
1472          * to overflow, so we check "count" independently.
1473          */
1474         if (count > tems.ts_c_dimension.width ||
1475             col + count > tems.ts_c_dimension.width)
1476                 count = tems.ts_c_dimension.width - col;
1477 
1478         tem_safe_virtual_cls(tem, count, row, col);
1479 
1480         if (!tem->tvs_isactive)
1481                 return;
1482 
1483         tem_safe_callback_cls(tem, count, row, col, credp, called_from);
1484 }
1485 
1486 /*ARGSUSED*/
1487 void
1488 tem_safe_text_display(struct tem_vt_state *tem, term_char_t *string,
1489     int count, screen_pos_t row, screen_pos_t col,

1490     cred_t *credp, enum called_from called_from)
1491 {
1492         struct vis_consdisplay da;
1493         int i;
1494         tem_char_t c;
1495 
1496         ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
1497             called_from == CALLED_FROM_STANDALONE);
1498 
1499         da.data = (uint8_t *)&c;
1500         da.width = 1;
1501         da.row = row;
1502         da.col = col;
1503 
1504         for (i = 0; i < count; i++) {
1505                 tem_safe_get_color(&da.fg_color, &da.bg_color, string[i]);
1506                 c = TEM_CHAR(string[i].tc_char);
1507                 tems_safe_display(&da, credp, called_from);
1508                 da.col++;
1509         }
1510 }
1511 
1512 /*
1513  * This function is used to blit a rectangular color image,
1514  * unperturbed on the underlying framebuffer, to render
1515  * icons and pictures.  The data is a pixel pattern that
1516  * fills a rectangle bounded to the width and height parameters.
1517  * The color pixel data must to be pre-adjusted by the caller
1518  * for the current video depth.
1519  *
1520  * This function is unused now.
1521  */
1522 /*ARGSUSED*/
1523 static void
1524 tem_safe_image_display(struct tem_vt_state *tem, uchar_t *image,
1525     int height, int width, screen_pos_t row, screen_pos_t col,
1526     cred_t *credp, enum called_from called_from)
1527 {
1528         struct vis_consdisplay da;
1529 
1530         mutex_enter(&tems.ts_lock);
1531         mutex_enter(&tem->tvs_lock);
1532 
1533         da.data = image;
1534         da.width = (screen_size_t)width;
1535         da.height = (screen_size_t)height;
1536         da.row = row;
1537         da.col = col;
1538 
1539         tems_safe_display(&da, credp, called_from);
1540 
1541         mutex_exit(&tem->tvs_lock);
1542         mutex_exit(&tems.ts_lock);
1543 }
1544 

1545 /*ARGSUSED*/
1546 void
1547 tem_safe_text_copy(struct tem_vt_state *tem,
1548     screen_pos_t s_col, screen_pos_t s_row,
1549     screen_pos_t e_col, screen_pos_t e_row,
1550     screen_pos_t t_col, screen_pos_t t_row,
1551     cred_t *credp, enum called_from called_from)
1552 {
1553         struct vis_conscopy da;
1554 
1555         ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
1556             called_from == CALLED_FROM_STANDALONE);
1557 
1558         da.s_row = s_row;
1559         da.s_col = s_col;
1560         da.e_row = e_row;
1561         da.e_col = e_col;
1562         da.t_row = t_row;
1563         da.t_col = t_col;
1564 
1565         tems_safe_copy(&da, credp, called_from);
1566 }
1567 
1568 void
1569 tem_safe_text_cls(struct tem_vt_state *tem,
1570     int count, screen_pos_t row, screen_pos_t col, cred_t *credp,
1571     enum called_from called_from)
1572 {
1573         text_attr_t attr;
1574         term_char_t c;
1575         int i;
1576 
1577         ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
1578             called_from == CALLED_FROM_STANDALONE);
1579 
1580         tem_safe_get_attr(tem, &c.tc_fg_color, &c.tc_bg_color, &attr,





1581             TEM_ATTR_SCREEN_REVERSE);
1582         c.tc_char = TEM_ATTR(attr & ~TEM_ATTR_UNDERLINE) | ' ';
1583 
1584         if (count > tems.ts_c_dimension.width ||
1585             col + count > tems.ts_c_dimension.width)
1586                 count = tems.ts_c_dimension.width - col;
1587 
1588         for (i = 0; i < count; i++)
1589                 tems.ts_blank_line[i] = c;
1590 
1591         tem_safe_text_display(tem, tems.ts_blank_line, count, row, col,
1592                 credp, called_from);
1593 }
1594 
1595 void
1596 tem_safe_pix_display(struct tem_vt_state *tem,
1597     term_char_t *string, int count,
1598     screen_pos_t row, screen_pos_t col,

1599     cred_t *credp, enum called_from called_from)
1600 {
1601         struct vis_consdisplay da;
1602         int     i;
1603 
1604         ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
1605             called_from == CALLED_FROM_STANDALONE);
1606 
1607         da.data = (uchar_t *)tem->tvs_pix_data;
1608         da.width = (screen_size_t)tems.ts_font.vf_width;
1609         da.height = (screen_size_t)tems.ts_font.vf_height;
1610         da.row = (row * da.height) + tems.ts_p_offset.y;
1611         da.col = (col * da.width) + tems.ts_p_offset.x;
1612 
1613         for (i = 0; i < count; i++) {
1614                 tem_safe_callback_bit2pix(tem, string[i]);
1615                 tems_safe_display(&da, credp, called_from);
1616                 da.col += da.width;
1617         }
1618 }
1619 
1620 void
1621 tem_safe_pix_copy(struct tem_vt_state *tem,
1622     screen_pos_t s_col, screen_pos_t s_row,
1623     screen_pos_t e_col, screen_pos_t e_row,
1624     screen_pos_t t_col, screen_pos_t t_row,
1625     cred_t *credp,
1626     enum called_from called_from)
1627 {
1628         struct vis_conscopy ma;
1629         static boolean_t need_clear = B_TRUE;
1630 
1631         ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
1632             called_from == CALLED_FROM_STANDALONE);
1633 
1634         if (need_clear && tem->tvs_first_line > 0) {
1635                 /*
1636                  * Clear OBP output above our kernel console term
1637                  * when our kernel console term begins to scroll up,
1638                  * we hope it is user friendly.
1639                  * (Also see comments on tem_safe_pix_clear_prom_output)
1640                  *
1641                  * This is only one time call.
1642                  */
1643                 tem_safe_pix_clear_prom_output(tem, credp, called_from);
1644         }
1645         need_clear = B_FALSE;
1646 
1647         ma.s_row = s_row * tems.ts_font.vf_height + tems.ts_p_offset.y;
1648         ma.e_row = (e_row + 1) * tems.ts_font.vf_height +
1649             tems.ts_p_offset.y - 1;
1650         ma.t_row = t_row * tems.ts_font.vf_height + tems.ts_p_offset.y;
1651 
1652         /*
1653          * Check if we're in process of clearing OBP's columns area,
1654          * which only happens when term scrolls up a whole line.
1655          */
1656         if (tem->tvs_first_line > 0 && t_row < s_row && t_col == 0 &&
1657             e_col == tems.ts_c_dimension.width - 1) {
1658                 /*
1659                  * We need to clear OBP's columns area outside our kernel
1660                  * console term. So that we set ma.e_col to entire row here.
1661                  */
1662                 ma.s_col = s_col * tems.ts_font.vf_width;
1663                 ma.e_col = tems.ts_p_dimension.width - 1;
1664 
1665                 ma.t_col = t_col * tems.ts_font.vf_width;
1666         } else {
1667                 ma.s_col = s_col * tems.ts_font.vf_width + tems.ts_p_offset.x;
1668                 ma.e_col = (e_col + 1) * tems.ts_font.vf_width +
1669                     tems.ts_p_offset.x - 1;
1670                 ma.t_col = t_col * tems.ts_font.vf_width + tems.ts_p_offset.x;
1671         }
1672 
1673         tems_safe_copy(&ma, credp, called_from);
1674 
1675         if (tem->tvs_first_line > 0 && t_row < s_row) {
1676                 /* We have scrolled up (s_row - t_row) rows. */
1677                 tem->tvs_first_line -= (s_row - t_row);
1678                 if (tem->tvs_first_line <= 0) {
1679                         /* All OBP rows have been cleared. */
1680                         tem->tvs_first_line = 0;
1681                 }
1682         }
1683 
1684 }
1685 
1686 void
1687 tem_safe_pix_bit2pix(struct tem_vt_state *tem, term_char_t c)

1688 {
1689         text_color_t fg, bg;
1690         void (*fp)(struct tem_vt_state *, tem_char_t,
1691             unsigned char, unsigned char);
1692 
1693         tem_safe_get_color(&fg, &bg, c);
1694         switch (tems.ts_pdepth) {
1695         case 4:
1696                 fp = bit_to_pix4;
1697                 break;
1698         case 8:
1699                 fp = bit_to_pix8;
1700                 break;
1701         case 15:
1702         case 16:
1703                 fp = bit_to_pix16;
1704                 break;
1705         case 24:

1706                 fp = bit_to_pix24;
1707                 break;
1708         case 32:
1709                 fp = bit_to_pix32;
1710                 break;
1711         default:
1712                 return;
1713         }
1714 
1715         fp(tem, c.tc_char, fg, bg);
1716 }
1717 
1718 
1719 /*
1720  * This function only clears count of columns in one row
1721  */
1722 void
1723 tem_safe_pix_cls(struct tem_vt_state *tem, int count,
1724     screen_pos_t row, screen_pos_t col, cred_t *credp,
1725     enum called_from called_from)
1726 {
1727         ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
1728             called_from == CALLED_FROM_STANDALONE);
1729 
1730         tem_safe_pix_cls_range(tem, row, 1, tems.ts_p_offset.y,
1731             col, count, tems.ts_p_offset.x, B_FALSE, credp, called_from);
1732 }
1733 
1734 /*
1735  * This function clears OBP output above our kernel console term area


1741  *      _________________________________
1742  *      |   _____________________       |  ---> OBP's bigger term window
1743  *      |   |                   |       |
1744  *      |___|                   |       |
1745  *      | | |                   |       |
1746  *      | | |                   |       |
1747  *      |_|_|___________________|_______|
1748  *        | |                   |          ---> first line
1749  *        | |___________________|---> our kernel console term window
1750  *        |
1751  *        |---> columns area to be cleared
1752  *
1753  * This function only takes care of the output above our kernel console term,
1754  * and tem_prom_scroll_up takes care of columns area outside of our kernel
1755  * console term.
1756  */
1757 static void
1758 tem_safe_pix_clear_prom_output(struct tem_vt_state *tem, cred_t *credp,
1759     enum called_from called_from)
1760 {
1761         int     nrows, ncols, width, height, offset;
1762 
1763         ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
1764             called_from == CALLED_FROM_STANDALONE);
1765 
1766         width = tems.ts_font.vf_width;
1767         height = tems.ts_font.vf_height;
1768         offset = tems.ts_p_offset.y % height;
1769 
1770         nrows = tems.ts_p_offset.y / height;
1771         ncols = (tems.ts_p_dimension.width + (width - 1))/ width;
1772 
1773         if (nrows > 0)
1774                 tem_safe_pix_cls_range(tem, 0, nrows, offset, 0, ncols, 0,
1775                     B_FALSE, credp, called_from);
1776 }
1777 
1778 /*
1779  * clear the whole screen for pixel mode, just clear the
1780  * physical screen.
1781  */
1782 void
1783 tem_safe_pix_clear_entire_screen(struct tem_vt_state *tem, cred_t *credp,
1784     enum called_from called_from)
1785 {
1786         struct vis_consclear cl;
1787         text_color_t fg_color;
1788         text_color_t bg_color;
1789         text_attr_t attr;
1790         term_char_t c;
1791         int nrows, ncols, width, height;
1792 
1793         ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
1794             called_from == CALLED_FROM_STANDALONE);
1795 
1796         /* call driver first, if error, clear terminal area */
1797         tem_safe_get_attr(tem, &c.tc_fg_color, &c.tc_bg_color, &attr,
1798             TEM_ATTR_SCREEN_REVERSE);
1799         c.tc_char = TEM_ATTR(attr);
1800 
1801         tem_safe_get_color(&fg_color, &bg_color, c);
1802         cl.bg_color = bg_color;
1803         if (tems_cls_layered(&cl, credp) == 0)
1804                 return;
1805 
1806         width = tems.ts_font.vf_width;
1807         height = tems.ts_font.vf_height;
1808 
1809         nrows = (tems.ts_p_dimension.height + (height - 1))/ height;
1810         ncols = (tems.ts_p_dimension.width + (width - 1))/ width;
1811 
1812         tem_safe_pix_cls_range(tem, 0, nrows, tems.ts_p_offset.y, 0, ncols,
1813             tems.ts_p_offset.x, B_FALSE, credp, called_from);
1814 
1815         /*
1816          * Since the whole screen is cleared, we don't need
1817          * to clear OBP output later.
1818          */
1819         if (tem->tvs_first_line > 0)
1820                 tem->tvs_first_line = 0;
1821 }
1822 
1823 /*
1824  * clear the whole screen, including the virtual screen buffer,
1825  * and reset the cursor to start point.
1826  */
1827 static void
1828 tem_safe_cls(struct tem_vt_state *tem,
1829     cred_t *credp, enum called_from called_from)
1830 {
1831         int     row;
1832 
1833         ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||


2111         ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
2112             called_from == CALLED_FROM_STANDALONE);
2113 
2114         ca.row = tem->tvs_c_cursor.row;
2115         ca.col = tem->tvs_c_cursor.col;
2116         ca.action = action;
2117 
2118         tems_safe_cursor(&ca, credp, called_from);
2119 
2120         if (action == VIS_GET_CURSOR) {
2121                 tem->tvs_c_cursor.row = ca.row;
2122                 tem->tvs_c_cursor.col = ca.col;
2123         }
2124 }
2125 
2126 void
2127 tem_safe_pix_cursor(struct tem_vt_state *tem, short action,
2128     cred_t *credp, enum called_from called_from)
2129 {
2130         struct vis_conscursor   ca;
2131         uint32_t color;
2132         text_color_t fg, bg;
2133         term_char_t c;
2134         text_attr_t attr;
2135 
2136         ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
2137             called_from == CALLED_FROM_STANDALONE);
2138 
2139         ca.row = tem->tvs_c_cursor.row * tems.ts_font.vf_height +
2140             tems.ts_p_offset.y;
2141         ca.col = tem->tvs_c_cursor.col * tems.ts_font.vf_width +
2142             tems.ts_p_offset.x;
2143         ca.width = (screen_size_t)tems.ts_font.vf_width;
2144         ca.height = (screen_size_t)tems.ts_font.vf_height;
2145 
2146         tem_safe_get_attr(tem, &c.tc_fg_color, &c.tc_bg_color, &attr,
2147             TEM_ATTR_REVERSE);
2148         c.tc_char = TEM_ATTR(attr);
2149 
2150         tem_safe_get_color(&fg, &bg, c);
2151 
2152         switch (tems.ts_pdepth) {
2153         case 4:
2154                 ca.fg_color.mono = fg;
2155                 ca.bg_color.mono = bg;
2156                 break;
2157         case 8:
2158                 ca.fg_color.mono = tems.ts_color_map(fg);
2159                 ca.bg_color.mono = tems.ts_color_map(bg);
2160                 break;
2161         case 15:
2162         case 16:
2163                 color = tems.ts_color_map(fg);
2164                 ca.fg_color.sixteen[0] = (color >> 8) & 0xFF;
2165                 ca.fg_color.sixteen[1] = color & 0xFF;
2166                 color = tems.ts_color_map(bg);
2167                 ca.bg_color.sixteen[0] = (color >> 8) & 0xFF;
2168                 ca.bg_color.sixteen[1] = color & 0xFF;
2169                 break;
2170         case 24:
2171         case 32:
2172 #ifdef _HAVE_TEM_FIRMWARE
2173                 /* Keeping this block to support old binary only drivers */
2174                 if (tem->tvs_flags & TEM_ATTR_REVERSE) {








2175                         ca.fg_color.twentyfour[0] = TEM_TEXT_WHITE24_RED;
2176                         ca.fg_color.twentyfour[1] = TEM_TEXT_WHITE24_GREEN;
2177                         ca.fg_color.twentyfour[2] = TEM_TEXT_WHITE24_BLUE;
2178 
2179                         ca.bg_color.twentyfour[0] = TEM_TEXT_BLACK24_RED;
2180                         ca.bg_color.twentyfour[1] = TEM_TEXT_BLACK24_GREEN;
2181                         ca.bg_color.twentyfour[2] = TEM_TEXT_BLACK24_BLUE;
2182                 } else {
2183                         ca.fg_color.twentyfour[0] = TEM_TEXT_BLACK24_RED;
2184                         ca.fg_color.twentyfour[1] = TEM_TEXT_BLACK24_GREEN;
2185                         ca.fg_color.twentyfour[2] = TEM_TEXT_BLACK24_BLUE;
2186 
2187                         ca.bg_color.twentyfour[0] = TEM_TEXT_WHITE24_RED;
2188                         ca.bg_color.twentyfour[1] = TEM_TEXT_WHITE24_GREEN;
2189                         ca.bg_color.twentyfour[2] = TEM_TEXT_WHITE24_BLUE;
2190                 }
2191 #else
2192                 color = tems.ts_color_map(fg);
2193                 ca.fg_color.twentyfour[0] = (color >> 16) & 0xFF;
2194                 ca.fg_color.twentyfour[1] = (color >> 8) & 0xFF;
2195                 ca.fg_color.twentyfour[2] = color & 0xFF;
2196                 color = tems.ts_color_map(bg);
2197                 ca.bg_color.twentyfour[0] = (color >> 16) & 0xFF;
2198                 ca.bg_color.twentyfour[1] = (color >> 8) & 0xFF;
2199                 ca.bg_color.twentyfour[2] = color & 0xFF;
2200                 break;
2201 #endif
2202         }
2203 
2204         ca.action = action;
2205 
2206         tems_safe_cursor(&ca, credp, called_from);
2207 
2208         if (action == VIS_GET_CURSOR) {
2209                 tem->tvs_c_cursor.row = 0;
2210                 tem->tvs_c_cursor.col = 0;
2211 
2212                 if (ca.row != 0) {
2213                         tem->tvs_c_cursor.row = (ca.row - tems.ts_p_offset.y) /
2214                             tems.ts_font.vf_height;
2215                 }
2216                 if (ca.col != 0) {
2217                         tem->tvs_c_cursor.col = (ca.col - tems.ts_p_offset.x) /
2218                             tems.ts_font.vf_width;
2219                 }
2220         }
2221 }
2222 
2223 static void
2224 bit_to_pix4(struct tem_vt_state *tem, tem_char_t c, text_color_t fg_color,
2225     text_color_t bg_color)
2226 {
2227         uint8_t *dest = (uint8_t *)tem->tvs_pix_data;
2228         font_bit_to_pix4(&tems.ts_font, dest, c, fg_color, bg_color);
2229 }
2230 
2231 static void
2232 bit_to_pix8(struct tem_vt_state *tem, tem_char_t c, text_color_t fg_color,
2233     text_color_t bg_color)
2234 {
2235         uint8_t *dest = (uint8_t *)tem->tvs_pix_data;
2236 
2237         fg_color = (text_color_t)tems.ts_color_map(fg_color);
2238         bg_color = (text_color_t)tems.ts_color_map(bg_color);
2239         font_bit_to_pix8(&tems.ts_font, dest, c, fg_color, bg_color);
2240 }
2241 
2242 static void
2243 bit_to_pix16(struct tem_vt_state *tem, tem_char_t c, text_color_t fg_color4,
2244     text_color_t bg_color4)
2245 {
2246         uint16_t fg_color16, bg_color16;
2247         uint16_t *dest;
2248 
2249         ASSERT(fg_color4 < 16 && bg_color4 < 16);
2250 
2251         fg_color16 = (uint16_t)tems.ts_color_map(fg_color4);
2252         bg_color16 = (uint16_t)tems.ts_color_map(bg_color4);
2253 
2254         dest = (uint16_t *)tem->tvs_pix_data;
2255         font_bit_to_pix16(&tems.ts_font, dest, c, fg_color16, bg_color16);
2256 }
2257 
2258 static void
2259 bit_to_pix24(struct tem_vt_state *tem, tem_char_t c, text_color_t fg_color4,
2260     text_color_t bg_color4)
2261 {
2262         uint32_t fg_color32, bg_color32;
2263         uint8_t *dest;
2264 
2265         ASSERT(fg_color4 < 16 && bg_color4 < 16);
2266 
2267 #ifdef _HAVE_TEM_FIRMWARE
2268         fg_color32 = PIX4TO32(fg_color4);
2269         bg_color32 = PIX4TO32(bg_color4);
2270 #else
2271         fg_color32 = tems.ts_color_map(fg_color4);
2272         bg_color32 = tems.ts_color_map(bg_color4);
2273 #endif
2274 
2275         dest = (uint8_t *)tem->tvs_pix_data;
2276         font_bit_to_pix24(&tems.ts_font, dest, c, fg_color32, bg_color32);
2277 }
2278 
2279 static void
2280 bit_to_pix32(struct tem_vt_state *tem, tem_char_t c, text_color_t fg_color4,
2281     text_color_t bg_color4)
2282 {
2283         uint32_t fg_color32, bg_color32, *dest;




2284 
2285         ASSERT(fg_color4 < 16 && bg_color4 < 16);
2286 
2287 #ifdef _HAVE_TEM_FIRMWARE
2288         fg_color32 = PIX4TO32(fg_color4);
2289         bg_color32 = PIX4TO32(bg_color4);
2290 #else
2291         fg_color32 = ((uint32_t)0xFF << 24) | tems.ts_color_map(fg_color4);
2292         bg_color32 = ((uint32_t)0xFF << 24) | tems.ts_color_map(bg_color4);
2293 #endif
2294 
2295         dest = (uint32_t *)tem->tvs_pix_data;
2296         font_bit_to_pix32(&tems.ts_font, dest, c, fg_color32, bg_color32);
2297 }
2298 
2299 /*
2300  * flag: TEM_ATTR_SCREEN_REVERSE or TEM_ATTR_REVERSE
2301  */
2302 void
2303 tem_safe_get_attr(struct tem_vt_state *tem, text_color_t *fg,
2304     text_color_t *bg, text_attr_t *attr, uint8_t flag)
2305 {
2306         if (tem->tvs_flags & flag) {
2307                 *fg = tem->tvs_bg_color;
2308                 *bg = tem->tvs_fg_color;


2309         } else {
2310                 *fg = tem->tvs_fg_color;
2311                 *bg = tem->tvs_bg_color;


2312         }
2313 
2314         if (attr == NULL)
2315                 return;
2316 
2317         *attr = tem->tvs_flags;
2318 }
2319 
2320 static void
2321 tem_safe_get_color(text_color_t *fg, text_color_t *bg, term_char_t c)
2322 {
2323         if (TEM_CHAR_ATTR(c.tc_char) & (TEM_ATTR_BRIGHT_FG | TEM_ATTR_BOLD))
2324                 *fg = brt_xlate[c.tc_fg_color];
2325         else
2326                 *fg = dim_xlate[c.tc_fg_color];
2327 
2328         if (TEM_CHAR_ATTR(c.tc_char) & TEM_ATTR_BRIGHT_BG)
2329                 *bg = brt_xlate[c.tc_bg_color];
2330         else
2331                 *bg = dim_xlate[c.tc_bg_color];
2332 }
2333 
2334 /*
2335  * Clear a rectangle of screen for pixel mode.
2336  *
2337  * arguments:
2338  *    row:      start row#
2339  *    nrows:    the number of rows to clear
2340  *    offset_y: the offset of height in pixels to begin clear
2341  *    col:      start col#
2342  *    ncols:    the number of cols to clear
2343  *    offset_x: the offset of width in pixels to begin clear
2344  *    scroll_up: whether this function is called during sroll up,
2345  *               which is called only once.
2346  */
2347 void
2348 tem_safe_pix_cls_range(struct tem_vt_state *tem,
2349     screen_pos_t row, int nrows, int offset_y,
2350     screen_pos_t col, int ncols, int offset_x,
2351     boolean_t sroll_up, cred_t *credp,
2352     enum called_from called_from)
2353 {
2354         struct vis_consdisplay da;
2355         int     i, j;
2356         int     row_add = 0;
2357         term_char_t c;
2358         text_attr_t attr;
2359 
2360         ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
2361             called_from == CALLED_FROM_STANDALONE);
2362 
2363         if (sroll_up)
2364                 row_add = tems.ts_c_dimension.height - 1;
2365 
2366         da.width = (screen_size_t)tems.ts_font.vf_width;
2367         da.height = (screen_size_t)tems.ts_font.vf_height;
2368 
2369         tem_safe_get_attr(tem, &c.tc_fg_color, &c.tc_bg_color, &attr,
2370             TEM_ATTR_SCREEN_REVERSE);
2371         /* Make sure we will not draw underlines */
2372         c.tc_char = TEM_ATTR(attr & ~TEM_ATTR_UNDERLINE) | ' ';
2373 
2374         tem_safe_callback_bit2pix(tem, c);
2375         da.data = (uchar_t *)tem->tvs_pix_data;
2376 
2377         for (i = 0; i < nrows; i++, row++) {
2378                 da.row = (row + row_add) * da.height + offset_y;
2379                 da.col = col * da.width + offset_x;
2380                 for (j = 0; j < ncols; j++) {
2381                         tems_safe_display(&da, credp, called_from);
2382                         da.col += da.width;
2383                 }
2384         }
2385 }
2386 
2387 /*
2388  * virtual screen operations
2389  */
2390 static void
2391 tem_safe_virtual_display(struct tem_vt_state *tem, term_char_t *string,
2392     int count, screen_pos_t row, screen_pos_t col)

2393 {
2394         int i, width;
2395         term_char_t *addr;


2396 
2397         if (row < 0 || row >= tems.ts_c_dimension.height ||
2398             col < 0 || col >= tems.ts_c_dimension.width ||
2399             col + count > tems.ts_c_dimension.width)
2400                 return;
2401 
2402         width = tems.ts_c_dimension.width;
2403         addr = tem->tvs_screen_buf + (row * width + col);


2404         for (i = 0; i < count; i++) {
2405                 *addr++ = string[i];


2406         }
2407 }
2408 
2409 static void
2410 i_virtual_copy_tem_chars(term_char_t *base,
2411     screen_pos_t s_col, screen_pos_t s_row,
2412     screen_pos_t e_col, screen_pos_t e_row,
2413     screen_pos_t t_col, screen_pos_t t_row)
2414 {
2415         term_char_t     *from;
2416         term_char_t     *to;
2417         int             cnt;
2418         screen_size_t chars_per_row;
2419         term_char_t     *to_row_start;
2420         term_char_t     *from_row_start;
2421         screen_size_t   rows_to_move;
2422         int             cols = tems.ts_c_dimension.width;
2423 
2424         chars_per_row = e_col - s_col + 1;
2425         rows_to_move = e_row - s_row + 1;
2426 
2427         to_row_start = base + ((t_row * cols) + t_col);
2428         from_row_start = base + ((s_row * cols) + s_col);
2429 
2430         if (to_row_start < from_row_start) {
2431                 while (rows_to_move-- > 0) {
2432                         to = to_row_start;
2433                         from = from_row_start;
2434                         to_row_start += cols;
2435                         from_row_start += cols;
2436                         for (cnt = chars_per_row; cnt-- > 0; )
2437                                 *to++ = *from++;
2438                 }
2439         } else {
2440                 /*


2467         int             cols = tems.ts_c_dimension.width;
2468 
2469         if (s_col < 0 || s_col >= cols ||
2470             s_row < 0 || s_row >= rows ||
2471             e_col < 0 || e_col >= cols ||
2472             e_row < 0 || e_row >= rows ||
2473             t_col < 0 || t_col >= cols ||
2474             t_row < 0 || t_row >= rows ||
2475             s_col > e_col ||
2476             s_row > e_row)
2477                 return;
2478 
2479         chars_per_row = e_col - s_col + 1;
2480         rows_to_move = e_row - s_row + 1;
2481 
2482         /* More sanity checks. */
2483         if (t_row + rows_to_move > rows ||
2484             t_col + chars_per_row > cols)
2485                 return;
2486 
2487         i_virtual_copy_tem_chars(tem->tvs_screen_buf, s_col, s_row,
2488             e_col, e_row, t_col, t_row);







2489 }
2490 
2491 static void
2492 tem_safe_virtual_cls(struct tem_vt_state *tem,
2493     int count, screen_pos_t row, screen_pos_t col)
2494 {
2495         int i;
2496         text_attr_t attr;
2497         term_char_t c;
2498 
2499         tem_safe_get_attr(tem, &c.tc_fg_color, &c.tc_bg_color, &attr,
2500             TEM_ATTR_SCREEN_REVERSE);
2501         c.tc_char = TEM_ATTR(attr & ~TEM_ATTR_UNDERLINE) | ' ';
2502 
2503         for (i = 0; i < tems.ts_c_dimension.width; i++)
2504                 tems.ts_blank_line[i] = c;
2505 
2506         tem_safe_virtual_display(tem, tems.ts_blank_line, count, row, col);
2507 }
2508 
2509 /*
2510  * only blank screen, not clear our screen buffer
2511  */
2512 void
2513 tem_safe_blank_screen(struct tem_vt_state *tem, cred_t *credp,
2514     enum called_from called_from)
2515 {
2516         int     row;
2517 
2518         ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
2519             called_from == CALLED_FROM_STANDALONE);
2520 
2521         if (tems.ts_display_mode == VIS_PIXEL) {
2522                 tem_safe_pix_clear_entire_screen(tem, credp, called_from);
2523                 return;
2524         }
2525 
2526         for (row = 0; row < tems.ts_c_dimension.height; row++) {
2527                 tem_safe_callback_cls(tem,
2528                     tems.ts_c_dimension.width,
2529                     row, 0, credp, called_from);
2530         }
2531 }
2532 
2533 /*
2534  * unblank screen with associated tem from its screen buffer
2535  */
2536 void
2537 tem_safe_unblank_screen(struct tem_vt_state *tem, cred_t *credp,
2538     enum called_from called_from)
2539 {
2540         int     row;





2541 
2542         ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
2543             called_from == CALLED_FROM_STANDALONE);
2544 
2545         if (tems.ts_display_mode == VIS_PIXEL)
2546                 tem_safe_pix_clear_entire_screen(tem, credp, called_from);
2547 
2548         tem_safe_callback_cursor(tem, VIS_HIDE_CURSOR, credp, called_from);
2549 


2550         /*
2551          * Display data in tvs_screen_buf to the actual framebuffer in a
2552          * row by row way.
2553          * When dealing with one row, output data with the same foreground
2554          * and background color all together.
2555          */
2556         for (row = 0; row < tems.ts_c_dimension.height; row++) {
2557                 tem_safe_callback_display(tem, tem->tvs_screen_rows[row],
2558                     tems.ts_c_dimension.width, row, 0, credp, called_from);








2559         }
2560 




























2561         tem_safe_callback_cursor(tem, VIS_DISPLAY_CURSOR, credp, called_from);
2562 }