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.c
          +++ new/usr/src/uts/common/io/tem.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   * ANSI terminal emulator module; parse ANSI X3.64 escape sequences and
  29   29   * the like.
  30   30   *
  31   31   * How Virtual Terminal Emulator Works:
  32   32   *
  33   33   * Every virtual terminal is associated with a tem_vt_state structure
  34   34   * and maintains a virtual screen buffer in tvs_screen_buf, which contains
  35   35   * all the characters which should be shown on the physical screen when
  36   36   * the terminal is activated.  There are also two other buffers, tvs_fg_buf
  37   37   * and tvs_bg_buf, which track the foreground and background colors of the
  38   38   * on screen characters
  39   39   *
  40   40   * Data written to a virtual terminal is composed of characters which
  41   41   * should be displayed on the screen when this virtual terminal is
  42   42   * activated, fg/bg colors of these characters, and other control
  43   43   * information (escape sequence, etc).
  44   44   *
  45   45   * When data is passed to a virtual terminal it first is parsed for
  46   46   * control information by tem_safe_parse().  Subsequently the character
  47   47   * and color data are written to tvs_screen_buf, tvs_fg_buf, and
  48   48   * tvs_bg_buf.  They are saved in these buffers in order to refresh
  49   49   * the screen when this terminal is activated.  If the terminal is
  50   50   * currently active, the data (characters and colors) are also written
  51   51   * to the physical screen by invoking a callback function,
  52   52   * tem_safe_text_callbacks() or tem_safe_pix_callbacks().
  53   53   *
  54   54   * When rendering data to the framebuffer, if the framebuffer is in
  55   55   * VIS_PIXEL mode, the character data will first be converted to pixel
  56   56   * data using tem_safe_pix_bit2pix(), and then the pixels get displayed
  57   57   * on the physical screen.  We only store the character and color data in
  58   58   * tem_vt_state since the bit2pix conversion only happens when actually
  59   59   * rendering to the physical framebuffer.
  60   60   */
  61   61  
  62   62  
  63   63  #include <sys/types.h>
  64   64  #include <sys/file.h>
  65   65  #include <sys/conf.h>
  66   66  #include <sys/errno.h>
  67   67  #include <sys/open.h>
  68   68  #include <sys/cred.h>
  69   69  #include <sys/kmem.h>
  70   70  #include <sys/ascii.h>
  71   71  #include <sys/consdev.h>
  72   72  #include <sys/font.h>
  73   73  #include <sys/fbio.h>
  74   74  #include <sys/conf.h>
  75   75  #include <sys/modctl.h>
  76   76  #include <sys/strsubr.h>
  77   77  #include <sys/stat.h>
  78   78  #include <sys/visual_io.h>
  79   79  #include <sys/mutex.h>
  80   80  #include <sys/param.h>
  81   81  #include <sys/debug.h>
  82   82  #include <sys/cmn_err.h>
  83   83  #include <sys/console.h>
  84   84  #include <sys/ddi.h>
  85   85  #include <sys/sunddi.h>
  86   86  #include <sys/sunldi.h>
  87   87  #include <sys/tem_impl.h>
  88   88  #ifdef _HAVE_TEM_FIRMWARE
  89   89  #include <sys/promif.h>
  90   90  #endif /* _HAVE_TEM_FIRMWARE */
  91   91  #include <sys/consplat.h>
  92   92  #include <sys/kd.h>
  93   93  #include <sys/sysmacros.h>
  94   94  #include <sys/note.h>
  95   95  #include <sys/t_lock.h>
  96   96  
  97   97  /* Terminal emulator internal helper functions */
  98   98  static void     tems_setup_terminal(struct vis_devinit *, size_t, size_t);
  99   99  static void     tems_modechange_callback(struct vis_modechg_arg *,
 100  100                  struct vis_devinit *);
 101  101  
 102  102  static void     tems_reset_colormap(cred_t *, enum called_from);
 103  103  
 104  104  static void     tem_free_buf(struct tem_vt_state *);
 105  105  static void     tem_internal_init(struct tem_vt_state *, cred_t *, boolean_t,
 106  106                      boolean_t);
 107  107  static void     tems_get_initial_color(tem_color_t *pcolor);
 108  108  
 109  109  /*
 110  110   * Globals
 111  111   */
 112  112  static ldi_ident_t      term_li = NULL;
 113  113  tem_state_t     tems;   /* common term info */
  
    | 
      ↓ open down ↓ | 
    113 lines elided | 
    
      ↑ open up ↑ | 
  
 114  114  _NOTE(MUTEX_PROTECTS_DATA(tems.ts_lock, tems))
 115  115  
 116  116  extern struct mod_ops mod_miscops;
 117  117  
 118  118  static struct modlmisc  modlmisc = {
 119  119          &mod_miscops,   /* modops */
 120  120          "ANSI Terminal Emulator", /* name */
 121  121  };
 122  122  
 123  123  static struct modlinkage modlinkage = {
 124      -        MODREV_1, (void *)&modlmisc, NULL
      124 +        MODREV_1, { (void *)&modlmisc, NULL }
 125  125  };
 126  126  
 127  127  int
 128  128  _init(void)
 129  129  {
 130  130          int ret;
 131  131          ret = mod_install(&modlinkage);
 132  132          if (ret != 0)
 133  133                  return (ret);
 134  134          ret = ldi_ident_from_mod(&modlinkage, &term_li);
 135  135          if (ret != 0) {
 136  136                  (void) mod_remove(&modlinkage);
 137  137                  return (ret);
 138  138          }
 139  139  
 140  140          mutex_init(&tems.ts_lock, (char *)NULL, MUTEX_DRIVER, NULL);
 141  141          list_create(&tems.ts_list, sizeof (struct tem_vt_state),
 142  142              offsetof(struct tem_vt_state, tvs_list_node));
 143  143          tems.ts_active = NULL;
 144  144  
 145  145          return (0);
 146  146  }
 147  147  
 148  148  int
 149  149  _fini()
 150  150  {
 151  151          int ret;
 152  152  
 153  153          ret = mod_remove(&modlinkage);
 154  154          if (ret == 0) {
 155  155                  ldi_ident_release(term_li);
 156  156                  term_li = NULL;
 157  157          }
 158  158          return (ret);
 159  159  }
 160  160  
 161  161  int
 162  162  _info(struct modinfo *modinfop)
 163  163  {
 164  164          return (mod_info(&modlinkage, modinfop));
 165  165  }
 166  166  
 167  167  static void
 168  168  tem_add(struct tem_vt_state *tem)
 169  169  {
 170  170          ASSERT(MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock));
 171  171  
 172  172          list_insert_head(&tems.ts_list, tem);
 173  173  }
 174  174  
 175  175  static void
 176  176  tem_rm(struct tem_vt_state *tem)
 177  177  {
 178  178          ASSERT(MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock));
 179  179  
 180  180          list_remove(&tems.ts_list, tem);
 181  181  }
 182  182  
 183  183  /*
 184  184   * This is the main entry point to the module.  It handles output requests
 185  185   * during normal system operation, when (e.g.) mutexes are available.
 186  186   */
 187  187  void
 188  188  tem_write(tem_vt_state_t tem_arg, uchar_t *buf, ssize_t len, cred_t *credp)
 189  189  {
 190  190          struct tem_vt_state *tem = (struct tem_vt_state *)tem_arg;
 191  191  
 192  192          mutex_enter(&tems.ts_lock);
 193  193          mutex_enter(&tem->tvs_lock);
 194  194  
 195  195          if (!tem->tvs_initialized) {
 196  196                  mutex_exit(&tem->tvs_lock);
 197  197                  mutex_exit(&tems.ts_lock);
 198  198                  return;
 199  199          }
 200  200  
 201  201          tem_safe_check_first_time(tem, credp, CALLED_FROM_NORMAL);
  
    | 
      ↓ open down ↓ | 
    67 lines elided | 
    
      ↑ open up ↑ | 
  
 202  202          tem_safe_terminal_emulate(tem, buf, len, credp, CALLED_FROM_NORMAL);
 203  203  
 204  204          mutex_exit(&tem->tvs_lock);
 205  205          mutex_exit(&tems.ts_lock);
 206  206  }
 207  207  
 208  208  static void
 209  209  tem_internal_init(struct tem_vt_state *ptem, cred_t *credp,
 210  210      boolean_t init_color, boolean_t clear_screen)
 211  211  {
 212      -        int i, j;
 213      -        int width, height;
 214      -        int total;
      212 +        unsigned i, j, width, height;
      213 +        text_attr_t attr;
 215  214          text_color_t fg;
 216  215          text_color_t bg;
 217      -        size_t  tc_size = sizeof (text_color_t);
 218  216  
 219  217          ASSERT(MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&ptem->tvs_lock));
 220  218  
 221  219          if (tems.ts_display_mode == VIS_PIXEL) {
 222  220                  ptem->tvs_pix_data_size = tems.ts_pix_data_size;
 223  221                  ptem->tvs_pix_data =
 224  222                      kmem_alloc(ptem->tvs_pix_data_size, KM_SLEEP);
 225  223          }
 226  224  
 227      -        ptem->tvs_outbuf_size = tems.ts_c_dimension.width;
 228      -        ptem->tvs_outbuf =
 229      -            (unsigned char *)kmem_alloc(ptem->tvs_outbuf_size, KM_SLEEP);
      225 +        ptem->tvs_outbuf_size = tems.ts_c_dimension.width *
      226 +            sizeof (*ptem->tvs_outbuf);
      227 +        ptem->tvs_outbuf = kmem_alloc(ptem->tvs_outbuf_size, KM_SLEEP);
 230  228  
 231  229          width = tems.ts_c_dimension.width;
 232  230          height = tems.ts_c_dimension.height;
 233      -        ptem->tvs_screen_buf_size = width * height;
 234      -        ptem->tvs_screen_buf =
 235      -            (unsigned char *)kmem_alloc(width * height, KM_SLEEP);
      231 +        ptem->tvs_screen_history_size = height;
 236  232  
 237      -        total = width * height * tc_size;
 238      -        ptem->tvs_fg_buf = (text_color_t *)kmem_alloc(total, KM_SLEEP);
 239      -        ptem->tvs_bg_buf = (text_color_t *)kmem_alloc(total, KM_SLEEP);
 240      -        ptem->tvs_color_buf_size = total;
      233 +        ptem->tvs_screen_buf_size = width * ptem->tvs_screen_history_size *
      234 +            sizeof (*ptem->tvs_screen_buf);
      235 +        ptem->tvs_screen_buf = kmem_alloc(ptem->tvs_screen_buf_size, KM_SLEEP);
      236 +        ptem->tvs_screen_rows = kmem_alloc(ptem->tvs_screen_history_size *
      237 +            sizeof (term_char_t *), KM_SLEEP);
 241  238  
 242  239          tem_safe_reset_display(ptem, credp, CALLED_FROM_NORMAL,
 243  240              clear_screen, init_color);
 244  241  
 245  242          ptem->tvs_utf8_left = 0;
 246  243          ptem->tvs_utf8_partial = 0;
 247  244  
 248      -        tem_safe_get_color(ptem, &fg, &bg, TEM_ATTR_SCREEN_REVERSE);
 249      -        for (i = 0; i < height; i++)
      245 +        /* Get default attributes and fill up the screen buffer. */
      246 +        tem_safe_get_attr(ptem, &fg, &bg, &attr, TEM_ATTR_SCREEN_REVERSE);
      247 +        for (i = 0; i < ptem->tvs_screen_history_size; i++) {
      248 +                ptem->tvs_screen_rows[i] = &ptem->tvs_screen_buf[i * width];
      249 +
 250  250                  for (j = 0; j < width; j++) {
 251      -                        ptem->tvs_screen_buf[i * width + j] = ' ';
 252      -                        ptem->tvs_fg_buf[(i * width +j) * tc_size] = fg;
 253      -                        ptem->tvs_bg_buf[(i * width +j) * tc_size] = bg;
      251 +                        ptem->tvs_screen_rows[i][j].tc_fg_color = fg;
      252 +                        ptem->tvs_screen_rows[i][j].tc_bg_color = bg;
      253 +                        ptem->tvs_screen_rows[i][j].tc_char =
      254 +                            TEM_ATTR(attr) | ' ';
 254  255  
 255  256                  }
      257 +        }
 256  258  
 257      -        ptem->tvs_initialized  = 1;
      259 +        ptem->tvs_initialized = B_TRUE;
 258  260  }
 259  261  
 260  262  int
 261  263  tem_initialized(tem_vt_state_t tem_arg)
 262  264  {
 263  265          struct tem_vt_state *ptem = (struct tem_vt_state *)tem_arg;
 264  266          int ret;
 265  267  
 266  268          mutex_enter(&ptem->tvs_lock);
 267      -        ret = ptem->tvs_initialized;
      269 +        ret = ptem->tvs_initialized == B_TRUE? 1 : 0;
 268  270          mutex_exit(&ptem->tvs_lock);
 269  271  
 270  272          return (ret);
 271  273  }
 272  274  
 273  275  tem_vt_state_t
 274  276  tem_init(cred_t *credp)
 275  277  {
 276  278          struct tem_vt_state *ptem;
 277  279  
 278  280          ptem = kmem_zalloc(sizeof (struct tem_vt_state), KM_SLEEP);
 279  281          mutex_init(&ptem->tvs_lock, (char *)NULL, MUTEX_DRIVER, NULL);
 280  282  
  
    | 
      ↓ open down ↓ | 
    3 lines elided | 
    
      ↑ open up ↑ | 
  
 281  283          mutex_enter(&tems.ts_lock);
 282  284          mutex_enter(&ptem->tvs_lock);
 283  285  
 284  286          ptem->tvs_isactive = B_FALSE;
 285  287          ptem->tvs_fbmode = KD_TEXT;
 286  288  
 287  289          /*
 288  290           * A tem is regarded as initialized only after tem_internal_init(),
 289  291           * will be set at the end of tem_internal_init().
 290  292           */
 291      -        ptem->tvs_initialized = 0;
      293 +        ptem->tvs_initialized = B_FALSE;
 292  294  
 293  295  
 294  296          if (!tems.ts_initialized) {
 295  297                  /*
 296  298                   * Only happens during early console configuration.
 297  299                   */
 298  300                  tem_add(ptem);
 299  301                  mutex_exit(&ptem->tvs_lock);
 300  302                  mutex_exit(&tems.ts_lock);
 301  303                  return ((tem_vt_state_t)ptem);
 302  304          }
 303  305  
 304  306          tem_internal_init(ptem, credp, B_TRUE, B_FALSE);
 305  307          tem_add(ptem);
 306  308          mutex_exit(&ptem->tvs_lock);
 307  309          mutex_exit(&tems.ts_lock);
 308  310  
 309  311          return ((tem_vt_state_t)ptem);
 310  312  }
 311  313  
 312  314  /*
 313  315   * re-init the tem after video mode has changed and tems_info has
 314  316   * been re-inited. The lock is already held.
 315  317   */
 316  318  static void
 317  319  tem_reinit(struct tem_vt_state *tem, boolean_t reset_display)
 318  320  {
 319  321          ASSERT(MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock));
 320  322  
 321  323          tem_free_buf(tem); /* only free virtual buffers */
 322  324  
 323  325          /* reserve color */
 324  326          tem_internal_init(tem, kcred, B_FALSE, reset_display);
 325  327  }
 326  328  
 327  329  static void
  
    | 
      ↓ open down ↓ | 
    26 lines elided | 
    
      ↑ open up ↑ | 
  
 328  330  tem_free_buf(struct tem_vt_state *tem)
 329  331  {
 330  332          ASSERT(tem != NULL && MUTEX_HELD(&tem->tvs_lock));
 331  333  
 332  334          if (tem->tvs_outbuf != NULL)
 333  335                  kmem_free(tem->tvs_outbuf, tem->tvs_outbuf_size);
 334  336          if (tem->tvs_pix_data != NULL)
 335  337                  kmem_free(tem->tvs_pix_data, tem->tvs_pix_data_size);
 336  338          if (tem->tvs_screen_buf != NULL)
 337  339                  kmem_free(tem->tvs_screen_buf, tem->tvs_screen_buf_size);
 338      -        if (tem->tvs_fg_buf != NULL)
 339      -                kmem_free(tem->tvs_fg_buf, tem->tvs_color_buf_size);
 340      -        if (tem->tvs_bg_buf != NULL)
 341      -                kmem_free(tem->tvs_bg_buf, tem->tvs_color_buf_size);
      340 +        if (tem->tvs_screen_rows != NULL) {
      341 +                kmem_free(tem->tvs_screen_rows, tem->tvs_screen_history_size *
      342 +                    sizeof (term_char_t *));
      343 +        }
 342  344  }
 343  345  
 344  346  void
 345  347  tem_destroy(tem_vt_state_t tem_arg, cred_t *credp)
 346  348  {
 347  349          struct tem_vt_state *tem = (struct tem_vt_state *)tem_arg;
 348  350  
 349  351          mutex_enter(&tems.ts_lock);
 350  352          mutex_enter(&tem->tvs_lock);
 351  353  
 352  354          if (tem->tvs_isactive && tem->tvs_fbmode == KD_TEXT)
 353  355                  tem_safe_blank_screen(tem, credp, CALLED_FROM_NORMAL);
 354  356  
 355  357          tem_free_buf(tem);
 356  358          tem_rm(tem);
 357  359  
 358  360          if (tems.ts_active == tem)
 359  361                  tems.ts_active = NULL;
 360  362  
 361  363          mutex_exit(&tem->tvs_lock);
 362  364          mutex_exit(&tems.ts_lock);
 363  365  
 364  366          kmem_free(tem, sizeof (struct tem_vt_state));
 365  367  }
 366  368  
 367  369  static int
 368  370  tems_failed(cred_t *credp, boolean_t finish_ioctl)
 369  371  {
 370  372          int     lyr_rval;
 371  373  
 372  374          ASSERT(MUTEX_HELD(&tems.ts_lock));
 373  375  
 374  376          if (finish_ioctl)
 375  377                  (void) ldi_ioctl(tems.ts_hdl, VIS_DEVFINI, 0,
 376  378                      FWRITE|FKIOCTL, credp, &lyr_rval);
 377  379  
 378  380          (void) ldi_close(tems.ts_hdl, NULL, credp);
 379  381          tems.ts_hdl = NULL;
 380  382          return (ENXIO);
 381  383  }
 382  384  
 383  385  /*
 384  386   * only called once during boot
 385  387   */
 386  388  int
 387  389  tem_info_init(char *pathname, cred_t *credp)
 388  390  {
 389  391          int                     lyr_rval, ret;
 390  392          struct vis_devinit      temargs;
 391  393          char                    *pathbuf;
 392  394          size_t height = 0;
 393  395          size_t width = 0;
 394  396          struct tem_vt_state *p;
 395  397  
 396  398          mutex_enter(&tems.ts_lock);
 397  399  
 398  400          if (tems.ts_initialized) {
 399  401                  mutex_exit(&tems.ts_lock);
 400  402                  return (0);
 401  403          }
 402  404  
 403  405          /*
 404  406           * Open the layered device using the devfs physical device name
 405  407           * after adding the /devices prefix.
 406  408           */
 407  409          pathbuf = kmem_alloc(MAXPATHLEN, KM_SLEEP);
 408  410          (void) strcpy(pathbuf, "/devices");
 409  411          if (i_ddi_prompath_to_devfspath(pathname,
 410  412              pathbuf + strlen("/devices")) != DDI_SUCCESS) {
 411  413                  cmn_err(CE_WARN, "terminal-emulator:  path conversion error");
 412  414                  kmem_free(pathbuf, MAXPATHLEN);
 413  415  
 414  416                  mutex_exit(&tems.ts_lock);
 415  417                  return (ENXIO);
 416  418          }
 417  419          if (ldi_open_by_name(pathbuf, FWRITE, credp,
 418  420              &tems.ts_hdl, term_li) != 0) {
 419  421                  cmn_err(CE_WARN, "terminal-emulator:  device path open error");
 420  422                  kmem_free(pathbuf, MAXPATHLEN);
 421  423  
 422  424                  mutex_exit(&tems.ts_lock);
 423  425                  return (ENXIO);
 424  426          }
 425  427          kmem_free(pathbuf, MAXPATHLEN);
 426  428  
 427  429          temargs.modechg_cb  = (vis_modechg_cb_t)tems_modechange_callback;
 428  430          temargs.modechg_arg = NULL;
 429  431  
 430  432          /*
 431  433           * Initialize the console and get the device parameters
 432  434           */
 433  435          if (ldi_ioctl(tems.ts_hdl, VIS_DEVINIT,
 434  436              (intptr_t)&temargs, FWRITE|FKIOCTL, credp, &lyr_rval) != 0) {
 435  437                  cmn_err(CE_WARN, "terminal emulator: Compatible fb not found");
 436  438                  ret = tems_failed(credp, B_FALSE);
 437  439                  mutex_exit(&tems.ts_lock);
 438  440                  return (ret);
 439  441          }
 440  442  
 441  443          /* Make sure the fb driver and terminal emulator versions match */
 442  444          if (temargs.version != VIS_CONS_REV) {
 443  445                  cmn_err(CE_WARN,
 444  446                      "terminal emulator: VIS_CONS_REV %d (see sys/visual_io.h) "
 445  447                      "of console fb driver not supported", temargs.version);
 446  448                  ret = tems_failed(credp, B_TRUE);
 447  449                  mutex_exit(&tems.ts_lock);
 448  450                  return (ret);
 449  451          }
 450  452  
  
    | 
      ↓ open down ↓ | 
    99 lines elided | 
    
      ↑ open up ↑ | 
  
 451  453          if ((tems.ts_fb_polledio = temargs.polledio) == NULL) {
 452  454                  cmn_err(CE_WARN, "terminal emulator: fb doesn't support polled "
 453  455                      "I/O");
 454  456                  ret = tems_failed(credp, B_TRUE);
 455  457                  mutex_exit(&tems.ts_lock);
 456  458                  return (ret);
 457  459          }
 458  460  
 459  461          /* other sanity checks */
 460  462          if (!((temargs.depth == 4) || (temargs.depth == 8) ||
      463 +            (temargs.depth == 15) || (temargs.depth == 16) ||
 461  464              (temargs.depth == 24) || (temargs.depth == 32))) {
 462  465                  cmn_err(CE_WARN, "terminal emulator: unsupported depth");
 463  466                  ret = tems_failed(credp, B_TRUE);
 464  467                  mutex_exit(&tems.ts_lock);
 465  468                  return (ret);
 466  469          }
 467  470  
 468  471          if ((temargs.mode != VIS_TEXT) && (temargs.mode != VIS_PIXEL)) {
 469  472                  cmn_err(CE_WARN, "terminal emulator: unsupported mode");
 470  473                  ret = tems_failed(credp, B_TRUE);
 471  474                  mutex_exit(&tems.ts_lock);
 472  475                  return (ret);
 473  476          }
 474  477  
 475  478          if ((temargs.mode == VIS_PIXEL) && plat_stdout_is_framebuffer())
 476  479                  plat_tem_get_prom_size(&height, &width);
 477  480  
 478  481          /*
 479  482           * Initialize the common terminal emulator info
 480  483           */
 481  484          tems_setup_terminal(&temargs, height, width);
 482  485  
 483  486          tems_reset_colormap(credp, CALLED_FROM_NORMAL);
 484  487          tems_get_initial_color(&tems.ts_init_color);
 485  488  
 486  489          tems.ts_initialized = 1; /* initialization flag */
 487  490  
 488  491          for (p = list_head(&tems.ts_list); p != NULL;
 489  492              p = list_next(&tems.ts_list, p)) {
 490  493                  mutex_enter(&p->tvs_lock);
 491  494                  tem_internal_init(p, credp, B_TRUE, B_FALSE);
 492  495                  if (temargs.mode == VIS_PIXEL)
 493  496                          tem_pix_align(p, credp, CALLED_FROM_NORMAL);
 494  497                  mutex_exit(&p->tvs_lock);
 495  498          }
 496  499  
 497  500          mutex_exit(&tems.ts_lock);
 498  501          return (0);
 499  502  }
 500  503  
 501  504  #define TEMS_DEPTH_DIFF         0x01
 502  505  #define TEMS_DIMENSION_DIFF     0x02
 503  506  
 504  507  static uchar_t
 505  508  tems_check_videomode(struct vis_devinit *tp)
 506  509  {
 507  510          uchar_t result = 0;
 508  511  
 509  512          if (tems.ts_pdepth != tp->depth)
 510  513                  result |= TEMS_DEPTH_DIFF;
 511  514  
 512  515          if (tp->mode == VIS_TEXT) {
 513  516                  if (tems.ts_c_dimension.width != tp->width ||
 514  517                      tems.ts_c_dimension.height != tp->height)
 515  518                          result |= TEMS_DIMENSION_DIFF;
 516  519          } else {
 517  520                  if (tems.ts_p_dimension.width != tp->width ||
  
    | 
      ↓ open down ↓ | 
    47 lines elided | 
    
      ↑ open up ↑ | 
  
 518  521                      tems.ts_p_dimension.height != tp->height)
 519  522                          result |= TEMS_DIMENSION_DIFF;
 520  523          }
 521  524  
 522  525          return (result);
 523  526  }
 524  527  
 525  528  static void
 526  529  tems_setup_terminal(struct vis_devinit *tp, size_t height, size_t width)
 527  530  {
      531 +        bitmap_data_t *font_data;
 528  532          int i;
 529      -        int old_blank_buf_size = tems.ts_c_dimension.width;
      533 +        int old_blank_buf_size = tems.ts_c_dimension.width *
      534 +            sizeof (*tems.ts_blank_line);
 530  535  
 531  536          ASSERT(MUTEX_HELD(&tems.ts_lock));
 532  537  
 533  538          tems.ts_pdepth = tp->depth;
 534  539          tems.ts_linebytes = tp->linebytes;
 535  540          tems.ts_display_mode = tp->mode;
      541 +        tems.ts_color_map = tp->color_map;
 536  542  
 537  543          switch (tp->mode) {
 538  544          case VIS_TEXT:
 539  545                  tems.ts_p_dimension.width = 0;
 540  546                  tems.ts_p_dimension.height = 0;
 541  547                  tems.ts_c_dimension.width = tp->width;
 542  548                  tems.ts_c_dimension.height = tp->height;
 543  549                  tems.ts_callbacks = &tem_safe_text_callbacks;
 544  550  
 545  551                  break;
 546  552  
 547  553          case VIS_PIXEL:
 548  554                  /*
 549  555                   * First check to see if the user has specified a screen size.
 550  556                   * If so, use those values.  Else use 34x80 as the default.
 551  557                   */
 552  558                  if (width == 0) {
 553  559                          width = TEM_DEFAULT_COLS;
 554  560                          height = TEM_DEFAULT_ROWS;
 555  561                  }
 556  562                  tems.ts_c_dimension.height = (screen_size_t)height;
 557  563                  tems.ts_c_dimension.width = (screen_size_t)width;
 558  564  
 559  565                  tems.ts_p_dimension.height = tp->height;
 560  566                  tems.ts_p_dimension.width = tp->width;
  
    | 
      ↓ open down ↓ | 
    15 lines elided | 
    
      ↑ open up ↑ | 
  
 561  567  
 562  568                  tems.ts_callbacks = &tem_safe_pix_callbacks;
 563  569  
 564  570                  /*
 565  571                   * set_font() will select a appropriate sized font for
 566  572                   * the number of rows and columns selected.  If we don't
 567  573                   * have a font that will fit, then it will use the
 568  574                   * default builtin font and adjust the rows and columns
 569  575                   * to fit on the screen.
 570  576                   */
 571      -                set_font(&tems.ts_font,
 572      -                    &tems.ts_c_dimension.height,
      577 +                font_data = set_font(&tems.ts_c_dimension.height,
 573  578                      &tems.ts_c_dimension.width,
 574  579                      tems.ts_p_dimension.height,
 575  580                      tems.ts_p_dimension.width);
 576  581  
      582 +                for (i = 0; i < VFNT_MAPS; i++) {
      583 +                        tems.ts_font.vf_map[i] =
      584 +                            font_data->font->vf_map[i];
      585 +                        tems.ts_font.vf_map_count[i] =
      586 +                            font_data->font->vf_map_count[i];
      587 +                }
      588 +                tems.ts_font.vf_bytes = font_data->font->vf_bytes;
      589 +                tems.ts_font.vf_width = font_data->font->vf_width;
      590 +                tems.ts_font.vf_height = font_data->font->vf_height;
      591 +
 577  592                  tems.ts_p_offset.y = (tems.ts_p_dimension.height -
 578      -                    (tems.ts_c_dimension.height * tems.ts_font.height)) / 2;
      593 +                    (tems.ts_c_dimension.height * tems.ts_font.vf_height)) / 2;
 579  594                  tems.ts_p_offset.x = (tems.ts_p_dimension.width -
 580      -                    (tems.ts_c_dimension.width * tems.ts_font.width)) / 2;
      595 +                    (tems.ts_c_dimension.width * tems.ts_font.vf_width)) / 2;
 581  596  
 582  597                  tems.ts_pix_data_size =
 583      -                    tems.ts_font.width * tems.ts_font.height;
      598 +                    tems.ts_font.vf_width * tems.ts_font.vf_height;
 584  599  
 585  600                  tems.ts_pix_data_size *= 4;
 586  601  
 587  602                  tems.ts_pdepth = tp->depth;
 588  603  
 589  604                  break;
 590  605          }
 591  606  
 592  607          /* Now virtual cls also uses the blank_line buffer */
 593  608          if (tems.ts_blank_line)
 594  609                  kmem_free(tems.ts_blank_line, old_blank_buf_size);
 595  610  
 596      -        tems.ts_blank_line = (unsigned char *)
 597      -            kmem_alloc(tems.ts_c_dimension.width, KM_SLEEP);
 598      -        for (i = 0; i < tems.ts_c_dimension.width; i++)
 599      -                tems.ts_blank_line[i] = ' ';
      611 +        tems.ts_blank_line = kmem_alloc(tems.ts_c_dimension.width *
      612 +            sizeof (*tems.ts_blank_line), KM_SLEEP);
 600  613  }
 601  614  
 602  615  /*
 603  616   * This is a callback function that we register with the frame
 604  617   * buffer driver layered underneath.  It gets invoked from
 605  618   * the underlying frame buffer driver to reconfigure the terminal
 606  619   * emulator to a new screen size and depth in conjunction with
 607  620   * framebuffer videomode changes.
 608  621   * Here we keep the foreground/background color and attributes,
 609  622   * which may be different with the initial settings, so that
 610  623   * the color won't change while the framebuffer videomode changes.
 611  624   * And we also reset the kernel terminal emulator and clear the
 612  625   * whole screen.
 613  626   */
 614  627  /* ARGSUSED */
 615  628  void
 616  629  tems_modechange_callback(struct vis_modechg_arg *arg,
 617  630      struct vis_devinit *devinit)
 618  631  {
 619  632          uchar_t diff;
 620  633          struct tem_vt_state *p;
 621  634          tem_modechg_cb_t cb;
 622  635          tem_modechg_cb_arg_t cb_arg;
 623  636  
 624  637          ASSERT(!(list_is_empty(&tems.ts_list)));
 625  638  
 626  639          mutex_enter(&tems.ts_lock);
 627  640  
 628  641          /*
 629  642           * currently only for pixel mode
 630  643           */
 631  644          diff = tems_check_videomode(devinit);
 632  645          if (diff == 0) {
 633  646                  mutex_exit(&tems.ts_lock);
 634  647                  return;
 635  648          }
 636  649  
 637  650          diff = diff & TEMS_DIMENSION_DIFF;
 638  651  
 639  652          if (diff == 0) {
 640  653                  /*
 641  654                   * Only need to reinit the active tem.
 642  655                   */
 643  656                  struct tem_vt_state *active = tems.ts_active;
 644  657                  tems.ts_pdepth = devinit->depth;
 645  658  
 646  659                  mutex_enter(&active->tvs_lock);
 647  660                  ASSERT(active->tvs_isactive);
 648  661                  tem_reinit(active, B_TRUE);
 649  662                  mutex_exit(&active->tvs_lock);
 650  663  
 651  664                  mutex_exit(&tems.ts_lock);
 652  665                  return;
 653  666          }
 654  667  
 655  668          tems_setup_terminal(devinit, tems.ts_c_dimension.height,
 656  669              tems.ts_c_dimension.width);
 657  670  
 658  671          for (p = list_head(&tems.ts_list); p != NULL;
 659  672              p = list_next(&tems.ts_list, p)) {
 660  673                  mutex_enter(&p->tvs_lock);
 661  674                  tem_reinit(p, p->tvs_isactive);
 662  675                  mutex_exit(&p->tvs_lock);
 663  676          }
 664  677  
 665  678  
 666  679          if (tems.ts_modechg_cb == NULL) {
 667  680                  mutex_exit(&tems.ts_lock);
 668  681                  return;
 669  682          }
 670  683  
 671  684          cb = tems.ts_modechg_cb;
  
    | 
      ↓ open down ↓ | 
    62 lines elided | 
    
      ↑ open up ↑ | 
  
 672  685          cb_arg = tems.ts_modechg_arg;
 673  686  
 674  687          /*
 675  688           * Release the lock while doing callback.
 676  689           */
 677  690          mutex_exit(&tems.ts_lock);
 678  691          cb(cb_arg);
 679  692  }
 680  693  
 681  694  /*
      695 + * This function is used to clear entire screen via the underlying framebuffer
      696 + * driver.
      697 + */
      698 +int
      699 +tems_cls_layered(struct vis_consclear *pda,
      700 +    cred_t *credp)
      701 +{
      702 +        int rval;
      703 +
      704 +        (void) ldi_ioctl(tems.ts_hdl, VIS_CONSCLEAR,
      705 +            (intptr_t)pda, FKIOCTL, credp, &rval);
      706 +        return (rval);
      707 +}
      708 +
      709 +/*
 682  710   * This function is used to display a rectangular blit of data
 683  711   * of a given size and location via the underlying framebuffer driver.
 684  712   * The blit can be as small as a pixel or as large as the screen.
 685  713   */
 686  714  void
 687      -tems_display_layered(
 688      -        struct vis_consdisplay *pda,
 689      -        cred_t *credp)
      715 +tems_display_layered(struct vis_consdisplay *pda,
      716 +    cred_t *credp)
 690  717  {
 691  718          int rval;
 692  719  
 693  720          (void) ldi_ioctl(tems.ts_hdl, VIS_CONSDISPLAY,
 694  721              (intptr_t)pda, FKIOCTL, credp, &rval);
 695  722  }
 696  723  
 697  724  /*
 698  725   * This function is used to invoke a block copy operation in the
 699  726   * underlying framebuffer driver.  Rectangle copies are how scrolling
 700  727   * is implemented, as well as horizontal text shifting escape seqs.
 701  728   * such as from vi when deleting characters and words.
 702  729   */
 703  730  void
 704      -tems_copy_layered(
 705      -        struct vis_conscopy *pma,
 706      -        cred_t *credp)
      731 +tems_copy_layered(struct vis_conscopy *pma,
      732 +    cred_t *credp)
 707  733  {
 708  734          int rval;
 709  735  
 710  736          (void) ldi_ioctl(tems.ts_hdl, VIS_CONSCOPY,
 711  737              (intptr_t)pma, FKIOCTL, credp, &rval);
 712  738  }
 713  739  
 714  740  /*
 715  741   * This function is used to show or hide a rectangluar monochrom
 716  742   * pixel inverting, text block cursor via the underlying framebuffer.
 717  743   */
 718  744  void
 719      -tems_cursor_layered(
 720      -        struct vis_conscursor *pca,
 721      -        cred_t *credp)
      745 +tems_cursor_layered(struct vis_conscursor *pca,
      746 +    cred_t *credp)
 722  747  {
 723  748          int rval;
 724  749  
 725  750          (void) ldi_ioctl(tems.ts_hdl, VIS_CONSCURSOR,
 726  751              (intptr_t)pca, FKIOCTL, credp, &rval);
 727  752  }
 728  753  
 729  754  static void
 730  755  tem_kdsetmode(int mode, cred_t *credp)
 731  756  {
 732  757          int rval;
 733  758  
 734  759          (void) ldi_ioctl(tems.ts_hdl, KDSETMODE,
 735  760              (intptr_t)mode, FKIOCTL, credp, &rval);
 736  761  
 737  762  }
 738  763  
 739  764  static void
 740  765  tems_reset_colormap(cred_t *credp, enum called_from called_from)
 741  766  {
  
    | 
      ↓ open down ↓ | 
    10 lines elided | 
    
      ↑ open up ↑ | 
  
 742  767          struct vis_cmap cm;
 743  768          int rval;
 744  769  
 745  770          if (called_from == CALLED_FROM_STANDALONE)
 746  771                  return;
 747  772  
 748  773          switch (tems.ts_pdepth) {
 749  774          case 8:
 750  775                  cm.index = 0;
 751  776                  cm.count = 16;
 752      -                cm.red   = cmap4_to_24.red;   /* 8-bits (1/3 of TrueColor 24) */
 753      -                cm.blue  = cmap4_to_24.blue;  /* 8-bits (1/3 of TrueColor 24) */
 754      -                cm.green = cmap4_to_24.green; /* 8-bits (1/3 of TrueColor 24) */
      777 +                /* 8-bits (1/3 of TrueColor 24) */
      778 +                cm.red   = (uint8_t *)cmap4_to_24.red;
      779 +                /* 8-bits (1/3 of TrueColor 24) */
      780 +                cm.blue  = (uint8_t *)cmap4_to_24.blue;
      781 +                /* 8-bits (1/3 of TrueColor 24) */
      782 +                cm.green = (uint8_t *)cmap4_to_24.green;
 755  783                  (void) ldi_ioctl(tems.ts_hdl, VIS_PUTCMAP, (intptr_t)&cm,
 756  784                      FKIOCTL, credp, &rval);
 757  785                  break;
 758  786          }
 759  787  }
 760  788  
 761  789  void
 762  790  tem_get_size(ushort_t *r, ushort_t *c, ushort_t *x, ushort_t *y)
 763  791  {
 764  792          mutex_enter(&tems.ts_lock);
 765  793          *r = (ushort_t)tems.ts_c_dimension.height;
 766  794          *c = (ushort_t)tems.ts_c_dimension.width;
 767  795          *x = (ushort_t)tems.ts_p_dimension.width;
 768  796          *y = (ushort_t)tems.ts_p_dimension.height;
 769  797          mutex_exit(&tems.ts_lock);
 770  798  }
 771  799  
 772  800  void
 773  801  tem_register_modechg_cb(tem_modechg_cb_t func, tem_modechg_cb_arg_t arg)
 774  802  {
 775  803          mutex_enter(&tems.ts_lock);
 776  804  
 777  805          tems.ts_modechg_cb = func;
 778  806          tems.ts_modechg_arg = arg;
 779  807  
 780  808          mutex_exit(&tems.ts_lock);
 781  809  }
 782  810  
 783  811  /*
 784  812   * This function is to scroll up the OBP output, which has
  
    | 
      ↓ open down ↓ | 
    20 lines elided | 
    
      ↑ open up ↑ | 
  
 785  813   * different screen height and width with our kernel console.
 786  814   */
 787  815  static void
 788  816  tem_prom_scroll_up(struct tem_vt_state *tem, int nrows, cred_t *credp,
 789  817      enum called_from called_from)
 790  818  {
 791  819          struct vis_conscopy     ma;
 792  820          int     ncols, width;
 793  821  
 794  822          /* copy */
 795      -        ma.s_row = nrows * tems.ts_font.height;
      823 +        ma.s_row = nrows * tems.ts_font.vf_height;
 796  824          ma.e_row = tems.ts_p_dimension.height - 1;
 797  825          ma.t_row = 0;
 798  826  
 799  827          ma.s_col = 0;
 800  828          ma.e_col = tems.ts_p_dimension.width - 1;
 801  829          ma.t_col = 0;
 802  830  
 803  831          tems_safe_copy(&ma, credp, called_from);
 804  832  
 805  833          /* clear */
 806      -        width = tems.ts_font.width;
      834 +        width = tems.ts_font.vf_width;
 807  835          ncols = (tems.ts_p_dimension.width + (width - 1))/ width;
 808  836  
 809  837          tem_safe_pix_cls_range(tem, 0, nrows, tems.ts_p_offset.y,
 810  838              0, ncols, 0, B_TRUE, credp, called_from);
 811  839  }
 812  840  
 813  841  #define PROM_DEFAULT_FONT_HEIGHT        22
 814  842  #define PROM_DEFAULT_WINDOW_TOP         0x8a
 815  843  
 816  844  /*
 817  845   * This function is to compute the starting row of the console, according to
 818  846   * PROM cursor's position. Here we have to take different fonts into account.
 819  847   */
 820  848  static int
 821  849  tem_adjust_row(struct tem_vt_state *tem, int prom_row, cred_t *credp,
 822  850      enum called_from called_from)
 823  851  {
 824  852          int     tem_row;
 825  853          int     tem_y;
 826  854          int     prom_charheight = 0;
 827  855          int     prom_window_top = 0;
  
    | 
      ↓ open down ↓ | 
    11 lines elided | 
    
      ↑ open up ↑ | 
  
 828  856          int     scroll_up_lines;
 829  857  
 830  858          plat_tem_get_prom_font_size(&prom_charheight, &prom_window_top);
 831  859          if (prom_charheight == 0)
 832  860                  prom_charheight = PROM_DEFAULT_FONT_HEIGHT;
 833  861          if (prom_window_top == 0)
 834  862                  prom_window_top = PROM_DEFAULT_WINDOW_TOP;
 835  863  
 836  864          tem_y = (prom_row + 1) * prom_charheight + prom_window_top -
 837  865              tems.ts_p_offset.y;
 838      -        tem_row = (tem_y + tems.ts_font.height - 1) /
 839      -            tems.ts_font.height - 1;
      866 +        tem_row = (tem_y + tems.ts_font.vf_height - 1) /
      867 +            tems.ts_font.vf_height - 1;
 840  868  
 841  869          if (tem_row < 0) {
 842  870                  tem_row = 0;
 843  871          } else if (tem_row >= (tems.ts_c_dimension.height - 1)) {
 844  872                  /*
 845  873                   * Scroll up the prom outputs if the PROM cursor's position is
 846  874                   * below our tem's lower boundary.
 847  875                   */
 848  876                  scroll_up_lines = tem_row -
 849  877                      (tems.ts_c_dimension.height - 1);
 850  878                  tem_prom_scroll_up(tem, scroll_up_lines, credp, called_from);
 851  879                  tem_row = tems.ts_c_dimension.height - 1;
 852  880          }
 853  881  
 854  882          return (tem_row);
 855  883  }
 856  884  
 857  885  void
 858  886  tem_pix_align(struct tem_vt_state *tem, cred_t *credp,
 859  887      enum called_from called_from)
 860  888  {
 861  889          uint32_t row = 0;
 862  890          uint32_t col = 0;
 863  891  
 864  892          if (plat_stdout_is_framebuffer()) {
 865  893                  plat_tem_hide_prom_cursor();
 866  894  
 867  895                  /*
 868  896                   * We are getting the current cursor position in pixel
 869  897                   * mode so that we don't over-write the console output
 870  898                   * during boot.
 871  899                   */
 872  900                  plat_tem_get_prom_pos(&row, &col);
 873  901  
 874  902                  /*
 875  903                   * Adjust the row if necessary when the font of our
 876  904                   * kernel console tem is different with that of prom
 877  905                   * tem.
 878  906                   */
 879  907                  row = tem_adjust_row(tem, row, credp, called_from);
 880  908  
 881  909                  /* first line of our kernel console output */
 882  910                  tem->tvs_first_line = row + 1;
 883  911  
 884  912                  /* re-set and align cusror position */
 885  913                  tem->tvs_s_cursor.row = tem->tvs_c_cursor.row =
 886  914                      (screen_pos_t)row;
 887  915                  tem->tvs_s_cursor.col = tem->tvs_c_cursor.col = 0;
 888  916          } else {
 889  917                  tem_safe_reset_display(tem, credp, called_from, B_TRUE, B_TRUE);
 890  918          }
 891  919  }
 892  920  
 893  921  static void
 894  922  tems_get_inverses(boolean_t *p_inverse, boolean_t *p_inverse_screen)
 895  923  {
 896  924          int i_inverse = 0;
 897  925          int i_inverse_screen = 0;
 898  926  
 899  927          plat_tem_get_inverses(&i_inverse, &i_inverse_screen);
 900  928  
 901  929          *p_inverse = (i_inverse == 0) ? B_FALSE : B_TRUE;
 902  930          *p_inverse_screen = (i_inverse_screen == 0) ? B_FALSE : B_TRUE;
 903  931  }
 904  932  
 905  933  /*
 906  934   * Get the foreground/background color and attributes from the initial
  
    | 
      ↓ open down ↓ | 
    57 lines elided | 
    
      ↑ open up ↑ | 
  
 907  935   * PROM, so that our kernel console can keep the same visual behaviour.
 908  936   */
 909  937  static void
 910  938  tems_get_initial_color(tem_color_t *pcolor)
 911  939  {
 912  940          boolean_t inverse, inverse_screen;
 913  941          unsigned short  flags = 0;
 914  942  
 915  943          pcolor->fg_color = DEFAULT_ANSI_FOREGROUND;
 916  944          pcolor->bg_color = DEFAULT_ANSI_BACKGROUND;
      945 +#ifndef _HAVE_TEM_FIRMWARE
      946 +        plat_tem_get_colors(&pcolor->fg_color, &pcolor->bg_color);
      947 +#endif
 917  948  
 918      -        if (plat_stdout_is_framebuffer()) {
 919      -                tems_get_inverses(&inverse, &inverse_screen);
 920      -                if (inverse)
 921      -                        flags |= TEM_ATTR_REVERSE;
 922      -                if (inverse_screen)
 923      -                        flags |= TEM_ATTR_SCREEN_REVERSE;
      949 +        tems_get_inverses(&inverse, &inverse_screen);
      950 +        if (inverse)
      951 +                flags |= TEM_ATTR_REVERSE;
      952 +        if (inverse_screen)
      953 +                flags |= TEM_ATTR_SCREEN_REVERSE;
 924  954  
 925      -                if (flags != 0) {
 926      -                        /*
 927      -                         * If either reverse flag is set, the screen is in
 928      -                         * white-on-black mode.  We set the bold flag to
 929      -                         * improve readability.
 930      -                         */
 931      -                        flags |= TEM_ATTR_BOLD;
 932      -                } else {
 933      -                        /*
 934      -                         * Otherwise, the screen is in black-on-white mode.
 935      -                         * The SPARC PROM console, which starts in this mode,
 936      -                         * uses the bright white background colour so we
 937      -                         * match it here.
 938      -                         */
 939      -                        if (pcolor->bg_color == ANSI_COLOR_WHITE)
 940      -                                flags |= TEM_ATTR_BRIGHT_BG;
 941      -                }
      955 +        if (flags != 0) {
      956 +                /*
      957 +                 * If either reverse flag is set, the screen is in
      958 +                 * white-on-black mode.  We set the bold flag to
      959 +                 * improve readability.
      960 +                 */
      961 +                flags |= TEM_ATTR_BOLD;
      962 +        } else {
      963 +                /*
      964 +                 * Otherwise, the screen is in black-on-white mode.
      965 +                 * The SPARC PROM console, which starts in this mode,
      966 +                 * uses the bright white background colour so we
      967 +                 * match it here.
      968 +                 */
      969 +                if (pcolor->bg_color == ANSI_COLOR_WHITE)
      970 +                        flags |= TEM_ATTR_BRIGHT_BG;
 942  971          }
 943  972  
 944  973          pcolor->a_flags = flags;
 945  974  }
 946  975  
 947  976  uchar_t
 948  977  tem_get_fbmode(tem_vt_state_t tem_arg)
 949  978  {
 950  979          struct tem_vt_state *tem = (struct tem_vt_state *)tem_arg;
 951  980  
 952  981          uchar_t fbmode;
 953  982  
 954  983          mutex_enter(&tem->tvs_lock);
 955  984          fbmode = tem->tvs_fbmode;
 956  985          mutex_exit(&tem->tvs_lock);
 957  986  
 958  987          return (fbmode);
 959  988  }
 960  989  
 961  990  void
 962  991  tem_set_fbmode(tem_vt_state_t tem_arg, uchar_t fbmode, cred_t *credp)
 963  992  {
 964  993          struct tem_vt_state *tem = (struct tem_vt_state *)tem_arg;
 965  994  
 966  995          mutex_enter(&tems.ts_lock);
 967  996          mutex_enter(&tem->tvs_lock);
 968  997  
 969  998          if (fbmode == tem->tvs_fbmode) {
 970  999                  mutex_exit(&tem->tvs_lock);
 971 1000                  mutex_exit(&tems.ts_lock);
 972 1001                  return;
 973 1002          }
 974 1003  
 975 1004          tem->tvs_fbmode = fbmode;
 976 1005  
 977 1006          if (tem->tvs_isactive) {
 978 1007                  tem_kdsetmode(tem->tvs_fbmode, credp);
 979 1008                  if (fbmode == KD_TEXT)
 980 1009                          tem_safe_unblank_screen(tem, credp, CALLED_FROM_NORMAL);
 981 1010          }
 982 1011  
 983 1012          mutex_exit(&tem->tvs_lock);
 984 1013          mutex_exit(&tems.ts_lock);
 985 1014  }
 986 1015  
 987 1016  void
 988 1017  tem_activate(tem_vt_state_t tem_arg, boolean_t unblank, cred_t *credp)
 989 1018  {
 990 1019          struct tem_vt_state *tem = (struct tem_vt_state *)tem_arg;
 991 1020  
 992 1021          mutex_enter(&tems.ts_lock);
 993 1022          tems.ts_active = tem;
 994 1023  
 995 1024          mutex_enter(&tem->tvs_lock);
 996 1025          tem->tvs_isactive = B_TRUE;
 997 1026  
 998 1027          tem_kdsetmode(tem->tvs_fbmode, credp);
 999 1028  
1000 1029          if (unblank)
1001 1030                  tem_safe_unblank_screen(tem, credp, CALLED_FROM_NORMAL);
1002 1031  
1003 1032          mutex_exit(&tem->tvs_lock);
1004 1033          mutex_exit(&tems.ts_lock);
1005 1034  }
1006 1035  
1007 1036  void
1008 1037  tem_switch(tem_vt_state_t tem_arg1, tem_vt_state_t tem_arg2, cred_t *credp)
1009 1038  {
1010 1039          struct tem_vt_state *cur = (struct tem_vt_state *)tem_arg1;
1011 1040          struct tem_vt_state *tobe = (struct tem_vt_state *)tem_arg2;
1012 1041  
1013 1042          mutex_enter(&tems.ts_lock);
1014 1043          mutex_enter(&tobe->tvs_lock);
1015 1044          mutex_enter(&cur->tvs_lock);
1016 1045  
1017 1046          tems.ts_active = tobe;
1018 1047          cur->tvs_isactive = B_FALSE;
1019 1048          tobe->tvs_isactive = B_TRUE;
1020 1049  
1021 1050          mutex_exit(&cur->tvs_lock);
1022 1051  
1023 1052          if (cur->tvs_fbmode != tobe->tvs_fbmode)
1024 1053                  tem_kdsetmode(tobe->tvs_fbmode, credp);
1025 1054  
1026 1055          if (tobe->tvs_fbmode == KD_TEXT)
1027 1056                  tem_safe_unblank_screen(tobe, credp, CALLED_FROM_NORMAL);
1028 1057  
1029 1058          mutex_exit(&tobe->tvs_lock);
1030 1059          mutex_exit(&tems.ts_lock);
1031 1060  }
  
    | 
      ↓ open down ↓ | 
    80 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX