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>
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/uts/common/io/tem_safe.c
          +++ new/usr/src/uts/common/io/tem_safe.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  12   12   *
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  
  22   22  /*
  23   23   * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  24   24   * Use is subject to license terms.
  25   25   */
  26   26  
  27   27  /*
  28   28   * Copyright 2016 Joyent, Inc.
  29   29   */
  30   30  
  31   31  /*
  32   32   * Polled I/O safe ANSI terminal emulator module;
  33   33   * Supporting TERM types 'sun' and 'sun-color, parsing
  34   34   * ANSI x3.64 escape sequences, and the like.  (See wscons(7d)
  35   35   * for more information).
  36   36   *
  37   37   * IMPORTANT:
  38   38   *
  39   39   *   The functions in this file *must* be able to function in
  40   40   *   standalone mode, ie. on a quiesced system.   In that state,
  41   41   *   access is single threaded, only one CPU is running.
  42   42   *   System services are NOT available.
  43   43   *
  44   44   * The following restrictions pertain to every function
  45   45   * in this file:
  46   46   *
  47   47   *     - CANNOT use the DDI or LDI interfaces
  48   48   *     - CANNOT call system services
  49   49   *     - CANNOT use mutexes
  50   50   *     - CANNOT wait for interrupts
  51   51   *     - CANNOT allocate memory
  52   52   *
  53   53   * All non-static functions in this file which:
  54   54   *     - Operates on tems and tem_vt_state
  55   55   *     - Not only called from standalone mode, i.e. has
  56   56   *       a "calledfrom" argument
  57   57   * should assert this at the beginning:
  58   58   *
  59   59   *    ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
  60   60   *        called_from == CALLED_FROM_STANDALONE);
  61   61   */
  62   62  
  63   63  #include <sys/types.h>
  64   64  #include <sys/ascii.h>
  65   65  #include <sys/visual_io.h>
  66   66  #include <sys/font.h>
  67   67  #include <sys/tem.h>
  68   68  #include <sys/tem_impl.h>
  69   69  #include <sys/ksynch.h>
  70   70  #include <sys/sysmacros.h>
  71   71  #include <sys/mutex.h>
  72   72  #include <sys/note.h>
  73   73  #include <sys/t_lock.h>
  74   74  
  75   75  tem_safe_callbacks_t tem_safe_text_callbacks = {
  76   76          &tem_safe_text_display,
  77   77          &tem_safe_text_copy,
  78   78          &tem_safe_text_cursor,
  79   79          NULL,
  
    | 
      ↓ open down ↓ | 
    79 lines elided | 
    
      ↑ open up ↑ | 
  
  80   80          &tem_safe_text_cls
  81   81  };
  82   82  tem_safe_callbacks_t tem_safe_pix_callbacks = {
  83   83          &tem_safe_pix_display,
  84   84          &tem_safe_pix_copy,
  85   85          &tem_safe_pix_cursor,
  86   86          &tem_safe_pix_bit2pix,
  87   87          &tem_safe_pix_cls
  88   88  };
  89   89  
  90      -
  91      -static void     tem_safe_control(struct tem_vt_state *, uchar_t,
       90 +static void     tem_safe_control(struct tem_vt_state *, tem_char_t,
  92   91                          cred_t *, enum called_from);
  93   92  static void     tem_safe_setparam(struct tem_vt_state *, int, int);
  94   93  static void     tem_safe_selgraph(struct tem_vt_state *);
  95      -static void     tem_safe_chkparam(struct tem_vt_state *, uchar_t,
       94 +static void     tem_safe_chkparam(struct tem_vt_state *, tem_char_t,
  96   95                          cred_t *, enum called_from);
  97      -static void     tem_safe_getparams(struct tem_vt_state *, uchar_t,
       96 +static void     tem_safe_getparams(struct tem_vt_state *, tem_char_t,
  98   97                          cred_t *, enum called_from);
  99      -static void     tem_safe_outch(struct tem_vt_state *, uchar_t,
       98 +static void     tem_safe_outch(struct tem_vt_state *, tem_char_t,
 100   99                          cred_t *, enum called_from);
 101      -static void     tem_safe_parse(struct tem_vt_state *, uchar_t,
      100 +static void     tem_safe_parse(struct tem_vt_state *, tem_char_t,
 102  101                          cred_t *, enum called_from);
 103  102  
 104  103  static void     tem_safe_new_line(struct tem_vt_state *,
 105  104                          cred_t *, enum called_from);
 106  105  static void     tem_safe_cr(struct tem_vt_state *);
 107  106  static void     tem_safe_lf(struct tem_vt_state *,
 108  107                          cred_t *, enum called_from);
 109  108  static void     tem_safe_send_data(struct tem_vt_state *, cred_t *,
 110  109                          enum called_from);
 111  110  static void     tem_safe_cls(struct tem_vt_state *,
 112  111                          cred_t *, enum called_from);
 113  112  static void     tem_safe_tab(struct tem_vt_state *,
 114  113                          cred_t *, enum called_from);
 115  114  static void     tem_safe_back_tab(struct tem_vt_state *,
 116  115                          cred_t *, enum called_from);
 117  116  static void     tem_safe_clear_tabs(struct tem_vt_state *, int);
 118  117  static void     tem_safe_set_tab(struct tem_vt_state *);
 119  118  static void     tem_safe_mv_cursor(struct tem_vt_state *, int, int,
 120  119                          cred_t *, enum called_from);
 121  120  static void     tem_safe_shift(struct tem_vt_state *, int, int,
 122  121                          cred_t *, enum called_from);
 123  122  static void     tem_safe_scroll(struct tem_vt_state *, int, int,
 124  123                          int, int, cred_t *, enum called_from);
 125  124  static void     tem_safe_clear_chars(struct tem_vt_state *tem,
 126  125                          int count, screen_pos_t row, screen_pos_t col,
 127  126                          cred_t *credp, enum called_from called_from);
 128  127  static void     tem_safe_copy_area(struct tem_vt_state *tem,
 129  128                          screen_pos_t s_col, screen_pos_t s_row,
  
    | 
      ↓ open down ↓ | 
    18 lines elided | 
    
      ↑ open up ↑ | 
  
 130  129                          screen_pos_t e_col, screen_pos_t e_row,
 131  130                          screen_pos_t t_col, screen_pos_t t_row,
 132  131                          cred_t *credp, enum called_from called_from);
 133  132  static void     tem_safe_image_display(struct tem_vt_state *, uchar_t *,
 134  133                          int, int, screen_pos_t, screen_pos_t,
 135  134                          cred_t *, enum called_from);
 136  135  static void     tem_safe_bell(struct tem_vt_state *tem,
 137  136                          enum called_from called_from);
 138  137  static void     tem_safe_pix_clear_prom_output(struct tem_vt_state *tem,
 139  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  140  
 141  141  static void     tem_safe_virtual_cls(struct tem_vt_state *, int, screen_pos_t,
 142  142                      screen_pos_t);
 143  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);
      144 +                    term_char_t *, int, screen_pos_t, screen_pos_t);
 146  145  static void     tem_safe_virtual_copy(struct tem_vt_state *, screen_pos_t,
 147  146                      screen_pos_t, screen_pos_t, screen_pos_t,
 148  147                      screen_pos_t, screen_pos_t);
 149  148  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,
      149 +static void     bit_to_pix4(struct tem_vt_state *tem, tem_char_t c,
 151  150                      text_color_t fg_color, text_color_t bg_color);
 152      -static void     bit_to_pix8(struct tem_vt_state *tem, uchar_t c,
      151 +static void     bit_to_pix8(struct tem_vt_state *tem, tem_char_t c,
 153  152                      text_color_t fg_color, text_color_t bg_color);
 154      -static void     bit_to_pix24(struct tem_vt_state *tem, uchar_t c,
      153 +static void     bit_to_pix16(struct tem_vt_state *tem, tem_char_t c,
 155  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);
 156  159  
 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  160  #define PIX4TO32(pix4) (uint32_t)(  \
 175  161      cmap4_to_24.red[pix4] << 16 |  \
 176  162      cmap4_to_24.green[pix4] << 8 | \
 177  163      cmap4_to_24.blue[pix4])
 178  164  
 179  165  #define INVERSE(ch) (ch ^ 0xff)
 180  166  
 181  167  #define tem_safe_callback_display       (*tems.ts_callbacks->tsc_display)
 182  168  #define tem_safe_callback_copy          (*tems.ts_callbacks->tsc_copy)
 183  169  #define tem_safe_callback_cursor        (*tems.ts_callbacks->tsc_cursor)
 184  170  #define tem_safe_callback_cls           (*tems.ts_callbacks->tsc_cls)
 185      -#define tem_safe_callback_bit2pix(tem, c, fg, bg)       {               \
      171 +#define tem_safe_callback_bit2pix(tem, c)       {               \
 186  172          ASSERT(tems.ts_callbacks->tsc_bit2pix != NULL);                 \
 187      -        (void) (*tems.ts_callbacks->tsc_bit2pix)((tem), (c), (fg), (bg));\
      173 +        (void) (*tems.ts_callbacks->tsc_bit2pix)((tem), (c));\
 188  174  }
 189  175  
 190  176  void
 191  177  tem_safe_check_first_time(
 192  178      struct tem_vt_state *tem,
 193  179      cred_t *credp,
 194  180      enum called_from called_from)
 195  181  {
 196  182          static int first_time = 1;
 197  183  
 198  184          ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
 199  185              called_from == CALLED_FROM_STANDALONE);
 200  186  
  
    | 
      ↓ open down ↓ | 
    3 lines elided | 
    
      ↑ open up ↑ | 
  
 201  187          /*
 202  188           * Realign the console cursor. We did this in tem_init().
 203  189           * However, drivers in the console stream may emit additional
 204  190           * messages before we are ready. This causes text overwrite
 205  191           * on the screen. This is a workaround.
 206  192           */
 207  193          if (!first_time)
 208  194                  return;
 209  195  
 210  196          first_time = 0;
 211      -        if (tems.ts_display_mode == VIS_TEXT) {
      197 +        if (tems.ts_display_mode == VIS_TEXT)
 212  198                  tem_safe_text_cursor(tem, VIS_GET_CURSOR, credp, called_from);
 213      -                tem_safe_align_cursor(tem);
 214      -        }
      199 +        else
      200 +                tem_safe_pix_cursor(tem, VIS_GET_CURSOR, credp, called_from);
      201 +        tem_safe_align_cursor(tem);
 215  202  }
 216  203  
 217  204  /*
 218  205   * This entry point handles output requests from restricted contexts like
 219  206   * kmdb, where services like mutexes are not available. This function
 220  207   * is entered when OBP or when a kernel debugger (such as kmdb)
 221  208   * are generating console output.  In those cases, power management
 222  209   * concerns are handled by the abort sequence initiation (ie. when
 223  210   * the user hits L1+A or the equivalent to enter OBP or the debugger.).
 224  211   * It is also entered when the kernel is panicing.
 225  212   */
 226  213  void
 227  214  tem_safe_polled_write(
 228  215      tem_vt_state_t tem_arg,
 229  216      uchar_t *buf,
 230  217      int len)
 231  218  {
 232  219          struct tem_vt_state *tem = (struct tem_vt_state *)tem_arg;
 233  220  
 234  221  #ifdef  __lock_lint
 235  222          _NOTE(NO_COMPETING_THREADS_NOW)
 236  223          _NOTE(NO_COMPETING_THREADS_AS_SIDE_EFFECT)
 237  224  #endif
 238  225  
 239  226          if (!tem->tvs_initialized) {
 240  227                  return;
 241  228          }
  
    | 
      ↓ open down ↓ | 
    17 lines elided | 
    
      ↑ open up ↑ | 
  
 242  229  
 243  230          tem_safe_check_first_time(tem, kcred, CALLED_FROM_STANDALONE);
 244  231          tem_safe_terminal_emulate(tem, buf, len, NULL, CALLED_FROM_STANDALONE);
 245  232  }
 246  233  
 247  234  /* Process partial UTF-8 sequence. */
 248  235  static void
 249  236  tem_safe_input_partial(struct tem_vt_state *tem, cred_t *credp,
 250  237      enum called_from called_from)
 251  238  {
 252      -        int i;
      239 +        unsigned i;
 253  240          uint8_t c;
 254  241  
 255  242          if (tem->tvs_utf8_left == 0)
 256  243                  return;
 257  244  
 258  245          for (i = 0; i < sizeof (tem->tvs_utf8_partial); i++) {
 259  246                  c = (tem->tvs_utf8_partial >> (24 - (i << 3))) & 0xff;
 260  247                  if (c != 0) {
 261  248                          tem_safe_parse(tem, c, credp, called_from);
 262  249                  }
 263  250          }
 264  251          tem->tvs_utf8_left = 0;
 265  252          tem->tvs_utf8_partial = 0;
 266  253  }
 267  254  
 268  255  /*
 269  256   * Handle UTF-8 sequences.
 270  257   */
 271  258  static void
 272  259  tem_safe_input_byte(struct tem_vt_state *tem, uchar_t c, cred_t *credp,
 273  260      enum called_from called_from)
 274  261  {
 275  262          /*
 276  263           * Check for UTF-8 code points. In case of error fall back to
 277  264           * 8-bit code. As we only have 8859-1 fonts for console, this will set
 278  265           * the limits on what chars we actually can display, therefore we
 279  266           * have to return to this code once we have solved the font issue.
 280  267           */
 281  268          if ((c & 0x80) == 0x00) {
 282  269                  /* One-byte sequence. */
 283  270                  tem_safe_input_partial(tem, credp, called_from);
 284  271                  tem_safe_parse(tem, c, credp, called_from);
 285  272                  return;
 286  273          }
 287  274          if ((c & 0xe0) == 0xc0) {
 288  275                  /* Two-byte sequence. */
 289  276                  tem_safe_input_partial(tem, credp, called_from);
 290  277                  tem->tvs_utf8_left = 1;
 291  278                  tem->tvs_utf8_partial = c;
 292  279                  return;
 293  280          }
 294  281          if ((c & 0xf0) == 0xe0) {
 295  282                  /* Three-byte sequence. */
 296  283                  tem_safe_input_partial(tem, credp, called_from);
 297  284                  tem->tvs_utf8_left = 2;
 298  285                  tem->tvs_utf8_partial = c;
 299  286                  return;
 300  287          }
 301  288          if ((c & 0xf8) == 0xf0) {
 302  289                  /* Four-byte sequence. */
 303  290                  tem_safe_input_partial(tem, credp, called_from);
 304  291                  tem->tvs_utf8_left = 3;
 305  292                  tem->tvs_utf8_partial = c;
 306  293                  return;
 307  294          }
 308  295          if ((c & 0xc0) == 0x80) {
 309  296                  /* Invalid state? */
 310  297                  if (tem->tvs_utf8_left == 0) {
 311  298                          tem_safe_parse(tem, c, credp, called_from);
 312  299                          return;
 313  300                  }
 314  301                  tem->tvs_utf8_left--;
 315  302                  tem->tvs_utf8_partial = (tem->tvs_utf8_partial << 8) | c;
 316  303                  if (tem->tvs_utf8_left == 0) {
 317  304                          tem_char_t v, u;
 318  305                          uint8_t b;
 319  306  
 320  307                          /*
 321  308                           * Transform the sequence of 2 to 4 bytes to
 322  309                           * unicode number.
 323  310                           */
 324  311                          v = 0;
 325  312                          u = tem->tvs_utf8_partial;
 326  313                          b = (u >> 24) & 0xff;
 327  314                          if (b != 0) {           /* Four-byte sequence */
 328  315                                  v = b & 0x07;
 329  316                                  b = (u >> 16) & 0xff;
 330  317                                  v = (v << 6) | (b & 0x3f);
 331  318                                  b = (u >> 8) & 0xff;
 332  319                                  v = (v << 6) | (b & 0x3f);
 333  320                                  b = u & 0xff;
 334  321                                  v = (v << 6) | (b & 0x3f);
 335  322                          } else if ((b = (u >> 16) & 0xff) != 0) {
 336  323                                  v = b & 0x0f;   /* Three-byte sequence */
  
    | 
      ↓ open down ↓ | 
    74 lines elided | 
    
      ↑ open up ↑ | 
  
 337  324                                  b = (u >> 8) & 0xff;
 338  325                                  v = (v << 6) | (b & 0x3f);
 339  326                                  b = u & 0xff;
 340  327                                  v = (v << 6) | (b & 0x3f);
 341  328                          } else if ((b = (u >> 8) & 0xff) != 0) {
 342  329                                  v = b & 0x1f;   /* Two-byte sequence */
 343  330                                  b = u & 0xff;
 344  331                                  v = (v << 6) | (b & 0x3f);
 345  332                          }
 346  333  
 347      -                        /* Use '?' as replacement if needed. */
 348      -                        if (v > 0xff)
 349      -                                v = '?';
 350  334                          tem_safe_parse(tem, v, credp, called_from);
 351  335                          tem->tvs_utf8_partial = 0;
 352  336                  }
 353  337                  return;
 354  338          }
 355  339          /* Anything left is illegal in UTF-8 sequence. */
 356  340          tem_safe_input_partial(tem, credp, called_from);
 357  341          tem_safe_parse(tem, c, credp, called_from);
 358  342  }
 359  343  
 360  344  /*
 361  345   * This is the main entry point into the terminal emulator.
 362  346   *
 363  347   * For each data message coming downstream, ANSI assumes that it is composed
 364  348   * of ASCII characters, which are treated as a byte-stream input to the
 365  349   * parsing state machine. All data is parsed immediately -- there is
 366  350   * no enqueing.
 367  351   */
 368  352  void
 369  353  tem_safe_terminal_emulate(
 370  354      struct tem_vt_state *tem,
 371  355      uchar_t *buf,
 372  356      int len,
 373  357      cred_t *credp,
 374  358      enum called_from called_from)
 375  359  {
 376  360  
 377  361          ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
 378  362              called_from == CALLED_FROM_STANDALONE);
 379  363  
 380  364          if (tem->tvs_isactive)
 381  365                  tem_safe_callback_cursor(tem,
 382  366                      VIS_HIDE_CURSOR, credp, called_from);
 383  367  
 384  368          for (; len > 0; len--, buf++)
 385  369                  tem_safe_input_byte(tem, *buf, credp, called_from);
 386  370  
 387  371          /*
 388  372           * Send the data we just got to the framebuffer.
 389  373           */
 390  374          tem_safe_send_data(tem, credp, called_from);
 391  375  
 392  376          if (tem->tvs_isactive)
 393  377                  tem_safe_callback_cursor(tem,
 394  378                      VIS_DISPLAY_CURSOR, credp, called_from);
 395  379  }
 396  380  
 397  381  /*
 398  382   * Display an rectangular image on the frame buffer using the
 399  383   * mechanism appropriate for the system state being called
 400  384   * from quiesced or normal (ie. use polled I/O vs. layered ioctls)
 401  385   */
 402  386  static void
 403  387  tems_safe_display(struct vis_consdisplay *pda, cred_t *credp,
 404  388      enum called_from called_from)
 405  389  {
 406  390          if (called_from == CALLED_FROM_STANDALONE)
 407  391                  tems.ts_fb_polledio->display(tems.ts_fb_polledio->arg, pda);
 408  392          else
 409  393                  tems_display_layered(pda, credp);
 410  394  }
 411  395  
 412  396  /*
 413  397   * Copy a rectangle from one location to another on the frame buffer
 414  398   * using the mechanism appropriate for the system state being called
 415  399   * from, quiesced or normal (ie. use polled I/O vs. layered ioctls)
 416  400   */
 417  401  void
 418  402  tems_safe_copy(struct vis_conscopy *pca, cred_t *credp,
 419  403      enum called_from called_from)
 420  404  {
 421  405          if (called_from == CALLED_FROM_STANDALONE)
 422  406                  tems.ts_fb_polledio->copy(tems.ts_fb_polledio->arg, pca);
 423  407          else
 424  408                  tems_copy_layered(pca, credp);
 425  409  }
 426  410  
 427  411  /*
 428  412   * Display or hide a rectangular block text cursor of a specificsize
 429  413   * at a specific location on frame buffer* using the mechanism
 430  414   * appropriate for the system state being called from, quisced or
 431  415   * normal (ie. use polled I/O vs. layered ioctls).
 432  416   */
 433  417  static void
 434  418  tems_safe_cursor(struct vis_conscursor *pca, cred_t *credp,
 435  419      enum called_from called_from)
 436  420  {
 437  421          if (called_from == CALLED_FROM_STANDALONE)
 438  422                  tems.ts_fb_polledio->cursor(tems.ts_fb_polledio->arg, pca);
  
    | 
      ↓ open down ↓ | 
    79 lines elided | 
    
      ↑ open up ↑ | 
  
 439  423          else
 440  424                  tems_cursor_layered(pca, credp);
 441  425  }
 442  426  
 443  427  /*
 444  428   * send the appropriate control message or set state based on the
 445  429   * value of the control character ch
 446  430   */
 447  431  
 448  432  static void
 449      -tem_safe_control(struct tem_vt_state *tem, uchar_t ch, cred_t *credp,
      433 +tem_safe_control(struct tem_vt_state *tem, tem_char_t ch, cred_t *credp,
 450  434      enum called_from called_from)
 451  435  {
 452  436          tem->tvs_state = A_STATE_START;
 453  437          switch (ch) {
 454  438          case A_BEL:
 455  439                  tem_safe_bell(tem, called_from);
 456  440                  break;
 457  441  
 458  442          case A_BS:
 459  443                  tem_safe_mv_cursor(tem,
 460  444                      tem->tvs_c_cursor.row,
 461  445                      tem->tvs_c_cursor.col - 1,
 462  446                      credp, called_from);
 463  447                  break;
 464  448  
 465  449          case A_HT:
 466  450                  tem_safe_tab(tem, credp, called_from);
 467  451                  break;
 468  452  
 469  453          case A_NL:
 470  454                  /*
 471  455                   * tem_safe_send_data(tem, credp, called_from);
 472  456                   * tem_safe_new_line(tem, credp, called_from);
 473  457                   * break;
 474  458                   */
 475  459  
 476  460          case A_VT:
 477  461                  tem_safe_send_data(tem, credp, called_from);
 478  462                  tem_safe_lf(tem, credp, called_from);
 479  463                  break;
 480  464  
 481  465          case A_FF:
 482  466                  tem_safe_send_data(tem, credp, called_from);
 483  467                  tem_safe_cls(tem, credp, called_from);
 484  468                  break;
 485  469  
 486  470          case A_CR:
 487  471                  tem_safe_send_data(tem, credp, called_from);
 488  472                  tem_safe_cr(tem);
 489  473                  break;
 490  474  
 491  475          case A_ESC:
 492  476                  tem->tvs_state = A_STATE_ESC;
 493  477                  break;
 494  478  
 495  479          case A_CSI:
 496  480                  {
 497  481                          int i;
  
    | 
      ↓ open down ↓ | 
    38 lines elided | 
    
      ↑ open up ↑ | 
  
 498  482                          tem->tvs_curparam = 0;
 499  483                          tem->tvs_paramval = 0;
 500  484                          tem->tvs_gotparam = B_FALSE;
 501  485                          /* clear the parameters */
 502  486                          for (i = 0; i < TEM_MAXPARAMS; i++)
 503  487                                  tem->tvs_params[i] = -1;
 504  488                          tem->tvs_state = A_STATE_CSI;
 505  489                  }
 506  490                  break;
 507  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 +
 508  505          case A_GS:
 509  506                  tem_safe_back_tab(tem, credp, called_from);
 510  507                  break;
 511  508  
 512  509          default:
 513  510                  break;
 514  511          }
 515  512  }
 516  513  
 517  514  
 518  515  /*
 519  516   * if parameters [0..count - 1] are not set, set them to the value
 520  517   * of newparam.
 521  518   */
 522  519  
 523  520  static void
 524  521  tem_safe_setparam(struct tem_vt_state *tem, int count, int newparam)
 525  522  {
 526  523          int i;
 527  524  
 528  525          for (i = 0; i < count; i++) {
 529  526                  if (tem->tvs_params[i] == -1)
 530  527                          tem->tvs_params[i] = newparam;
 531  528          }
 532  529  }
 533  530  
 534  531  
 535  532  /*
 536  533   * select graphics mode based on the param vals stored in a_params
 537  534   */
 538  535  static void
 539  536  tem_safe_selgraph(struct tem_vt_state *tem)
 540  537  {
 541  538          int curparam;
 542  539          int count = 0;
 543  540          int param;
 544  541  
 545  542          tem->tvs_state = A_STATE_START;
 546  543  
 547  544          curparam = tem->tvs_curparam;
 548  545          do {
 549  546                  param = tem->tvs_params[count];
 550  547  
 551  548                  switch (param) {
 552  549                  case -1:
 553  550                  case 0:
 554  551                          /* reset to initial normal settings */
 555  552                          tem->tvs_fg_color = tems.ts_init_color.fg_color;
 556  553                          tem->tvs_bg_color = tems.ts_init_color.bg_color;
 557  554                          tem->tvs_flags = tems.ts_init_color.a_flags;
  
    | 
      ↓ open down ↓ | 
    40 lines elided | 
    
      ↑ open up ↑ | 
  
 558  555                          break;
 559  556  
 560  557                  case 1: /* Bold Intense */
 561  558                          tem->tvs_flags |= TEM_ATTR_BOLD;
 562  559                          break;
 563  560  
 564  561                  case 2: /* Faint Intense */
 565  562                          tem->tvs_flags &= ~TEM_ATTR_BOLD;
 566  563                          break;
 567  564  
      565 +                case 4: /* Underline */
      566 +                        tem->tvs_flags |= TEM_ATTR_UNDERLINE;
      567 +                        break;
 568  568                  case 5: /* Blink */
 569  569                          tem->tvs_flags |= TEM_ATTR_BLINK;
 570  570                          break;
 571  571  
 572  572                  case 7: /* Reverse video */
 573  573                          if (tem->tvs_flags & TEM_ATTR_SCREEN_REVERSE) {
 574  574                                  tem->tvs_flags &= ~TEM_ATTR_REVERSE;
 575  575                          } else {
 576  576                                  tem->tvs_flags |= TEM_ATTR_REVERSE;
 577  577                          }
 578  578                          break;
 579  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 +
 580  600                  case 30: /* black       (grey)          foreground */
 581  601                  case 31: /* red         (light red)     foreground */
 582  602                  case 32: /* green       (light green)   foreground */
 583  603                  case 33: /* brown       (yellow)        foreground */
 584  604                  case 34: /* blue        (light blue)    foreground */
 585  605                  case 35: /* magenta     (light magenta) foreground */
 586  606                  case 36: /* cyan        (light cyan)    foreground */
 587  607                  case 37: /* white       (bright white)  foreground */
 588  608                          tem->tvs_fg_color = param - 30;
 589  609                          tem->tvs_flags &= ~TEM_ATTR_BRIGHT_FG;
 590  610                          break;
 591  611  
 592  612                  case 39:
 593  613                          /*
 594  614                           * Reset the foreground colour and brightness.
 595  615                           */
 596  616                          tem->tvs_fg_color = tems.ts_init_color.fg_color;
 597  617                          if (tems.ts_init_color.a_flags & TEM_ATTR_BRIGHT_FG)
 598  618                                  tem->tvs_flags |= TEM_ATTR_BRIGHT_FG;
 599  619                          else
 600  620                                  tem->tvs_flags &= ~TEM_ATTR_BRIGHT_FG;
 601  621                          break;
 602  622  
 603  623                  case 40: /* black       (grey)          background */
 604  624                  case 41: /* red         (light red)     background */
 605  625                  case 42: /* green       (light green)   background */
 606  626                  case 43: /* brown       (yellow)        background */
 607  627                  case 44: /* blue        (light blue)    background */
 608  628                  case 45: /* magenta     (light magenta) background */
 609  629                  case 46: /* cyan        (light cyan)    background */
 610  630                  case 47: /* white       (bright white)  background */
 611  631                          tem->tvs_bg_color = param - 40;
 612  632                          tem->tvs_flags &= ~TEM_ATTR_BRIGHT_BG;
 613  633                          break;
 614  634  
 615  635                  case 49:
 616  636                          /*
 617  637                           * Reset the background colour and brightness.
 618  638                           */
 619  639                          tem->tvs_bg_color = tems.ts_init_color.bg_color;
 620  640                          if (tems.ts_init_color.a_flags & TEM_ATTR_BRIGHT_BG)
 621  641                                  tem->tvs_flags |= TEM_ATTR_BRIGHT_BG;
 622  642                          else
 623  643                                  tem->tvs_flags &= ~TEM_ATTR_BRIGHT_BG;
 624  644                          break;
 625  645  
 626  646                  case 90: /* black       (grey)          foreground */
 627  647                  case 91: /* red         (light red)     foreground */
 628  648                  case 92: /* green       (light green)   foreground */
 629  649                  case 93: /* brown       (yellow)        foreground */
 630  650                  case 94: /* blue        (light blue)    foreground */
 631  651                  case 95: /* magenta     (light magenta) foreground */
 632  652                  case 96: /* cyan        (light cyan)    foreground */
 633  653                  case 97: /* white       (bright white)  foreground */
 634  654                          tem->tvs_fg_color = param - 90;
 635  655                          tem->tvs_flags |= TEM_ATTR_BRIGHT_FG;
 636  656                          break;
 637  657  
 638  658                  case 100: /* black      (grey)          background */
 639  659                  case 101: /* red        (light red)     background */
 640  660                  case 102: /* green      (light green)   background */
 641  661                  case 103: /* brown      (yellow)        background */
 642  662                  case 104: /* blue       (light blue)    background */
 643  663                  case 105: /* magenta    (light magenta) background */
 644  664                  case 106: /* cyan       (light cyan)    background */
 645  665                  case 107: /* white      (bright white)  background */
 646  666                          tem->tvs_bg_color = param - 100;
 647  667                          tem->tvs_flags |= TEM_ATTR_BRIGHT_BG;
 648  668                          break;
 649  669  
 650  670                  default:
 651  671                          break;
 652  672                  }
 653  673                  count++;
 654  674                  curparam--;
 655  675  
  
    | 
      ↓ open down ↓ | 
    66 lines elided | 
    
      ↑ open up ↑ | 
  
 656  676          } while (curparam > 0);
 657  677  }
 658  678  
 659  679  /*
 660  680   * perform the appropriate action for the escape sequence
 661  681   *
 662  682   * General rule:  This code does not validate the arguments passed.
 663  683   *                It assumes that the next lower level will do so.
 664  684   */
 665  685  static void
 666      -tem_safe_chkparam(struct tem_vt_state *tem, uchar_t ch, cred_t *credp,
      686 +tem_safe_chkparam(struct tem_vt_state *tem, tem_char_t ch, cred_t *credp,
 667  687      enum called_from called_from)
 668  688  {
 669  689          int     i;
 670  690          int     row;
 671  691          int     col;
 672  692  
 673  693          ASSERT((called_from == CALLED_FROM_STANDALONE) ||
 674  694              MUTEX_HELD(&tem->tvs_lock));
 675  695  
 676  696          row = tem->tvs_c_cursor.row;
 677  697          col = tem->tvs_c_cursor.col;
 678  698  
 679  699          switch (ch) {
 680  700  
 681  701          case 'm': /* select terminal graphics mode */
 682  702                  tem_safe_send_data(tem, credp, called_from);
 683  703                  tem_safe_selgraph(tem);
 684  704                  break;
 685  705  
 686  706          case '@':               /* insert char */
 687  707                  tem_safe_setparam(tem, 1, 1);
 688  708                  tem_safe_shift(tem, tem->tvs_params[0], TEM_SHIFT_RIGHT,
 689  709                      credp, called_from);
 690  710                  break;
 691  711  
 692  712          case 'A':               /* cursor up */
 693  713                  tem_safe_setparam(tem, 1, 1);
 694  714                  tem_safe_mv_cursor(tem, row - tem->tvs_params[0], col,
 695  715                      credp, called_from);
 696  716                  break;
 697  717  
 698  718          case 'd':               /* VPA - vertical position absolute */
 699  719                  tem_safe_setparam(tem, 1, 1);
 700  720                  tem_safe_mv_cursor(tem, tem->tvs_params[0] - 1, col,
 701  721                      credp, called_from);
 702  722                  break;
 703  723  
 704  724          case 'e':               /* VPR - vertical position relative */
 705  725          case 'B':               /* cursor down */
 706  726                  tem_safe_setparam(tem, 1, 1);
 707  727                  tem_safe_mv_cursor(tem, row + tem->tvs_params[0], col,
 708  728                      credp, called_from);
 709  729                  break;
 710  730  
 711  731          case 'a':               /* HPR - horizontal position relative */
 712  732          case 'C':               /* cursor right */
 713  733                  tem_safe_setparam(tem, 1, 1);
 714  734                  tem_safe_mv_cursor(tem, row, col + tem->tvs_params[0],
 715  735                      credp, called_from);
 716  736                  break;
 717  737  
 718  738          case '`':               /* HPA - horizontal position absolute */
 719  739                  tem_safe_setparam(tem, 1, 1);
 720  740                  tem_safe_mv_cursor(tem, row, tem->tvs_params[0] - 1,
 721  741                      credp, called_from);
 722  742                  break;
 723  743  
 724  744          case 'D':               /* cursor left */
 725  745                  tem_safe_setparam(tem, 1, 1);
 726  746                  tem_safe_mv_cursor(tem, row, col - tem->tvs_params[0],
 727  747                      credp, called_from);
 728  748                  break;
 729  749  
 730  750          case 'E':               /* CNL cursor next line */
 731  751                  tem_safe_setparam(tem, 1, 1);
 732  752                  tem_safe_mv_cursor(tem, row + tem->tvs_params[0], 0,
 733  753                      credp, called_from);
 734  754                  break;
 735  755  
 736  756          case 'F':               /* CPL cursor previous line */
 737  757                  tem_safe_setparam(tem, 1, 1);
 738  758                  tem_safe_mv_cursor(tem, row - tem->tvs_params[0], 0,
 739  759                      credp, called_from);
 740  760                  break;
 741  761  
 742  762          case 'G':               /* cursor horizontal position */
 743  763                  tem_safe_setparam(tem, 1, 1);
 744  764                  tem_safe_mv_cursor(tem, row, tem->tvs_params[0] - 1,
 745  765                      credp, called_from);
 746  766                  break;
 747  767  
 748  768          case 'g':               /* clear tabs */
 749  769                  tem_safe_setparam(tem, 1, 0);
 750  770                  tem_safe_clear_tabs(tem, tem->tvs_params[0]);
 751  771                  break;
 752  772  
 753  773          case 'f':               /* HVP Horizontal and Vertical Position */
 754  774          case 'H':               /* CUP position cursor */
 755  775                  tem_safe_setparam(tem, 2, 1);
 756  776                  tem_safe_mv_cursor(tem,
 757  777                      tem->tvs_params[0] - 1,
 758  778                      tem->tvs_params[1] - 1,
 759  779                      credp, called_from);
 760  780                  break;
 761  781  
 762  782          case 'I':               /* CHT - Cursor Horizontal Tab */
 763  783                  /* Not implemented */
 764  784                  break;
 765  785  
 766  786          case 'J':               /* ED - Erase in Display */
 767  787                  tem_safe_send_data(tem, credp, called_from);
 768  788                  tem_safe_setparam(tem, 1, 0);
 769  789                  switch (tem->tvs_params[0]) {
 770  790                  case 0:
 771  791                          /* erase cursor to end of screen */
 772  792                          /* FIRST erase cursor to end of line */
 773  793                          tem_safe_clear_chars(tem,
 774  794                              tems.ts_c_dimension.width -
 775  795                              tem->tvs_c_cursor.col,
 776  796                              tem->tvs_c_cursor.row,
 777  797                              tem->tvs_c_cursor.col, credp, called_from);
 778  798  
 779  799                          /* THEN erase lines below the cursor */
 780  800                          for (row = tem->tvs_c_cursor.row + 1;
 781  801                              row < tems.ts_c_dimension.height;
 782  802                              row++) {
 783  803                                  tem_safe_clear_chars(tem,
 784  804                                      tems.ts_c_dimension.width,
 785  805                                      row, 0, credp, called_from);
 786  806                          }
 787  807                          break;
 788  808  
 789  809                  case 1:
 790  810                          /* erase beginning of screen to cursor */
 791  811                          /* FIRST erase lines above the cursor */
 792  812                          for (row = 0;
 793  813                              row < tem->tvs_c_cursor.row;
 794  814                              row++) {
 795  815                                  tem_safe_clear_chars(tem,
 796  816                                      tems.ts_c_dimension.width,
 797  817                                      row, 0, credp, called_from);
 798  818                          }
 799  819                          /* THEN erase beginning of line to cursor */
 800  820                          tem_safe_clear_chars(tem,
 801  821                              tem->tvs_c_cursor.col + 1,
 802  822                              tem->tvs_c_cursor.row,
 803  823                              0, credp, called_from);
 804  824                          break;
 805  825  
 806  826                  case 2:
 807  827                          /* erase whole screen */
 808  828                          for (row = 0;
 809  829                              row < tems.ts_c_dimension.height;
 810  830                              row++) {
 811  831                                  tem_safe_clear_chars(tem,
 812  832                                      tems.ts_c_dimension.width,
 813  833                                      row, 0, credp, called_from);
 814  834                          }
 815  835                          break;
 816  836                  }
 817  837                  break;
 818  838  
 819  839          case 'K':               /* EL - Erase in Line */
 820  840                  tem_safe_send_data(tem, credp, called_from);
 821  841                  tem_safe_setparam(tem, 1, 0);
 822  842                  switch (tem->tvs_params[0]) {
 823  843                  case 0:
 824  844                          /* erase cursor to end of line */
 825  845                          tem_safe_clear_chars(tem,
 826  846                              (tems.ts_c_dimension.width -
 827  847                              tem->tvs_c_cursor.col),
 828  848                              tem->tvs_c_cursor.row,
 829  849                              tem->tvs_c_cursor.col,
 830  850                              credp, called_from);
 831  851                          break;
 832  852  
 833  853                  case 1:
 834  854                          /* erase beginning of line to cursor */
 835  855                          tem_safe_clear_chars(tem,
 836  856                              tem->tvs_c_cursor.col + 1,
 837  857                              tem->tvs_c_cursor.row,
 838  858                              0, credp, called_from);
 839  859                          break;
 840  860  
 841  861                  case 2:
 842  862                          /* erase whole line */
 843  863                          tem_safe_clear_chars(tem,
 844  864                              tems.ts_c_dimension.width,
 845  865                              tem->tvs_c_cursor.row,
 846  866                              0, credp, called_from);
 847  867                          break;
 848  868                  }
 849  869                  break;
 850  870  
 851  871          case 'L':               /* insert line */
 852  872                  tem_safe_send_data(tem, credp, called_from);
 853  873                  tem_safe_setparam(tem, 1, 1);
 854  874                  tem_safe_scroll(tem,
 855  875                      tem->tvs_c_cursor.row,
 856  876                      tems.ts_c_dimension.height - 1,
 857  877                      tem->tvs_params[0], TEM_SCROLL_DOWN,
 858  878                      credp, called_from);
 859  879                  break;
 860  880  
 861  881          case 'M':               /* delete line */
 862  882                  tem_safe_send_data(tem, credp, called_from);
 863  883                  tem_safe_setparam(tem, 1, 1);
 864  884                  tem_safe_scroll(tem,
 865  885                      tem->tvs_c_cursor.row,
 866  886                      tems.ts_c_dimension.height - 1,
 867  887                      tem->tvs_params[0], TEM_SCROLL_UP,
 868  888                      credp, called_from);
 869  889                  break;
 870  890  
 871  891          case 'P':               /* DCH - delete char */
 872  892                  tem_safe_setparam(tem, 1, 1);
 873  893                  tem_safe_shift(tem, tem->tvs_params[0], TEM_SHIFT_LEFT,
 874  894                      credp, called_from);
 875  895                  break;
 876  896  
 877  897          case 'S':               /* scroll up */
 878  898                  tem_safe_send_data(tem, credp, called_from);
 879  899                  tem_safe_setparam(tem, 1, 1);
 880  900                  tem_safe_scroll(tem, 0,
 881  901                      tems.ts_c_dimension.height - 1,
 882  902                      tem->tvs_params[0], TEM_SCROLL_UP,
 883  903                      credp, called_from);
 884  904                  break;
 885  905  
 886  906          case 'T':               /* scroll down */
 887  907                  tem_safe_send_data(tem, credp, called_from);
 888  908                  tem_safe_setparam(tem, 1, 1);
 889  909                  tem_safe_scroll(tem, 0,
 890  910                      tems.ts_c_dimension.height - 1,
 891  911                      tem->tvs_params[0], TEM_SCROLL_DOWN,
 892  912                      credp, called_from);
 893  913                  break;
 894  914  
 895  915          case 'X':               /* erase char */
 896  916                  tem_safe_setparam(tem, 1, 1);
 897  917                  tem_safe_clear_chars(tem,
 898  918                      tem->tvs_params[0],
 899  919                      tem->tvs_c_cursor.row,
 900  920                      tem->tvs_c_cursor.col,
 901  921                      credp, called_from);
 902  922                  break;
 903  923  
 904  924          case 'Z':               /* cursor backward tabulation */
 905  925                  tem_safe_setparam(tem, 1, 1);
 906  926  
 907  927                  /*
 908  928                   * Rule exception - We do sanity checking here.
 909  929                   *
 910  930                   * Restrict the count to a sane value to keep from
 911  931                   * looping for a long time.  There can't be more than one
 912  932                   * tab stop per column, so use that as a limit.
 913  933                   */
 914  934                  if (tem->tvs_params[0] > tems.ts_c_dimension.width)
 915  935                          tem->tvs_params[0] = tems.ts_c_dimension.width;
 916  936  
 917  937                  for (i = 0; i < tem->tvs_params[0]; i++)
 918  938                          tem_safe_back_tab(tem, credp, called_from);
  
    | 
      ↓ open down ↓ | 
    242 lines elided | 
    
      ↑ open up ↑ | 
  
 919  939                  break;
 920  940          }
 921  941          tem->tvs_state = A_STATE_START;
 922  942  }
 923  943  
 924  944  
 925  945  /*
 926  946   * Gather the parameters of an ANSI escape sequence
 927  947   */
 928  948  static void
 929      -tem_safe_getparams(struct tem_vt_state *tem, uchar_t ch,
      949 +tem_safe_getparams(struct tem_vt_state *tem, tem_char_t ch,
 930  950      cred_t *credp, enum called_from called_from)
 931  951  {
 932  952          ASSERT((called_from == CALLED_FROM_STANDALONE) ||
 933  953              MUTEX_HELD(&tem->tvs_lock));
 934  954  
 935  955          if (ch >= '0' && ch <= '9') {
 936  956                  tem->tvs_paramval = ((tem->tvs_paramval * 10) + (ch - '0'));
 937  957                  tem->tvs_gotparam = B_TRUE;  /* Remember got parameter */
 938  958                  return; /* Return immediately */
 939  959          } else if (tem->tvs_state == A_STATE_CSI_EQUAL ||
 940  960              tem->tvs_state == A_STATE_CSI_QMARK) {
 941  961                  tem->tvs_state = A_STATE_START;
 942  962          } else {
 943  963                  if (tem->tvs_curparam < TEM_MAXPARAMS) {
 944  964                          if (tem->tvs_gotparam) {
 945  965                                  /* get the parameter value */
 946  966                                  tem->tvs_params[tem->tvs_curparam] =
 947  967                                      tem->tvs_paramval;
 948  968                          }
 949  969                          tem->tvs_curparam++;
 950  970                  }
 951  971  
 952  972                  if (ch == ';') {
 953  973                          /* Restart parameter search */
  
    | 
      ↓ open down ↓ | 
    14 lines elided | 
    
      ↑ open up ↑ | 
  
 954  974                          tem->tvs_gotparam = B_FALSE;
 955  975                          tem->tvs_paramval = 0; /* No parame value yet */
 956  976                  } else {
 957  977                          /* Handle escape sequence */
 958  978                          tem_safe_chkparam(tem, ch, credp, called_from);
 959  979                  }
 960  980          }
 961  981  }
 962  982  
 963  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 +/*
 964 1039   * Add character to internal buffer.
 965 1040   * When its full, send it to the next layer.
 966 1041   */
 967 1042  
 968 1043  static void
 969      -tem_safe_outch(struct tem_vt_state *tem, uchar_t ch,
     1044 +tem_safe_outch(struct tem_vt_state *tem, tem_char_t ch,
 970 1045      cred_t *credp, enum called_from called_from)
 971 1046  {
     1047 +        text_color_t fg;
     1048 +        text_color_t bg;
     1049 +        text_attr_t attr;
 972 1050  
 973 1051          ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
 974 1052              called_from == CALLED_FROM_STANDALONE);
 975 1053  
 976 1054          /* buffer up the character until later */
 977      -
 978      -        tem->tvs_outbuf[tem->tvs_outindex++] = ch;
     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++;
 979 1060          tem->tvs_c_cursor.col++;
 980 1061          if (tem->tvs_c_cursor.col >= tems.ts_c_dimension.width) {
 981 1062                  tem_safe_send_data(tem, credp, called_from);
 982 1063                  tem_safe_new_line(tem, credp, called_from);
 983 1064          }
 984 1065  }
 985 1066  
 986 1067  static void
 987 1068  tem_safe_new_line(struct tem_vt_state *tem,
 988 1069      cred_t *credp, enum called_from called_from)
 989 1070  {
 990 1071          tem_safe_cr(tem);
 991 1072          tem_safe_lf(tem, credp, called_from);
 992 1073  }
 993 1074  
 994 1075  static void
 995 1076  tem_safe_cr(struct tem_vt_state *tem)
 996 1077  {
 997 1078          tem->tvs_c_cursor.col = 0;
 998 1079          tem_safe_align_cursor(tem);
 999 1080  }
1000 1081  
1001 1082  static void
1002 1083  tem_safe_lf(struct tem_vt_state *tem,
1003 1084      cred_t *credp, enum called_from called_from)
1004 1085  {
1005 1086          int row;
1006 1087  
1007 1088          ASSERT((called_from == CALLED_FROM_STANDALONE) ||
1008 1089              MUTEX_HELD(&tem->tvs_lock));
1009 1090  
1010 1091          /*
1011 1092           * Sanity checking notes:
1012 1093           * . a_nscroll was validated when it was set.
1013 1094           * . Regardless of that, tem_safe_scroll and tem_safe_mv_cursor
1014 1095           *   will prevent anything bad from happening.
1015 1096           */
1016 1097          row = tem->tvs_c_cursor.row + 1;
1017 1098  
1018 1099          if (row >= tems.ts_c_dimension.height) {
1019 1100                  if (tem->tvs_nscroll != 0) {
1020 1101                          tem_safe_scroll(tem, 0,
1021 1102                              tems.ts_c_dimension.height - 1,
1022 1103                              tem->tvs_nscroll, TEM_SCROLL_UP,
1023 1104                              credp, called_from);
1024 1105                          row = tems.ts_c_dimension.height -
1025 1106                              tem->tvs_nscroll;
1026 1107                  } else {        /* no scroll */
1027 1108                          /*
1028 1109                           * implement Esc[#r when # is zero.  This means no
1029 1110                           * scroll but just return cursor to top of screen,
1030 1111                           * do not clear screen.
1031 1112                           */
1032 1113                          row = 0;
1033 1114                  }
1034 1115          }
1035 1116  
1036 1117          tem_safe_mv_cursor(tem, row, tem->tvs_c_cursor.col,
1037 1118              credp, called_from);
1038 1119  
1039 1120          if (tem->tvs_nscroll == 0) {
1040 1121                  /* erase rest of cursor line */
1041 1122                  tem_safe_clear_chars(tem,
1042 1123                      tems.ts_c_dimension.width -
1043 1124                      tem->tvs_c_cursor.col,
1044 1125                      tem->tvs_c_cursor.row,
1045 1126                      tem->tvs_c_cursor.col,
1046 1127                      credp, called_from);
  
    | 
      ↓ open down ↓ | 
    58 lines elided | 
    
      ↑ open up ↑ | 
  
1047 1128  
1048 1129          }
1049 1130  
1050 1131          tem_safe_align_cursor(tem);
1051 1132  }
1052 1133  
1053 1134  static void
1054 1135  tem_safe_send_data(struct tem_vt_state *tem, cred_t *credp,
1055 1136      enum called_from called_from)
1056 1137  {
1057      -        text_color_t fg_color;
1058      -        text_color_t bg_color;
1059      -
1060 1138          ASSERT((called_from == CALLED_FROM_STANDALONE) ||
1061 1139              MUTEX_HELD(&tem->tvs_lock));
1062 1140  
1063 1141          if (tem->tvs_outindex == 0) {
1064 1142                  tem_safe_align_cursor(tem);
1065 1143                  return;
1066 1144          }
1067 1145  
1068      -        tem_safe_get_color(tem, &fg_color, &bg_color, TEM_ATTR_REVERSE);
1069 1146          tem_safe_virtual_display(tem,
1070 1147              tem->tvs_outbuf, tem->tvs_outindex,
1071      -            tem->tvs_s_cursor.row, tem->tvs_s_cursor.col,
1072      -            fg_color, bg_color);
     1148 +            tem->tvs_s_cursor.row, tem->tvs_s_cursor.col);
1073 1149  
1074 1150          if (tem->tvs_isactive) {
1075 1151                  /*
1076 1152                   * Call the primitive to render this data.
1077 1153                   */
1078 1154                  tem_safe_callback_display(tem,
1079 1155                      tem->tvs_outbuf, tem->tvs_outindex,
1080 1156                      tem->tvs_s_cursor.row, tem->tvs_s_cursor.col,
1081      -                    fg_color, bg_color,
1082 1157                      credp, called_from);
1083 1158          }
1084 1159  
1085 1160          tem->tvs_outindex = 0;
1086 1161  
1087 1162          tem_safe_align_cursor(tem);
1088 1163  }
1089 1164  
1090 1165  
1091 1166  /*
1092 1167   * We have just done something to the current output point.  Reset the start
1093 1168   * point for the buffered data in a_outbuf.  There shouldn't be any data
1094 1169   * buffered yet.
1095 1170   */
1096 1171  static void
1097 1172  tem_safe_align_cursor(struct tem_vt_state *tem)
1098 1173  {
  
    | 
      ↓ open down ↓ | 
    7 lines elided | 
    
      ↑ open up ↑ | 
  
1099 1174          tem->tvs_s_cursor.row = tem->tvs_c_cursor.row;
1100 1175          tem->tvs_s_cursor.col = tem->tvs_c_cursor.col;
1101 1176  }
1102 1177  
1103 1178  /*
1104 1179   * State machine parser based on the current state and character input
1105 1180   * major terminations are to control character or normal character
1106 1181   */
1107 1182  
1108 1183  static void
1109      -tem_safe_parse(struct tem_vt_state *tem, uchar_t ch,
     1184 +tem_safe_parse(struct tem_vt_state *tem, tem_char_t ch,
1110 1185      cred_t *credp, enum called_from called_from)
1111 1186  {
1112 1187          int     i;
1113 1188  
1114 1189          ASSERT((called_from == CALLED_FROM_STANDALONE) ||
1115 1190              MUTEX_HELD(&tem->tvs_lock));
1116 1191  
1117 1192          if (tem->tvs_state == A_STATE_START) {  /* Normal state? */
1118      -                if (ch == A_CSI || ch == A_ESC || ch < ' ') {
     1193 +                if (ch == A_CSI || ch == A_OSC || ch == A_ESC || ch < ' ') {
1119 1194                          /* Control */
1120 1195                          tem_safe_control(tem, ch, credp, called_from);
1121 1196                  } else {
1122 1197                          /* Display */
1123 1198                          tem_safe_outch(tem, ch, credp, called_from);
1124 1199                  }
1125 1200                  return;
1126 1201          }
1127 1202  
1128 1203          /* In <ESC> sequence */
1129 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 +
1130 1210                  if (tem->tvs_state != A_STATE_CSI) {
1131 1211                          tem_safe_getparams(tem, ch, credp, called_from);
1132 1212                          return;
1133 1213                  }
1134 1214  
1135 1215                  switch (ch) {
1136 1216                  case '?':
1137 1217                          tem->tvs_state = A_STATE_CSI_QMARK;
1138 1218                          return;
1139 1219                  case '=':
1140 1220                          tem->tvs_state = A_STATE_CSI_EQUAL;
1141 1221                          return;
1142 1222                  case 's':
1143 1223                          /*
1144 1224                           * As defined below, this sequence
1145 1225                           * saves the cursor.  However, Sun
1146 1226                           * defines ESC[s as reset.  We resolved
1147 1227                           * the conflict by selecting reset as it
1148 1228                           * is exported in the termcap file for
1149 1229                           * sun-mon, while the "save cursor"
1150 1230                           * definition does not exist anywhere in
1151 1231                           * /etc/termcap.
1152 1232                           * However, having no coherent
1153 1233                           * definition of reset, we have not
1154 1234                           * implemented it.
1155 1235                           */
1156 1236  
1157 1237                          /*
1158 1238                           * Original code
1159 1239                           * tem->tvs_r_cursor.row = tem->tvs_c_cursor.row;
1160 1240                           * tem->tvs_r_cursor.col = tem->tvs_c_cursor.col;
1161 1241                           * tem->tvs_state = A_STATE_START;
1162 1242                           */
1163 1243  
1164 1244                          tem->tvs_state = A_STATE_START;
1165 1245                          return;
1166 1246                  case 'u':
1167 1247                          tem_safe_mv_cursor(tem, tem->tvs_r_cursor.row,
1168 1248                              tem->tvs_r_cursor.col, credp, called_from);
1169 1249                          tem->tvs_state = A_STATE_START;
1170 1250                          return;
1171 1251                  case 'p':       /* sunbow */
1172 1252                          tem_safe_send_data(tem, credp, called_from);
1173 1253                          /*
1174 1254                           * Don't set anything if we are
1175 1255                           * already as we want to be.
1176 1256                           */
1177 1257                          if (tem->tvs_flags & TEM_ATTR_SCREEN_REVERSE) {
1178 1258                                  tem->tvs_flags &= ~TEM_ATTR_SCREEN_REVERSE;
1179 1259                                  /*
1180 1260                                   * If we have switched the characters to be the
1181 1261                                   * inverse from the screen, then switch them as
1182 1262                                   * well to keep them the inverse of the screen.
1183 1263                                   */
1184 1264                                  if (tem->tvs_flags & TEM_ATTR_REVERSE)
1185 1265                                          tem->tvs_flags &= ~TEM_ATTR_REVERSE;
1186 1266                                  else
1187 1267                                          tem->tvs_flags |= TEM_ATTR_REVERSE;
1188 1268                          }
1189 1269                          tem_safe_cls(tem, credp, called_from);
1190 1270                          tem->tvs_state = A_STATE_START;
1191 1271                          return;
1192 1272                  case 'q':       /* sunwob */
1193 1273                          tem_safe_send_data(tem, credp, called_from);
1194 1274                          /*
1195 1275                           * Don't set anything if we are
1196 1276                           * already where as we want to be.
1197 1277                           */
1198 1278                          if (!(tem->tvs_flags & TEM_ATTR_SCREEN_REVERSE)) {
1199 1279                                  tem->tvs_flags |= TEM_ATTR_SCREEN_REVERSE;
1200 1280                                  /*
1201 1281                                   * If we have switched the characters to be the
1202 1282                                   * inverse from the screen, then switch them as
1203 1283                                   * well to keep them the inverse of the screen.
1204 1284                                   */
1205 1285                                  if (!(tem->tvs_flags & TEM_ATTR_REVERSE))
1206 1286                                          tem->tvs_flags |= TEM_ATTR_REVERSE;
1207 1287                                  else
1208 1288                                          tem->tvs_flags &= ~TEM_ATTR_REVERSE;
1209 1289                          }
1210 1290  
1211 1291                          tem_safe_cls(tem, credp, called_from);
1212 1292                          tem->tvs_state = A_STATE_START;
1213 1293                          return;
1214 1294                  case 'r':       /* sunscrl */
1215 1295                          /*
1216 1296                           * Rule exception:  check for validity here.
1217 1297                           */
1218 1298                          tem->tvs_nscroll = tem->tvs_paramval;
1219 1299                          if (tem->tvs_nscroll > tems.ts_c_dimension.height)
1220 1300                                  tem->tvs_nscroll = tems.ts_c_dimension.height;
1221 1301                          if (tem->tvs_nscroll < 0)
1222 1302                                  tem->tvs_nscroll = 1;
1223 1303                          tem->tvs_state = A_STATE_START;
1224 1304                          return;
1225 1305                  default:
1226 1306                          tem_safe_getparams(tem, ch, credp, called_from);
1227 1307                          return;
1228 1308                  }
1229 1309          }
  
    | 
      ↓ open down ↓ | 
    90 lines elided | 
    
      ↑ open up ↑ | 
  
1230 1310  
1231 1311          /* Previous char was <ESC> */
1232 1312          if (ch == '[') {
1233 1313                  tem->tvs_curparam = 0;
1234 1314                  tem->tvs_paramval = 0;
1235 1315                  tem->tvs_gotparam = B_FALSE;
1236 1316                  /* clear the parameters */
1237 1317                  for (i = 0; i < TEM_MAXPARAMS; i++)
1238 1318                          tem->tvs_params[i] = -1;
1239 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;
1240 1328          } else if (ch == 'Q') { /* <ESC>Q ? */
1241 1329                  tem->tvs_state = A_STATE_START;
1242 1330          } else if (ch == 'C') { /* <ESC>C ? */
1243 1331                  tem->tvs_state = A_STATE_START;
1244 1332          } else {
1245 1333                  tem->tvs_state = A_STATE_START;
1246 1334                  if (ch == 'c') {
1247 1335                          /* ESC c resets display */
1248 1336                          tem_safe_reset_display(tem, credp, called_from,
1249 1337                              B_TRUE, B_TRUE);
1250 1338                  } else if (ch == 'H') {
1251 1339                          /* ESC H sets a tab */
1252 1340                          tem_safe_set_tab(tem);
1253 1341                  } else if (ch == '7') {
1254 1342                          /* ESC 7 Save Cursor position */
1255 1343                          tem->tvs_r_cursor.row = tem->tvs_c_cursor.row;
1256 1344                          tem->tvs_r_cursor.col = tem->tvs_c_cursor.col;
1257 1345                  } else if (ch == '8') {
1258 1346                          /* ESC 8 Restore Cursor position */
1259 1347                          tem_safe_mv_cursor(tem, tem->tvs_r_cursor.row,
1260 1348                              tem->tvs_r_cursor.col, credp, called_from);
1261 1349                  /* check for control chars */
1262 1350                  } else if (ch < ' ') {
1263 1351                          tem_safe_control(tem, ch, credp, called_from);
1264 1352                  } else {
1265 1353                          tem_safe_outch(tem, ch, credp, called_from);
1266 1354                  }
1267 1355          }
1268 1356  }
1269 1357  
1270 1358  /* ARGSUSED */
1271 1359  static void
1272 1360  tem_safe_bell(struct tem_vt_state *tem, enum called_from called_from)
1273 1361  {
1274 1362          if (called_from == CALLED_FROM_STANDALONE)
1275 1363                  (void) beep_polled(BEEP_CONSOLE);
1276 1364          else
1277 1365                  (void) beep(BEEP_CONSOLE);
1278 1366  }
1279 1367  
1280 1368  
1281 1369  static void
1282 1370  tem_safe_scroll(struct tem_vt_state *tem, int start, int end, int count,
1283 1371      int direction, cred_t *credp, enum called_from called_from)
1284 1372  {
1285 1373          int     row;
1286 1374          int     lines_affected;
1287 1375  
1288 1376          ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
1289 1377              called_from == CALLED_FROM_STANDALONE);
1290 1378  
1291 1379          lines_affected = end - start + 1;
1292 1380          if (count > lines_affected)
1293 1381                  count = lines_affected;
1294 1382          if (count <= 0)
1295 1383                  return;
1296 1384  
1297 1385          switch (direction) {
1298 1386          case TEM_SCROLL_UP:
1299 1387                  if (count < lines_affected) {
1300 1388                          tem_safe_copy_area(tem, 0, start + count,
1301 1389                              tems.ts_c_dimension.width - 1, end,
1302 1390                              0, start, credp, called_from);
1303 1391                  }
1304 1392                  for (row = (end - count) + 1; row <= end; row++) {
1305 1393                          tem_safe_clear_chars(tem, tems.ts_c_dimension.width,
1306 1394                              row, 0, credp, called_from);
1307 1395                  }
1308 1396                  break;
1309 1397  
1310 1398          case TEM_SCROLL_DOWN:
1311 1399                  if (count < lines_affected) {
1312 1400                          tem_safe_copy_area(tem, 0, start,
1313 1401                              tems.ts_c_dimension.width - 1,
1314 1402                              end - count, 0, start + count,
1315 1403                              credp, called_from);
1316 1404                  }
1317 1405                  for (row = start; row < start + count; row++) {
1318 1406                          tem_safe_clear_chars(tem, tems.ts_c_dimension.width,
1319 1407                              row, 0, credp, called_from);
1320 1408                  }
1321 1409                  break;
1322 1410          }
1323 1411  }
1324 1412  
1325 1413  static void
1326 1414  tem_safe_copy_area(struct tem_vt_state *tem,
1327 1415      screen_pos_t s_col, screen_pos_t s_row,
1328 1416      screen_pos_t e_col, screen_pos_t e_row,
1329 1417      screen_pos_t t_col, screen_pos_t t_row,
1330 1418      cred_t *credp, enum called_from called_from)
1331 1419  {
1332 1420          int rows;
1333 1421          int cols;
1334 1422  
1335 1423          ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
1336 1424              called_from == CALLED_FROM_STANDALONE);
1337 1425  
1338 1426          if (s_col < 0 || s_row < 0 ||
1339 1427              e_col < 0 || e_row < 0 ||
1340 1428              t_col < 0 || t_row < 0 ||
1341 1429              s_col >= tems.ts_c_dimension.width ||
1342 1430              e_col >= tems.ts_c_dimension.width ||
1343 1431              t_col >= tems.ts_c_dimension.width ||
1344 1432              s_row >= tems.ts_c_dimension.height ||
1345 1433              e_row >= tems.ts_c_dimension.height ||
1346 1434              t_row >= tems.ts_c_dimension.height)
1347 1435                  return;
1348 1436  
1349 1437          if (s_row > e_row || s_col > e_col)
1350 1438                  return;
1351 1439  
1352 1440          rows = e_row - s_row + 1;
1353 1441          cols = e_col - s_col + 1;
1354 1442          if (t_row + rows > tems.ts_c_dimension.height ||
1355 1443              t_col + cols > tems.ts_c_dimension.width)
1356 1444                  return;
1357 1445  
1358 1446          tem_safe_virtual_copy(tem,
1359 1447              s_col, s_row,
1360 1448              e_col, e_row,
1361 1449              t_col, t_row);
1362 1450  
1363 1451          if (!tem->tvs_isactive)
1364 1452                  return;
1365 1453  
1366 1454          tem_safe_callback_copy(tem, s_col, s_row,
1367 1455              e_col, e_row, t_col, t_row, credp, called_from);
1368 1456  }
1369 1457  
1370 1458  static void
1371 1459  tem_safe_clear_chars(struct tem_vt_state *tem, int count, screen_pos_t row,
1372 1460      screen_pos_t col, cred_t *credp, enum called_from called_from)
1373 1461  {
1374 1462          ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
1375 1463              called_from == CALLED_FROM_STANDALONE);
1376 1464  
1377 1465          if (row < 0 || row >= tems.ts_c_dimension.height ||
1378 1466              col < 0 || col >= tems.ts_c_dimension.width ||
1379 1467              count < 0)
1380 1468                  return;
1381 1469  
1382 1470          /*
1383 1471           * Note that very large values of "count" could cause col+count
1384 1472           * to overflow, so we check "count" independently.
1385 1473           */
1386 1474          if (count > tems.ts_c_dimension.width ||
1387 1475              col + count > tems.ts_c_dimension.width)
1388 1476                  count = tems.ts_c_dimension.width - col;
1389 1477  
  
    | 
      ↓ open down ↓ | 
    140 lines elided | 
    
      ↑ open up ↑ | 
  
1390 1478          tem_safe_virtual_cls(tem, count, row, col);
1391 1479  
1392 1480          if (!tem->tvs_isactive)
1393 1481                  return;
1394 1482  
1395 1483          tem_safe_callback_cls(tem, count, row, col, credp, called_from);
1396 1484  }
1397 1485  
1398 1486  /*ARGSUSED*/
1399 1487  void
1400      -tem_safe_text_display(struct tem_vt_state *tem, uchar_t *string,
     1488 +tem_safe_text_display(struct tem_vt_state *tem, term_char_t *string,
1401 1489      int count, screen_pos_t row, screen_pos_t col,
1402      -    text_color_t fg_color, text_color_t bg_color,
1403 1490      cred_t *credp, enum called_from called_from)
1404 1491  {
1405 1492          struct vis_consdisplay da;
     1493 +        int i;
     1494 +        tem_char_t c;
1406 1495  
1407 1496          ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
1408 1497              called_from == CALLED_FROM_STANDALONE);
1409 1498  
1410      -        da.data = string;
1411      -        da.width = (screen_size_t)count;
     1499 +        da.data = (uint8_t *)&c;
     1500 +        da.width = 1;
1412 1501          da.row = row;
1413 1502          da.col = col;
1414 1503  
1415      -        da.fg_color = fg_color;
1416      -        da.bg_color = bg_color;
1417      -
1418      -        tems_safe_display(&da, credp, called_from);
     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 +        }
1419 1510  }
1420 1511  
1421 1512  /*
1422 1513   * This function is used to blit a rectangular color image,
1423 1514   * unperturbed on the underlying framebuffer, to render
1424 1515   * icons and pictures.  The data is a pixel pattern that
1425 1516   * fills a rectangle bounded to the width and height parameters.
1426 1517   * The color pixel data must to be pre-adjusted by the caller
1427 1518   * for the current video depth.
1428 1519   *
1429 1520   * This function is unused now.
1430 1521   */
1431 1522  /*ARGSUSED*/
1432 1523  static void
1433 1524  tem_safe_image_display(struct tem_vt_state *tem, uchar_t *image,
1434 1525      int height, int width, screen_pos_t row, screen_pos_t col,
1435 1526      cred_t *credp, enum called_from called_from)
1436 1527  {
1437 1528          struct vis_consdisplay da;
1438 1529  
1439 1530          mutex_enter(&tems.ts_lock);
1440 1531          mutex_enter(&tem->tvs_lock);
1441 1532  
1442 1533          da.data = image;
1443 1534          da.width = (screen_size_t)width;
  
    | 
      ↓ open down ↓ | 
    15 lines elided | 
    
      ↑ open up ↑ | 
  
1444 1535          da.height = (screen_size_t)height;
1445 1536          da.row = row;
1446 1537          da.col = col;
1447 1538  
1448 1539          tems_safe_display(&da, credp, called_from);
1449 1540  
1450 1541          mutex_exit(&tem->tvs_lock);
1451 1542          mutex_exit(&tems.ts_lock);
1452 1543  }
1453 1544  
1454      -
1455 1545  /*ARGSUSED*/
1456 1546  void
1457 1547  tem_safe_text_copy(struct tem_vt_state *tem,
1458 1548      screen_pos_t s_col, screen_pos_t s_row,
1459 1549      screen_pos_t e_col, screen_pos_t e_row,
1460 1550      screen_pos_t t_col, screen_pos_t t_row,
1461 1551      cred_t *credp, enum called_from called_from)
1462 1552  {
1463 1553          struct vis_conscopy da;
1464 1554  
1465 1555          ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
1466 1556              called_from == CALLED_FROM_STANDALONE);
1467 1557  
1468 1558          da.s_row = s_row;
1469 1559          da.s_col = s_col;
1470 1560          da.e_row = e_row;
1471 1561          da.e_col = e_col;
1472 1562          da.t_row = t_row;
  
    | 
      ↓ open down ↓ | 
    8 lines elided | 
    
      ↑ open up ↑ | 
  
1473 1563          da.t_col = t_col;
1474 1564  
1475 1565          tems_safe_copy(&da, credp, called_from);
1476 1566  }
1477 1567  
1478 1568  void
1479 1569  tem_safe_text_cls(struct tem_vt_state *tem,
1480 1570      int count, screen_pos_t row, screen_pos_t col, cred_t *credp,
1481 1571      enum called_from called_from)
1482 1572  {
1483      -        struct vis_consdisplay da;
     1573 +        text_attr_t attr;
     1574 +        term_char_t c;
     1575 +        int i;
1484 1576  
1485 1577          ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
1486 1578              called_from == CALLED_FROM_STANDALONE);
1487 1579  
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,
     1580 +        tem_safe_get_attr(tem, &c.tc_fg_color, &c.tc_bg_color, &attr,
1494 1581              TEM_ATTR_SCREEN_REVERSE);
1495      -        tems_safe_display(&da, credp, called_from);
     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);
1496 1593  }
1497 1594  
1498 1595  void
1499 1596  tem_safe_pix_display(struct tem_vt_state *tem,
1500      -    uchar_t *string, int count,
     1597 +    term_char_t *string, int count,
1501 1598      screen_pos_t row, screen_pos_t col,
1502      -    text_color_t fg_color, text_color_t bg_color,
1503 1599      cred_t *credp, enum called_from called_from)
1504 1600  {
1505 1601          struct vis_consdisplay da;
1506 1602          int     i;
1507 1603  
1508 1604          ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
1509 1605              called_from == CALLED_FROM_STANDALONE);
1510 1606  
1511 1607          da.data = (uchar_t *)tem->tvs_pix_data;
1512      -        da.width = tems.ts_font.width;
1513      -        da.height = tems.ts_font.height;
     1608 +        da.width = (screen_size_t)tems.ts_font.vf_width;
     1609 +        da.height = (screen_size_t)tems.ts_font.vf_height;
1514 1610          da.row = (row * da.height) + tems.ts_p_offset.y;
1515 1611          da.col = (col * da.width) + tems.ts_p_offset.x;
1516 1612  
1517 1613          for (i = 0; i < count; i++) {
1518      -                tem_safe_callback_bit2pix(tem, string[i], fg_color, bg_color);
     1614 +                tem_safe_callback_bit2pix(tem, string[i]);
1519 1615                  tems_safe_display(&da, credp, called_from);
1520 1616                  da.col += da.width;
1521 1617          }
1522 1618  }
1523 1619  
1524 1620  void
1525 1621  tem_safe_pix_copy(struct tem_vt_state *tem,
1526 1622      screen_pos_t s_col, screen_pos_t s_row,
1527 1623      screen_pos_t e_col, screen_pos_t e_row,
1528 1624      screen_pos_t t_col, screen_pos_t t_row,
1529 1625      cred_t *credp,
1530 1626      enum called_from called_from)
1531 1627  {
1532 1628          struct vis_conscopy ma;
1533 1629          static boolean_t need_clear = B_TRUE;
1534 1630  
1535 1631          ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
1536 1632              called_from == CALLED_FROM_STANDALONE);
1537 1633  
1538 1634          if (need_clear && tem->tvs_first_line > 0) {
1539 1635                  /*
1540 1636                   * Clear OBP output above our kernel console term
  
    | 
      ↓ open down ↓ | 
    12 lines elided | 
    
      ↑ open up ↑ | 
  
1541 1637                   * when our kernel console term begins to scroll up,
1542 1638                   * we hope it is user friendly.
1543 1639                   * (Also see comments on tem_safe_pix_clear_prom_output)
1544 1640                   *
1545 1641                   * This is only one time call.
1546 1642                   */
1547 1643                  tem_safe_pix_clear_prom_output(tem, credp, called_from);
1548 1644          }
1549 1645          need_clear = B_FALSE;
1550 1646  
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;
     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;
1554 1651  
1555 1652          /*
1556 1653           * Check if we're in process of clearing OBP's columns area,
1557 1654           * which only happens when term scrolls up a whole line.
1558 1655           */
1559 1656          if (tem->tvs_first_line > 0 && t_row < s_row && t_col == 0 &&
1560 1657              e_col == tems.ts_c_dimension.width - 1) {
1561 1658                  /*
1562 1659                   * We need to clear OBP's columns area outside our kernel
1563 1660                   * console term. So that we set ma.e_col to entire row here.
1564 1661                   */
1565      -                ma.s_col = s_col * tems.ts_font.width;
     1662 +                ma.s_col = s_col * tems.ts_font.vf_width;
1566 1663                  ma.e_col = tems.ts_p_dimension.width - 1;
1567 1664  
1568      -                ma.t_col = t_col * tems.ts_font.width;
     1665 +                ma.t_col = t_col * tems.ts_font.vf_width;
1569 1666          } 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 +
     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 +
1572 1669                      tems.ts_p_offset.x - 1;
1573      -                ma.t_col = t_col * tems.ts_font.width + tems.ts_p_offset.x;
     1670 +                ma.t_col = t_col * tems.ts_font.vf_width + tems.ts_p_offset.x;
1574 1671          }
1575 1672  
1576 1673          tems_safe_copy(&ma, credp, called_from);
1577 1674  
1578 1675          if (tem->tvs_first_line > 0 && t_row < s_row) {
1579 1676                  /* We have scrolled up (s_row - t_row) rows. */
1580 1677                  tem->tvs_first_line -= (s_row - t_row);
1581 1678                  if (tem->tvs_first_line <= 0) {
1582 1679                          /* All OBP rows have been cleared. */
1583 1680                          tem->tvs_first_line = 0;
1584 1681                  }
1585 1682          }
1586 1683  
1587 1684  }
1588 1685  
1589 1686  void
1590      -tem_safe_pix_bit2pix(struct tem_vt_state *tem, unsigned char c,
1591      -    unsigned char fg, unsigned char bg)
     1687 +tem_safe_pix_bit2pix(struct tem_vt_state *tem, term_char_t c)
1592 1688  {
1593      -        void (*fp)(struct tem_vt_state *, unsigned char,
     1689 +        text_color_t fg, bg;
     1690 +        void (*fp)(struct tem_vt_state *, tem_char_t,
1594 1691              unsigned char, unsigned char);
1595 1692  
     1693 +        tem_safe_get_color(&fg, &bg, c);
1596 1694          switch (tems.ts_pdepth) {
1597 1695          case 4:
1598 1696                  fp = bit_to_pix4;
1599 1697                  break;
1600 1698          case 8:
1601 1699                  fp = bit_to_pix8;
1602 1700                  break;
     1701 +        case 15:
     1702 +        case 16:
     1703 +                fp = bit_to_pix16;
     1704 +                break;
1603 1705          case 24:
1604      -        case 32:
1605 1706                  fp = bit_to_pix24;
     1707 +                break;
     1708 +        case 32:
     1709 +                fp = bit_to_pix32;
     1710 +                break;
     1711 +        default:
     1712 +                return;
1606 1713          }
1607 1714  
1608      -        fp(tem, c, fg, bg);
     1715 +        fp(tem, c.tc_char, fg, bg);
1609 1716  }
1610 1717  
1611 1718  
1612 1719  /*
1613 1720   * This function only clears count of columns in one row
1614 1721   */
1615 1722  void
1616 1723  tem_safe_pix_cls(struct tem_vt_state *tem, int count,
1617 1724      screen_pos_t row, screen_pos_t col, cred_t *credp,
1618 1725      enum called_from called_from)
1619 1726  {
1620 1727          ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
1621 1728              called_from == CALLED_FROM_STANDALONE);
1622 1729  
1623 1730          tem_safe_pix_cls_range(tem, row, 1, tems.ts_p_offset.y,
1624 1731              col, count, tems.ts_p_offset.x, B_FALSE, credp, called_from);
1625 1732  }
1626 1733  
1627 1734  /*
1628 1735   * This function clears OBP output above our kernel console term area
1629 1736   * because OBP's term may have a bigger terminal window than that of
1630 1737   * our kernel console term. So we need to clear OBP output garbage outside
1631 1738   * of our kernel console term at a proper time, which is when the first
1632 1739   * row output of our kernel console term scrolls at the first screen line.
1633 1740   *
1634 1741   *      _________________________________
1635 1742   *      |   _____________________       |  ---> OBP's bigger term window
1636 1743   *      |   |                   |       |
1637 1744   *      |___|                   |       |
1638 1745   *      | | |                   |       |
1639 1746   *      | | |                   |       |
1640 1747   *      |_|_|___________________|_______|
1641 1748   *        | |                   |          ---> first line
1642 1749   *        | |___________________|---> our kernel console term window
1643 1750   *        |
  
    | 
      ↓ open down ↓ | 
    25 lines elided | 
    
      ↑ open up ↑ | 
  
1644 1751   *        |---> columns area to be cleared
1645 1752   *
1646 1753   * This function only takes care of the output above our kernel console term,
1647 1754   * and tem_prom_scroll_up takes care of columns area outside of our kernel
1648 1755   * console term.
1649 1756   */
1650 1757  static void
1651 1758  tem_safe_pix_clear_prom_output(struct tem_vt_state *tem, cred_t *credp,
1652 1759      enum called_from called_from)
1653 1760  {
1654      -        int     nrows, ncols, width, height;
     1761 +        int     nrows, ncols, width, height, offset;
1655 1762  
1656 1763          ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
1657 1764              called_from == CALLED_FROM_STANDALONE);
1658 1765  
1659      -        width = tems.ts_font.width;
1660      -        height = tems.ts_font.height;
     1766 +        width = tems.ts_font.vf_width;
     1767 +        height = tems.ts_font.vf_height;
     1768 +        offset = tems.ts_p_offset.y % height;
1661 1769  
1662      -        nrows = (tems.ts_p_offset.y + (height - 1))/ height;
     1770 +        nrows = tems.ts_p_offset.y / height;
1663 1771          ncols = (tems.ts_p_dimension.width + (width - 1))/ width;
1664 1772  
1665      -        tem_safe_pix_cls_range(tem, 0, nrows, 0, 0, ncols, 0,
1666      -            B_FALSE, credp, called_from);
     1773 +        if (nrows > 0)
     1774 +                tem_safe_pix_cls_range(tem, 0, nrows, offset, 0, ncols, 0,
     1775 +                    B_FALSE, credp, called_from);
1667 1776  }
1668 1777  
1669 1778  /*
1670 1779   * clear the whole screen for pixel mode, just clear the
1671 1780   * physical screen.
1672 1781   */
1673 1782  void
1674 1783  tem_safe_pix_clear_entire_screen(struct tem_vt_state *tem, cred_t *credp,
1675 1784      enum called_from called_from)
1676 1785  {
1677      -        int     nrows, ncols, width, height;
     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;
1678 1792  
1679 1793          ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
1680 1794              called_from == CALLED_FROM_STANDALONE);
1681 1795  
1682      -        width = tems.ts_font.width;
1683      -        height = tems.ts_font.height;
     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);
1684 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 +
1685 1809          nrows = (tems.ts_p_dimension.height + (height - 1))/ height;
1686 1810          ncols = (tems.ts_p_dimension.width + (width - 1))/ width;
1687 1811  
1688      -        tem_safe_pix_cls_range(tem, 0, nrows, 0, 0, ncols, 0,
1689      -            B_FALSE, credp, called_from);
     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);
1690 1814  
1691 1815          /*
1692 1816           * Since the whole screen is cleared, we don't need
1693 1817           * to clear OBP output later.
1694 1818           */
1695 1819          if (tem->tvs_first_line > 0)
1696 1820                  tem->tvs_first_line = 0;
1697 1821  }
1698 1822  
1699 1823  /*
1700 1824   * clear the whole screen, including the virtual screen buffer,
1701 1825   * and reset the cursor to start point.
1702 1826   */
1703 1827  static void
1704 1828  tem_safe_cls(struct tem_vt_state *tem,
1705 1829      cred_t *credp, enum called_from called_from)
1706 1830  {
1707 1831          int     row;
1708 1832  
1709 1833          ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
1710 1834              called_from == CALLED_FROM_STANDALONE);
1711 1835  
1712 1836          if (tems.ts_display_mode == VIS_TEXT) {
1713 1837                  for (row = 0; row < tems.ts_c_dimension.height; row++) {
1714 1838                          tem_safe_clear_chars(tem, tems.ts_c_dimension.width,
1715 1839                              row, 0, credp, called_from);
1716 1840                  }
1717 1841                  tem->tvs_c_cursor.row = 0;
1718 1842                  tem->tvs_c_cursor.col = 0;
1719 1843                  tem_safe_align_cursor(tem);
1720 1844                  return;
1721 1845          }
1722 1846  
1723 1847          ASSERT(tems.ts_display_mode == VIS_PIXEL);
1724 1848  
1725 1849          for (row = 0; row < tems.ts_c_dimension.height; row++) {
1726 1850                  tem_safe_virtual_cls(tem, tems.ts_c_dimension.width, row, 0);
1727 1851          }
1728 1852          tem->tvs_c_cursor.row = 0;
1729 1853          tem->tvs_c_cursor.col = 0;
1730 1854          tem_safe_align_cursor(tem);
1731 1855  
1732 1856          if (!tem->tvs_isactive)
1733 1857                  return;
1734 1858  
1735 1859          tem_safe_pix_clear_entire_screen(tem, credp, called_from);
1736 1860  }
1737 1861  
1738 1862  static void
1739 1863  tem_safe_back_tab(struct tem_vt_state *tem,
1740 1864      cred_t *credp, enum called_from called_from)
1741 1865  {
1742 1866          int     i;
1743 1867          screen_pos_t    tabstop;
1744 1868  
1745 1869          ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
1746 1870              called_from == CALLED_FROM_STANDALONE);
1747 1871  
1748 1872          tabstop = 0;
1749 1873  
1750 1874          for (i = tem->tvs_ntabs - 1; i >= 0; i--) {
1751 1875                  if (tem->tvs_tabs[i] < tem->tvs_c_cursor.col) {
1752 1876                          tabstop = tem->tvs_tabs[i];
1753 1877                          break;
1754 1878                  }
1755 1879          }
1756 1880  
1757 1881          tem_safe_mv_cursor(tem, tem->tvs_c_cursor.row,
1758 1882              tabstop, credp, called_from);
1759 1883  }
1760 1884  
1761 1885  static void
1762 1886  tem_safe_tab(struct tem_vt_state *tem,
1763 1887      cred_t *credp, enum called_from called_from)
1764 1888  {
1765 1889          int     i;
1766 1890          screen_pos_t    tabstop;
1767 1891  
1768 1892          ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
1769 1893              called_from == CALLED_FROM_STANDALONE);
1770 1894  
1771 1895          tabstop = tems.ts_c_dimension.width - 1;
1772 1896  
1773 1897          for (i = 0; i < tem->tvs_ntabs; i++) {
1774 1898                  if (tem->tvs_tabs[i] > tem->tvs_c_cursor.col) {
1775 1899                          tabstop = tem->tvs_tabs[i];
1776 1900                          break;
1777 1901                  }
1778 1902          }
1779 1903  
1780 1904          tem_safe_mv_cursor(tem, tem->tvs_c_cursor.row,
1781 1905              tabstop, credp, called_from);
1782 1906  }
1783 1907  
1784 1908  static void
1785 1909  tem_safe_set_tab(struct tem_vt_state *tem)
1786 1910  {
1787 1911          int     i;
1788 1912          int     j;
1789 1913  
1790 1914          if (tem->tvs_ntabs == TEM_MAXTAB)
1791 1915                  return;
1792 1916          if (tem->tvs_ntabs == 0 ||
1793 1917              tem->tvs_tabs[tem->tvs_ntabs] < tem->tvs_c_cursor.col) {
1794 1918                          tem->tvs_tabs[tem->tvs_ntabs++] = tem->tvs_c_cursor.col;
1795 1919                          return;
1796 1920          }
1797 1921          for (i = 0; i < tem->tvs_ntabs; i++) {
1798 1922                  if (tem->tvs_tabs[i] == tem->tvs_c_cursor.col)
1799 1923                          return;
1800 1924                  if (tem->tvs_tabs[i] > tem->tvs_c_cursor.col) {
1801 1925                          for (j = tem->tvs_ntabs - 1; j >= i; j--)
1802 1926                                  tem->tvs_tabs[j+ 1] = tem->tvs_tabs[j];
1803 1927                          tem->tvs_tabs[i] = tem->tvs_c_cursor.col;
1804 1928                          tem->tvs_ntabs++;
1805 1929                          return;
1806 1930                  }
1807 1931          }
1808 1932  }
1809 1933  
1810 1934  static void
1811 1935  tem_safe_clear_tabs(struct tem_vt_state *tem, int action)
1812 1936  {
1813 1937          int     i;
1814 1938          int     j;
1815 1939  
1816 1940          switch (action) {
1817 1941          case 3: /* clear all tabs */
1818 1942                  tem->tvs_ntabs = 0;
1819 1943                  break;
1820 1944          case 0: /* clr tab at cursor */
1821 1945  
1822 1946                  for (i = 0; i < tem->tvs_ntabs; i++) {
1823 1947                          if (tem->tvs_tabs[i] == tem->tvs_c_cursor.col) {
1824 1948                                  tem->tvs_ntabs--;
1825 1949                                  for (j = i; j < tem->tvs_ntabs; j++)
1826 1950                                          tem->tvs_tabs[j] = tem->tvs_tabs[j + 1];
1827 1951                                  return;
1828 1952                          }
1829 1953                  }
1830 1954                  break;
1831 1955          }
1832 1956  }
1833 1957  
1834 1958  static void
1835 1959  tem_safe_mv_cursor(struct tem_vt_state *tem, int row, int col,
1836 1960      cred_t *credp, enum called_from called_from)
1837 1961  {
1838 1962          ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
1839 1963              called_from == CALLED_FROM_STANDALONE);
1840 1964  
1841 1965          /*
1842 1966           * Sanity check and bounds enforcement.  Out of bounds requests are
1843 1967           * clipped to the screen boundaries.  This seems to be what SPARC
1844 1968           * does.
1845 1969           */
1846 1970          if (row < 0)
1847 1971                  row = 0;
1848 1972          if (row >= tems.ts_c_dimension.height)
1849 1973                  row = tems.ts_c_dimension.height - 1;
1850 1974          if (col < 0)
1851 1975                  col = 0;
1852 1976          if (col >= tems.ts_c_dimension.width)
1853 1977                  col = tems.ts_c_dimension.width - 1;
1854 1978  
1855 1979          tem_safe_send_data(tem, credp, called_from);
1856 1980          tem->tvs_c_cursor.row = (screen_pos_t)row;
1857 1981          tem->tvs_c_cursor.col = (screen_pos_t)col;
1858 1982          tem_safe_align_cursor(tem);
1859 1983  }
1860 1984  
1861 1985  /* ARGSUSED */
1862 1986  void
1863 1987  tem_safe_reset_emulator(struct tem_vt_state *tem,
1864 1988      cred_t *credp, enum called_from called_from,
1865 1989      boolean_t init_color)
1866 1990  {
1867 1991          int j;
1868 1992  
1869 1993          ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
1870 1994              called_from == CALLED_FROM_STANDALONE);
1871 1995  
1872 1996          tem->tvs_c_cursor.row = 0;
1873 1997          tem->tvs_c_cursor.col = 0;
1874 1998          tem->tvs_r_cursor.row = 0;
1875 1999          tem->tvs_r_cursor.col = 0;
1876 2000          tem->tvs_s_cursor.row = 0;
1877 2001          tem->tvs_s_cursor.col = 0;
1878 2002          tem->tvs_outindex = 0;
1879 2003          tem->tvs_state = A_STATE_START;
1880 2004          tem->tvs_gotparam = B_FALSE;
1881 2005          tem->tvs_curparam = 0;
1882 2006          tem->tvs_paramval = 0;
1883 2007          tem->tvs_nscroll = 1;
1884 2008  
1885 2009          if (init_color) {
1886 2010                  /* use initial settings */
1887 2011                  tem->tvs_fg_color = tems.ts_init_color.fg_color;
1888 2012                  tem->tvs_bg_color = tems.ts_init_color.bg_color;
1889 2013                  tem->tvs_flags = tems.ts_init_color.a_flags;
1890 2014          }
1891 2015  
1892 2016          /*
1893 2017           * set up the initial tab stops
1894 2018           */
1895 2019          tem->tvs_ntabs = 0;
1896 2020          for (j = 8; j < tems.ts_c_dimension.width; j += 8)
1897 2021                  tem->tvs_tabs[tem->tvs_ntabs++] = (screen_pos_t)j;
1898 2022  
1899 2023          for (j = 0; j < TEM_MAXPARAMS; j++)
1900 2024                  tem->tvs_params[j] = 0;
1901 2025  }
1902 2026  
1903 2027  void
1904 2028  tem_safe_reset_display(struct tem_vt_state *tem,
1905 2029      cred_t *credp, enum called_from called_from,
1906 2030      boolean_t clear_txt, boolean_t init_color)
1907 2031  {
1908 2032          ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
1909 2033              called_from == CALLED_FROM_STANDALONE);
1910 2034  
1911 2035          tem_safe_reset_emulator(tem, credp, called_from, init_color);
1912 2036  
1913 2037          if (clear_txt) {
1914 2038                  if (tem->tvs_isactive)
1915 2039                          tem_safe_callback_cursor(tem,
1916 2040                              VIS_HIDE_CURSOR, credp, called_from);
1917 2041  
1918 2042                  tem_safe_cls(tem, credp, called_from);
1919 2043  
1920 2044                  if (tem->tvs_isactive)
1921 2045                          tem_safe_callback_cursor(tem,
1922 2046                              VIS_DISPLAY_CURSOR, credp, called_from);
1923 2047          }
1924 2048  }
1925 2049  
1926 2050  static void
1927 2051  tem_safe_shift(
1928 2052          struct tem_vt_state *tem,
1929 2053          int count,
1930 2054          int direction,
1931 2055          cred_t *credp,
1932 2056          enum called_from called_from)
1933 2057  {
1934 2058          int rest_of_line;
1935 2059  
1936 2060          ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
1937 2061              called_from == CALLED_FROM_STANDALONE);
1938 2062  
1939 2063          rest_of_line = tems.ts_c_dimension.width - tem->tvs_c_cursor.col;
1940 2064          if (count > rest_of_line)
1941 2065                  count = rest_of_line;
1942 2066  
1943 2067          if (count <= 0)
1944 2068                  return;
1945 2069  
1946 2070          switch (direction) {
1947 2071          case TEM_SHIFT_LEFT:
1948 2072                  if (count < rest_of_line) {
1949 2073                          tem_safe_copy_area(tem,
1950 2074                              tem->tvs_c_cursor.col + count,
1951 2075                              tem->tvs_c_cursor.row,
1952 2076                              tems.ts_c_dimension.width - 1,
1953 2077                              tem->tvs_c_cursor.row,
1954 2078                              tem->tvs_c_cursor.col,
1955 2079                              tem->tvs_c_cursor.row,
1956 2080                              credp, called_from);
1957 2081                  }
1958 2082  
1959 2083                  tem_safe_clear_chars(tem, count, tem->tvs_c_cursor.row,
1960 2084                      (tems.ts_c_dimension.width - count), credp,
1961 2085                      called_from);
1962 2086                  break;
1963 2087          case TEM_SHIFT_RIGHT:
1964 2088                  if (count < rest_of_line) {
1965 2089                          tem_safe_copy_area(tem,
1966 2090                              tem->tvs_c_cursor.col,
1967 2091                              tem->tvs_c_cursor.row,
1968 2092                              tems.ts_c_dimension.width - count - 1,
1969 2093                              tem->tvs_c_cursor.row,
1970 2094                              tem->tvs_c_cursor.col + count,
1971 2095                              tem->tvs_c_cursor.row,
1972 2096                              credp, called_from);
1973 2097                  }
1974 2098  
1975 2099                  tem_safe_clear_chars(tem, count, tem->tvs_c_cursor.row,
1976 2100                      tem->tvs_c_cursor.col, credp, called_from);
1977 2101                  break;
1978 2102          }
1979 2103  }
1980 2104  
1981 2105  void
1982 2106  tem_safe_text_cursor(struct tem_vt_state *tem, short action,
1983 2107      cred_t *credp, enum called_from called_from)
1984 2108  {
1985 2109          struct vis_conscursor   ca;
1986 2110  
1987 2111          ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
1988 2112              called_from == CALLED_FROM_STANDALONE);
1989 2113  
1990 2114          ca.row = tem->tvs_c_cursor.row;
1991 2115          ca.col = tem->tvs_c_cursor.col;
1992 2116          ca.action = action;
1993 2117  
1994 2118          tems_safe_cursor(&ca, credp, called_from);
1995 2119  
1996 2120          if (action == VIS_GET_CURSOR) {
  
    | 
      ↓ open down ↓ | 
    297 lines elided | 
    
      ↑ open up ↑ | 
  
1997 2121                  tem->tvs_c_cursor.row = ca.row;
1998 2122                  tem->tvs_c_cursor.col = ca.col;
1999 2123          }
2000 2124  }
2001 2125  
2002 2126  void
2003 2127  tem_safe_pix_cursor(struct tem_vt_state *tem, short action,
2004 2128      cred_t *credp, enum called_from called_from)
2005 2129  {
2006 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;
2007 2135  
2008 2136          ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
2009 2137              called_from == CALLED_FROM_STANDALONE);
2010 2138  
2011      -        ca.row = tem->tvs_c_cursor.row * tems.ts_font.height +
     2139 +        ca.row = tem->tvs_c_cursor.row * tems.ts_font.vf_height +
2012 2140              tems.ts_p_offset.y;
2013      -        ca.col = tem->tvs_c_cursor.col * tems.ts_font.width +
     2141 +        ca.col = tem->tvs_c_cursor.col * tems.ts_font.vf_width +
2014 2142              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) {
     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 */
2018 2174                  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 2175                          ca.fg_color.twentyfour[0] = TEM_TEXT_WHITE24_RED;
2028 2176                          ca.fg_color.twentyfour[1] = TEM_TEXT_WHITE24_GREEN;
2029 2177                          ca.fg_color.twentyfour[2] = TEM_TEXT_WHITE24_BLUE;
2030 2178  
2031 2179                          ca.bg_color.twentyfour[0] = TEM_TEXT_BLACK24_RED;
2032 2180                          ca.bg_color.twentyfour[1] = TEM_TEXT_BLACK24_GREEN;
2033 2181                          ca.bg_color.twentyfour[2] = TEM_TEXT_BLACK24_BLUE;
2034 2182                  } else {
2035 2183                          ca.fg_color.twentyfour[0] = TEM_TEXT_BLACK24_RED;
2036 2184                          ca.fg_color.twentyfour[1] = TEM_TEXT_BLACK24_GREEN;
2037 2185                          ca.fg_color.twentyfour[2] = TEM_TEXT_BLACK24_BLUE;
2038 2186  
2039 2187                          ca.bg_color.twentyfour[0] = TEM_TEXT_WHITE24_RED;
2040 2188                          ca.bg_color.twentyfour[1] = TEM_TEXT_WHITE24_GREEN;
2041 2189                          ca.bg_color.twentyfour[2] = TEM_TEXT_WHITE24_BLUE;
2042 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
2043 2202          }
2044 2203  
2045 2204          ca.action = action;
2046 2205  
2047 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 +        }
2048 2221  }
2049 2222  
2050 2223  static void
2051      -bit_to_pix4(struct tem_vt_state *tem, uchar_t c, text_color_t fg_color,
     2224 +bit_to_pix4(struct tem_vt_state *tem, tem_char_t c, text_color_t fg_color,
2052 2225      text_color_t bg_color)
2053 2226  {
2054 2227          uint8_t *dest = (uint8_t *)tem->tvs_pix_data;
2055 2228          font_bit_to_pix4(&tems.ts_font, dest, c, fg_color, bg_color);
2056 2229  }
2057 2230  
2058 2231  static void
2059      -bit_to_pix8(struct tem_vt_state *tem, uchar_t c, text_color_t fg_color,
     2232 +bit_to_pix8(struct tem_vt_state *tem, tem_char_t c, text_color_t fg_color,
2060 2233      text_color_t bg_color)
2061 2234  {
2062 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);
2063 2239          font_bit_to_pix8(&tems.ts_font, dest, c, fg_color, bg_color);
2064 2240  }
2065 2241  
2066 2242  static void
2067      -bit_to_pix24(struct tem_vt_state *tem, uchar_t c, text_color_t fg_color4,
     2243 +bit_to_pix16(struct tem_vt_state *tem, tem_char_t c, text_color_t fg_color4,
2068 2244      text_color_t bg_color4)
2069 2245  {
2070      -        uint32_t fg_color32, bg_color32, *dest;
     2246 +        uint16_t fg_color16, bg_color16;
     2247 +        uint16_t *dest;
2071 2248  
2072 2249          ASSERT(fg_color4 < 16 && bg_color4 < 16);
2073 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
2074 2268          fg_color32 = PIX4TO32(fg_color4);
2075 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
2076 2274  
2077      -        dest = (uint32_t *)tem->tvs_pix_data;
     2275 +        dest = (uint8_t *)tem->tvs_pix_data;
2078 2276          font_bit_to_pix24(&tems.ts_font, dest, c, fg_color32, bg_color32);
2079 2277  }
2080 2278  
2081      -static text_color_t
2082      -ansi_bg_to_solaris(struct tem_vt_state *tem, int ansi)
     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)
2083 2282  {
2084      -        if (tem->tvs_flags & TEM_ATTR_BRIGHT_BG)
2085      -                return (brt_xlate[ansi]);
2086      -        else
2087      -                return (dim_xlate[ansi]);
2088      -}
     2283 +        uint32_t fg_color32, bg_color32, *dest;
2089 2284  
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      -        }
     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);
2099 2297  }
2100 2298  
2101 2299  /*
2102 2300   * flag: TEM_ATTR_SCREEN_REVERSE or TEM_ATTR_REVERSE
2103 2301   */
2104 2302  void
2105      -tem_safe_get_color(struct tem_vt_state *tem, text_color_t *fg,
2106      -    text_color_t *bg, uint8_t flag)
     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)
2107 2305  {
2108 2306          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);
     2307 +                *fg = tem->tvs_bg_color;
     2308 +                *bg = tem->tvs_fg_color;
2113 2309          } 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);
     2310 +                *fg = tem->tvs_fg_color;
     2311 +                *bg = tem->tvs_bg_color;
2118 2312          }
     2313 +
     2314 +        if (attr == NULL)
     2315 +                return;
     2316 +
     2317 +        *attr = tem->tvs_flags;
2119 2318  }
2120 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 +
2121 2334  /*
2122 2335   * Clear a rectangle of screen for pixel mode.
2123 2336   *
2124 2337   * arguments:
2125 2338   *    row:      start row#
2126 2339   *    nrows:    the number of rows to clear
2127 2340   *    offset_y: the offset of height in pixels to begin clear
2128 2341   *    col:      start col#
2129 2342   *    ncols:    the number of cols to clear
2130 2343   *    offset_x: the offset of width in pixels to begin clear
2131 2344   *    scroll_up: whether this function is called during sroll up,
2132 2345   *               which is called only once.
2133 2346   */
  
    | 
      ↓ open down ↓ | 
    3 lines elided | 
    
      ↑ open up ↑ | 
  
2134 2347  void
2135 2348  tem_safe_pix_cls_range(struct tem_vt_state *tem,
2136 2349      screen_pos_t row, int nrows, int offset_y,
2137 2350      screen_pos_t col, int ncols, int offset_x,
2138 2351      boolean_t sroll_up, cred_t *credp,
2139 2352      enum called_from called_from)
2140 2353  {
2141 2354          struct vis_consdisplay da;
2142 2355          int     i, j;
2143 2356          int     row_add = 0;
2144      -        text_color_t fg_color;
2145      -        text_color_t bg_color;
     2357 +        term_char_t c;
     2358 +        text_attr_t attr;
2146 2359  
2147 2360          ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
2148 2361              called_from == CALLED_FROM_STANDALONE);
2149 2362  
2150 2363          if (sroll_up)
2151 2364                  row_add = tems.ts_c_dimension.height - 1;
2152 2365  
2153      -        da.width = tems.ts_font.width;
2154      -        da.height = tems.ts_font.height;
     2366 +        da.width = (screen_size_t)tems.ts_font.vf_width;
     2367 +        da.height = (screen_size_t)tems.ts_font.vf_height;
2155 2368  
2156      -        tem_safe_get_color(tem, &fg_color, &bg_color, TEM_ATTR_SCREEN_REVERSE);
     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) | ' ';
2157 2373  
2158      -        tem_safe_callback_bit2pix(tem, ' ', fg_color, bg_color);
     2374 +        tem_safe_callback_bit2pix(tem, c);
2159 2375          da.data = (uchar_t *)tem->tvs_pix_data;
2160 2376  
2161 2377          for (i = 0; i < nrows; i++, row++) {
2162 2378                  da.row = (row + row_add) * da.height + offset_y;
2163 2379                  da.col = col * da.width + offset_x;
2164 2380                  for (j = 0; j < ncols; j++) {
2165 2381                          tems_safe_display(&da, credp, called_from);
2166 2382                          da.col += da.width;
2167 2383                  }
2168 2384          }
2169 2385  }
2170 2386  
2171 2387  /*
2172 2388   * virtual screen operations
2173 2389   */
2174 2390  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)
     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)
2178 2393  {
2179 2394          int i, width;
2180      -        unsigned char *addr;
2181      -        text_color_t *pfgcolor;
2182      -        text_color_t *pbgcolor;
     2395 +        term_char_t *addr;
2183 2396  
2184 2397          if (row < 0 || row >= tems.ts_c_dimension.height ||
2185 2398              col < 0 || col >= tems.ts_c_dimension.width ||
2186 2399              col + count > tems.ts_c_dimension.width)
2187 2400                  return;
2188 2401  
2189 2402          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);
     2403 +        addr = tem->tvs_screen_buf + (row * width + col);
2193 2404          for (i = 0; i < count; i++) {
2194 2405                  *addr++ = string[i];
2195      -                *pfgcolor++ = fg_color;
2196      -                *pbgcolor++ = bg_color;
2197 2406          }
2198 2407  }
2199 2408  
2200 2409  static void
2201      -i_virtual_copy(unsigned char *base,
     2410 +i_virtual_copy_tem_chars(term_char_t *base,
2202 2411      screen_pos_t s_col, screen_pos_t s_row,
2203 2412      screen_pos_t e_col, screen_pos_t e_row,
2204 2413      screen_pos_t t_col, screen_pos_t t_row)
2205 2414  {
2206      -        unsigned char   *from;
2207      -        unsigned char   *to;
     2415 +        term_char_t     *from;
     2416 +        term_char_t     *to;
2208 2417          int             cnt;
2209 2418          screen_size_t chars_per_row;
2210      -        unsigned char   *to_row_start;
2211      -        unsigned char   *from_row_start;
     2419 +        term_char_t     *to_row_start;
     2420 +        term_char_t     *from_row_start;
2212 2421          screen_size_t   rows_to_move;
2213 2422          int             cols = tems.ts_c_dimension.width;
2214 2423  
2215 2424          chars_per_row = e_col - s_col + 1;
2216 2425          rows_to_move = e_row - s_row + 1;
2217 2426  
2218 2427          to_row_start = base + ((t_row * cols) + t_col);
2219 2428          from_row_start = base + ((s_row * cols) + s_col);
2220 2429  
2221 2430          if (to_row_start < from_row_start) {
2222 2431                  while (rows_to_move-- > 0) {
2223 2432                          to = to_row_start;
2224 2433                          from = from_row_start;
2225 2434                          to_row_start += cols;
2226 2435                          from_row_start += cols;
2227 2436                          for (cnt = chars_per_row; cnt-- > 0; )
2228 2437                                  *to++ = *from++;
2229 2438                  }
2230 2439          } else {
2231 2440                  /*
2232 2441                   * Offset to the end of the region and copy backwards.
2233 2442                   */
2234 2443                  cnt = rows_to_move * cols + chars_per_row;
2235 2444                  to_row_start += cnt;
2236 2445                  from_row_start += cnt;
2237 2446  
2238 2447                  while (rows_to_move-- > 0) {
2239 2448                          to_row_start -= cols;
2240 2449                          from_row_start -= cols;
2241 2450                          to = to_row_start;
2242 2451                          from = from_row_start;
2243 2452                          for (cnt = chars_per_row; cnt-- > 0; )
2244 2453                                  *--to = *--from;
2245 2454                  }
2246 2455          }
2247 2456  }
2248 2457  
2249 2458  static void
2250 2459  tem_safe_virtual_copy(struct tem_vt_state *tem,
2251 2460      screen_pos_t s_col, screen_pos_t s_row,
2252 2461      screen_pos_t e_col, screen_pos_t e_row,
2253 2462      screen_pos_t t_col, screen_pos_t t_row)
2254 2463  {
2255 2464          screen_size_t chars_per_row;
2256 2465          screen_size_t   rows_to_move;
2257 2466          int             rows = tems.ts_c_dimension.height;
2258 2467          int             cols = tems.ts_c_dimension.width;
2259 2468  
2260 2469          if (s_col < 0 || s_col >= cols ||
2261 2470              s_row < 0 || s_row >= rows ||
2262 2471              e_col < 0 || e_col >= cols ||
2263 2472              e_row < 0 || e_row >= rows ||
2264 2473              t_col < 0 || t_col >= cols ||
2265 2474              t_row < 0 || t_row >= rows ||
2266 2475              s_col > e_col ||
2267 2476              s_row > e_row)
  
    | 
      ↓ open down ↓ | 
    46 lines elided | 
    
      ↑ open up ↑ | 
  
2268 2477                  return;
2269 2478  
2270 2479          chars_per_row = e_col - s_col + 1;
2271 2480          rows_to_move = e_row - s_row + 1;
2272 2481  
2273 2482          /* More sanity checks. */
2274 2483          if (t_row + rows_to_move > rows ||
2275 2484              t_col + chars_per_row > cols)
2276 2485                  return;
2277 2486  
2278      -        i_virtual_copy(tem->tvs_screen_buf, s_col, s_row,
     2487 +        i_virtual_copy_tem_chars(tem->tvs_screen_buf, s_col, s_row,
2279 2488              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 2489  }
2288 2490  
2289 2491  static void
2290 2492  tem_safe_virtual_cls(struct tem_vt_state *tem,
2291 2493      int count, screen_pos_t row, screen_pos_t col)
2292 2494  {
2293      -        text_color_t fg_color;
2294      -        text_color_t bg_color;
     2495 +        int i;
     2496 +        text_attr_t attr;
     2497 +        term_char_t c;
2295 2498  
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);
     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);
2299 2507  }
2300 2508  
2301 2509  /*
2302 2510   * only blank screen, not clear our screen buffer
2303 2511   */
2304 2512  void
2305 2513  tem_safe_blank_screen(struct tem_vt_state *tem, cred_t *credp,
2306 2514      enum called_from called_from)
2307 2515  {
2308 2516          int     row;
2309 2517  
2310 2518          ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
2311 2519              called_from == CALLED_FROM_STANDALONE);
2312 2520  
2313 2521          if (tems.ts_display_mode == VIS_PIXEL) {
2314 2522                  tem_safe_pix_clear_entire_screen(tem, credp, called_from);
2315 2523                  return;
2316 2524          }
2317 2525  
2318 2526          for (row = 0; row < tems.ts_c_dimension.height; row++) {
2319 2527                  tem_safe_callback_cls(tem,
2320 2528                      tems.ts_c_dimension.width,
2321 2529                      row, 0, credp, called_from);
  
    | 
      ↓ open down ↓ | 
    13 lines elided | 
    
      ↑ open up ↑ | 
  
2322 2530          }
2323 2531  }
2324 2532  
2325 2533  /*
2326 2534   * unblank screen with associated tem from its screen buffer
2327 2535   */
2328 2536  void
2329 2537  tem_safe_unblank_screen(struct tem_vt_state *tem, cred_t *credp,
2330 2538      enum called_from called_from)
2331 2539  {
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;
     2540 +        int     row;
2338 2541  
2339 2542          ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
2340 2543              called_from == CALLED_FROM_STANDALONE);
2341 2544  
2342 2545          if (tems.ts_display_mode == VIS_PIXEL)
2343 2546                  tem_safe_pix_clear_entire_screen(tem, credp, called_from);
2344 2547  
2345 2548          tem_safe_callback_cursor(tem, VIS_HIDE_CURSOR, credp, called_from);
2346 2549  
2347      -        width = tems.ts_c_dimension.width;
2348      -
2349 2550          /*
2350 2551           * Display data in tvs_screen_buf to the actual framebuffer in a
2351 2552           * row by row way.
2352 2553           * When dealing with one row, output data with the same foreground
2353 2554           * and background color all together.
2354 2555           */
2355 2556          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);
     2557 +                tem_safe_callback_display(tem, tem->tvs_screen_rows[row],
     2558 +                    tems.ts_c_dimension.width, row, 0, credp, called_from);
2394 2559          }
2395 2560  
2396 2561          tem_safe_callback_cursor(tem, VIS_DISPLAY_CURSOR, credp, called_from);
2397 2562  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX