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>

@@ -85,22 +85,21 @@
         &tem_safe_pix_cursor,
         &tem_safe_pix_bit2pix,
         &tem_safe_pix_cls
 };
 
-
-static void     tem_safe_control(struct tem_vt_state *, uchar_t,
+static void     tem_safe_control(struct tem_vt_state *, tem_char_t,
                         cred_t *, enum called_from);
 static void     tem_safe_setparam(struct tem_vt_state *, int, int);
 static void     tem_safe_selgraph(struct tem_vt_state *);
-static void     tem_safe_chkparam(struct tem_vt_state *, uchar_t,
+static void     tem_safe_chkparam(struct tem_vt_state *, tem_char_t,
                         cred_t *, enum called_from);
-static void     tem_safe_getparams(struct tem_vt_state *, uchar_t,
+static void     tem_safe_getparams(struct tem_vt_state *, tem_char_t,
                         cred_t *, enum called_from);
-static void     tem_safe_outch(struct tem_vt_state *, uchar_t,
+static void     tem_safe_outch(struct tem_vt_state *, tem_char_t,
                         cred_t *, enum called_from);
-static void     tem_safe_parse(struct tem_vt_state *, uchar_t,
+static void     tem_safe_parse(struct tem_vt_state *, tem_char_t,
                         cred_t *, enum called_from);
 
 static void     tem_safe_new_line(struct tem_vt_state *,
                         cred_t *, enum called_from);
 static void     tem_safe_cr(struct tem_vt_state *);

@@ -135,44 +134,31 @@
                         cred_t *, enum called_from);
 static void     tem_safe_bell(struct tem_vt_state *tem,
                         enum called_from called_from);
 static void     tem_safe_pix_clear_prom_output(struct tem_vt_state *tem,
                         cred_t *credp, enum called_from called_from);
+static void     tem_safe_get_color(text_color_t *, text_color_t *, term_char_t);
 
 static void     tem_safe_virtual_cls(struct tem_vt_state *, int, screen_pos_t,
                     screen_pos_t);
 static void     tem_safe_virtual_display(struct tem_vt_state *,
-                    unsigned char *, int, screen_pos_t, screen_pos_t,
-                    text_color_t, text_color_t);
+                    term_char_t *, int, screen_pos_t, screen_pos_t);
 static void     tem_safe_virtual_copy(struct tem_vt_state *, screen_pos_t,
                     screen_pos_t, screen_pos_t, screen_pos_t,
                     screen_pos_t, screen_pos_t);
 static void     tem_safe_align_cursor(struct tem_vt_state *tem);
-static void     bit_to_pix4(struct tem_vt_state *tem, uchar_t c,
+static void     bit_to_pix4(struct tem_vt_state *tem, tem_char_t c,
                     text_color_t fg_color, text_color_t bg_color);
-static void     bit_to_pix8(struct tem_vt_state *tem, uchar_t c,
+static void     bit_to_pix8(struct tem_vt_state *tem, tem_char_t c,
                     text_color_t fg_color, text_color_t bg_color);
-static void     bit_to_pix24(struct tem_vt_state *tem, uchar_t c,
+static void     bit_to_pix16(struct tem_vt_state *tem, tem_char_t c,
                     text_color_t fg_color, text_color_t bg_color);
+static void     bit_to_pix24(struct tem_vt_state *tem, tem_char_t c,
+                    text_color_t fg_color, text_color_t bg_color);
+static void     bit_to_pix32(struct tem_vt_state *tem, tem_char_t c,
+                    text_color_t fg_color, text_color_t bg_color);
 
-/* BEGIN CSTYLED */
-/*                                  Bk  Rd  Gr  Br  Bl  Mg  Cy  Wh */
-static text_color_t dim_xlate[] = {  1,  5,  3,  7,  2,  6,  4,  8 };
-static text_color_t brt_xlate[] = {  9, 13, 11, 15, 10, 14, 12,  0 };
-/* END CSTYLED */
-
-
-text_cmap_t cmap4_to_24 = {
-/* BEGIN CSTYLED */
-/* 0    1    2    3    4    5    6    7    8    9   10   11   12   13   14   15
-  Wh+  Bk   Bl   Gr   Cy   Rd   Mg   Br   Wh   Bk+  Bl+  Gr+  Cy+  Rd+  Mg+  Yw */
-  0xff,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x40,0x00,0x00,0x00,0xff,0xff,0xff,
-  0xff,0x00,0x00,0x80,0x80,0x00,0x00,0x80,0x80,0x40,0x00,0xff,0xff,0x00,0x00,0xff,
-  0xff,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x40,0xff,0x00,0xff,0x00,0xff,0x00
-/* END CSTYLED */
-};
-
 #define PIX4TO32(pix4) (uint32_t)(  \
     cmap4_to_24.red[pix4] << 16 |  \
     cmap4_to_24.green[pix4] << 8 | \
     cmap4_to_24.blue[pix4])
 

@@ -180,13 +166,13 @@
 
 #define tem_safe_callback_display       (*tems.ts_callbacks->tsc_display)
 #define tem_safe_callback_copy          (*tems.ts_callbacks->tsc_copy)
 #define tem_safe_callback_cursor        (*tems.ts_callbacks->tsc_cursor)
 #define tem_safe_callback_cls           (*tems.ts_callbacks->tsc_cls)
-#define tem_safe_callback_bit2pix(tem, c, fg, bg)       {               \
+#define tem_safe_callback_bit2pix(tem, c)       {               \
         ASSERT(tems.ts_callbacks->tsc_bit2pix != NULL);                 \
-        (void) (*tems.ts_callbacks->tsc_bit2pix)((tem), (c), (fg), (bg));\
+        (void) (*tems.ts_callbacks->tsc_bit2pix)((tem), (c));\
 }
 
 void
 tem_safe_check_first_time(
     struct tem_vt_state *tem,

@@ -206,14 +192,15 @@
          */
         if (!first_time)
                 return;
 
         first_time = 0;
-        if (tems.ts_display_mode == VIS_TEXT) {
+        if (tems.ts_display_mode == VIS_TEXT)
                 tem_safe_text_cursor(tem, VIS_GET_CURSOR, credp, called_from);
+        else
+                tem_safe_pix_cursor(tem, VIS_GET_CURSOR, credp, called_from);
                 tem_safe_align_cursor(tem);
-        }
 }
 
 /*
  * This entry point handles output requests from restricted contexts like
  * kmdb, where services like mutexes are not available. This function

@@ -247,11 +234,11 @@
 /* Process partial UTF-8 sequence. */
 static void
 tem_safe_input_partial(struct tem_vt_state *tem, cred_t *credp,
     enum called_from called_from)
 {
-        int i;
+        unsigned i;
         uint8_t c;
 
         if (tem->tvs_utf8_left == 0)
                 return;
 

@@ -342,13 +329,10 @@
                                 v = b & 0x1f;   /* Two-byte sequence */
                                 b = u & 0xff;
                                 v = (v << 6) | (b & 0x3f);
                         }
 
-                        /* Use '?' as replacement if needed. */
-                        if (v > 0xff)
-                                v = '?';
                         tem_safe_parse(tem, v, credp, called_from);
                         tem->tvs_utf8_partial = 0;
                 }
                 return;
         }

@@ -444,11 +428,11 @@
  * send the appropriate control message or set state based on the
  * value of the control character ch
  */
 
 static void
-tem_safe_control(struct tem_vt_state *tem, uchar_t ch, cred_t *credp,
+tem_safe_control(struct tem_vt_state *tem, tem_char_t ch, cred_t *credp,
     enum called_from called_from)
 {
         tem->tvs_state = A_STATE_START;
         switch (ch) {
         case A_BEL:

@@ -503,10 +487,23 @@
                                 tem->tvs_params[i] = -1;
                         tem->tvs_state = A_STATE_CSI;
                 }
                 break;
 
+        case A_OSC:
+                {
+                        int i;
+                        tem->tvs_curparam = 0;
+                        tem->tvs_paramval = 0;
+                        tem->tvs_gotparam = B_FALSE;
+                        /* clear the parameters */
+                        for (i = 0; i < TEM_MAXPARAMS; i++)
+                                tem->tvs_params[i] = -1;
+                        tem->tvs_state = A_STATE_OSC;
+                }
+                break;
+
         case A_GS:
                 tem_safe_back_tab(tem, credp, called_from);
                 break;
 
         default:

@@ -563,10 +560,13 @@
 
                 case 2: /* Faint Intense */
                         tem->tvs_flags &= ~TEM_ATTR_BOLD;
                         break;
 
+                case 4: /* Underline */
+                        tem->tvs_flags |= TEM_ATTR_UNDERLINE;
+                        break;
                 case 5: /* Blink */
                         tem->tvs_flags |= TEM_ATTR_BLINK;
                         break;
 
                 case 7: /* Reverse video */

@@ -575,10 +575,30 @@
                         } else {
                                 tem->tvs_flags |= TEM_ATTR_REVERSE;
                         }
                         break;
 
+                case 22: /* Remove Bold */
+                        tem->tvs_flags &= ~TEM_ATTR_BOLD;
+                        break;
+
+                case 24: /* Remove Underline */
+                        tem->tvs_flags &= ~TEM_ATTR_UNDERLINE;
+                        break;
+
+                case 25: /* Remove Blink */
+                        tem->tvs_flags &= ~TEM_ATTR_BLINK;
+                        break;
+
+                case 27: /* Remove Reverse */
+                        if (tem->tvs_flags & TEM_ATTR_SCREEN_REVERSE) {
+                                tem->tvs_flags |= TEM_ATTR_REVERSE;
+                        } else {
+                                tem->tvs_flags &= ~TEM_ATTR_REVERSE;
+                        }
+                        break;
+
                 case 30: /* black       (grey)          foreground */
                 case 31: /* red         (light red)     foreground */
                 case 32: /* green       (light green)   foreground */
                 case 33: /* brown       (yellow)        foreground */
                 case 34: /* blue        (light blue)    foreground */

@@ -661,11 +681,11 @@
  *
  * General rule:  This code does not validate the arguments passed.
  *                It assumes that the next lower level will do so.
  */
 static void
-tem_safe_chkparam(struct tem_vt_state *tem, uchar_t ch, cred_t *credp,
+tem_safe_chkparam(struct tem_vt_state *tem, tem_char_t ch, cred_t *credp,
     enum called_from called_from)
 {
         int     i;
         int     row;
         int     col;

@@ -924,11 +944,11 @@
 
 /*
  * Gather the parameters of an ANSI escape sequence
  */
 static void
-tem_safe_getparams(struct tem_vt_state *tem, uchar_t ch,
+tem_safe_getparams(struct tem_vt_state *tem, tem_char_t ch,
     cred_t *credp, enum called_from called_from)
 {
         ASSERT((called_from == CALLED_FROM_STANDALONE) ||
             MUTEX_HELD(&tem->tvs_lock));
 

@@ -959,25 +979,86 @@
                 }
         }
 }
 
 /*
+ * Gather the OSC string.
+ * OSC Ps ; Pt ST
+ * OSC Ps ; Pt BEL
+ * Ps is number sequence identifying the function. We only support
+ * Ps = 4 and Ps = 104.
+ * Quite obviously this is nowhere close to be done;)
+ */
+/* ARGSUSED */
+static void
+tem_safe_get_oscstring(struct tem_vt_state *tem, uchar_t ch,
+    cred_t *credp __unused, enum called_from called_from)
+{
+        ASSERT((called_from == CALLED_FROM_STANDALONE) ||
+            MUTEX_HELD(&tem->tvs_lock));
+
+        /* Should we cancel? */
+        if (ch == A_CAN || ch == A_SUB || ch == A_ESC) {
+                tem->tvs_state = A_STATE_START;
+                return;
+        }
+
+        /* following two if statements will read in the numeric parameter */
+        if (ch >= '0' && ch <= '9') {
+                tem->tvs_paramval = ((tem->tvs_paramval * 10) + (ch - '0'));
+                tem->tvs_gotparam = B_TRUE;  /* Remember got parameter */
+                return; /* Return immediately */
+        }
+
+        if (tem->tvs_gotparam && ch == ';') {
+                /* get the parameter value */
+                tem->tvs_params[tem->tvs_curparam] = tem->tvs_paramval;
+                tem->tvs_curparam++;
+                tem->tvs_gotparam = B_FALSE;
+                tem->tvs_paramval = 0;
+        }
+
+        if (tem->tvs_curparam == 0) {
+                /* bad sequence */
+                tem->tvs_state = A_STATE_START;
+                return;
+        }
+        if (tem->tvs_gotparam == B_FALSE && tem->tvs_curparam > 0) {
+                if (tem->tvs_params[0] != 4 && tem->tvs_params[0] != 104) {
+                        /* make sure tvs_params will not get filled up */
+                        tem->tvs_curparam = 1;
+                }
+        }
+        if (ch == A_ST || ch == A_BEL) {
+                /* done */
+                tem->tvs_state = A_STATE_START;
+                return;
+        }
+}
+
+/*
  * Add character to internal buffer.
  * When its full, send it to the next layer.
  */
 
 static void
-tem_safe_outch(struct tem_vt_state *tem, uchar_t ch,
+tem_safe_outch(struct tem_vt_state *tem, tem_char_t ch,
     cred_t *credp, enum called_from called_from)
 {
+        text_color_t fg;
+        text_color_t bg;
+        text_attr_t attr;
 
         ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
             called_from == CALLED_FROM_STANDALONE);
 
         /* buffer up the character until later */
-
-        tem->tvs_outbuf[tem->tvs_outindex++] = ch;
+        tem_safe_get_attr(tem, &fg, &bg, &attr, TEM_ATTR_REVERSE);
+        tem->tvs_outbuf[tem->tvs_outindex].tc_char = ch | TEM_ATTR(attr);
+        tem->tvs_outbuf[tem->tvs_outindex].tc_fg_color = fg;
+        tem->tvs_outbuf[tem->tvs_outindex].tc_bg_color = bg;
+        tem->tvs_outindex++;
         tem->tvs_c_cursor.col++;
         if (tem->tvs_c_cursor.col >= tems.ts_c_dimension.width) {
                 tem_safe_send_data(tem, credp, called_from);
                 tem_safe_new_line(tem, credp, called_from);
         }

@@ -1052,35 +1133,29 @@
 
 static void
 tem_safe_send_data(struct tem_vt_state *tem, cred_t *credp,
     enum called_from called_from)
 {
-        text_color_t fg_color;
-        text_color_t bg_color;
-
         ASSERT((called_from == CALLED_FROM_STANDALONE) ||
             MUTEX_HELD(&tem->tvs_lock));
 
         if (tem->tvs_outindex == 0) {
                 tem_safe_align_cursor(tem);
                 return;
         }
 
-        tem_safe_get_color(tem, &fg_color, &bg_color, TEM_ATTR_REVERSE);
         tem_safe_virtual_display(tem,
             tem->tvs_outbuf, tem->tvs_outindex,
-            tem->tvs_s_cursor.row, tem->tvs_s_cursor.col,
-            fg_color, bg_color);
+            tem->tvs_s_cursor.row, tem->tvs_s_cursor.col);
 
         if (tem->tvs_isactive) {
                 /*
                  * Call the primitive to render this data.
                  */
                 tem_safe_callback_display(tem,
                     tem->tvs_outbuf, tem->tvs_outindex,
                     tem->tvs_s_cursor.row, tem->tvs_s_cursor.col,
-                    fg_color, bg_color,
                     credp, called_from);
         }
 
         tem->tvs_outindex = 0;
 

@@ -1104,20 +1179,20 @@
  * State machine parser based on the current state and character input
  * major terminations are to control character or normal character
  */
 
 static void
-tem_safe_parse(struct tem_vt_state *tem, uchar_t ch,
+tem_safe_parse(struct tem_vt_state *tem, tem_char_t ch,
     cred_t *credp, enum called_from called_from)
 {
         int     i;
 
         ASSERT((called_from == CALLED_FROM_STANDALONE) ||
             MUTEX_HELD(&tem->tvs_lock));
 
         if (tem->tvs_state == A_STATE_START) {  /* Normal state? */
-                if (ch == A_CSI || ch == A_ESC || ch < ' ') {
+                if (ch == A_CSI || ch == A_OSC || ch == A_ESC || ch < ' ') {
                         /* Control */
                         tem_safe_control(tem, ch, credp, called_from);
                 } else {
                         /* Display */
                         tem_safe_outch(tem, ch, credp, called_from);

@@ -1125,10 +1200,15 @@
                 return;
         }
 
         /* In <ESC> sequence */
         if (tem->tvs_state != A_STATE_ESC) {    /* Need to get parameters? */
+                if (tem->tvs_state == A_STATE_OSC) {
+                        tem_safe_get_oscstring(tem, ch, credp, called_from);
+                        return;
+                }
+
                 if (tem->tvs_state != A_STATE_CSI) {
                         tem_safe_getparams(tem, ch, credp, called_from);
                         return;
                 }
 

@@ -1235,10 +1315,18 @@
                 tem->tvs_gotparam = B_FALSE;
                 /* clear the parameters */
                 for (i = 0; i < TEM_MAXPARAMS; i++)
                         tem->tvs_params[i] = -1;
                 tem->tvs_state = A_STATE_CSI;
+        } else if (ch == ']') {
+                tem->tvs_curparam = 0;
+                tem->tvs_paramval = 0;
+                tem->tvs_gotparam = B_FALSE;
+                /* clear the parameters */
+                for (i = 0; i < TEM_MAXPARAMS; i++)
+                        tem->tvs_params[i] = -1;
+                tem->tvs_state = A_STATE_OSC;
         } else if (ch == 'Q') { /* <ESC>Q ? */
                 tem->tvs_state = A_STATE_START;
         } else if (ch == 'C') { /* <ESC>C ? */
                 tem->tvs_state = A_STATE_START;
         } else {

@@ -1395,29 +1483,32 @@
         tem_safe_callback_cls(tem, count, row, col, credp, called_from);
 }
 
 /*ARGSUSED*/
 void
-tem_safe_text_display(struct tem_vt_state *tem, uchar_t *string,
+tem_safe_text_display(struct tem_vt_state *tem, term_char_t *string,
     int count, screen_pos_t row, screen_pos_t col,
-    text_color_t fg_color, text_color_t bg_color,
     cred_t *credp, enum called_from called_from)
 {
         struct vis_consdisplay da;
+        int i;
+        tem_char_t c;
 
         ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
             called_from == CALLED_FROM_STANDALONE);
 
-        da.data = string;
-        da.width = (screen_size_t)count;
+        da.data = (uint8_t *)&c;
+        da.width = 1;
         da.row = row;
         da.col = col;
 
-        da.fg_color = fg_color;
-        da.bg_color = bg_color;
-
+        for (i = 0; i < count; i++) {
+                tem_safe_get_color(&da.fg_color, &da.bg_color, string[i]);
+                c = TEM_CHAR(string[i].tc_char);
         tems_safe_display(&da, credp, called_from);
+                da.col++;
+        }
 }
 
 /*
  * This function is used to blit a rectangular color image,
  * unperturbed on the underlying framebuffer, to render

@@ -1449,11 +1540,10 @@
 
         mutex_exit(&tem->tvs_lock);
         mutex_exit(&tems.ts_lock);
 }
 
-
 /*ARGSUSED*/
 void
 tem_safe_text_copy(struct tem_vt_state *tem,
     screen_pos_t s_col, screen_pos_t s_row,
     screen_pos_t e_col, screen_pos_t e_row,

@@ -1478,46 +1568,52 @@
 void
 tem_safe_text_cls(struct tem_vt_state *tem,
     int count, screen_pos_t row, screen_pos_t col, cred_t *credp,
     enum called_from called_from)
 {
-        struct vis_consdisplay da;
+        text_attr_t attr;
+        term_char_t c;
+        int i;
 
         ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
             called_from == CALLED_FROM_STANDALONE);
 
-        da.data = tems.ts_blank_line;
-        da.width = (screen_size_t)count;
-        da.row = row;
-        da.col = col;
-
-        tem_safe_get_color(tem, &da.fg_color, &da.bg_color,
+        tem_safe_get_attr(tem, &c.tc_fg_color, &c.tc_bg_color, &attr,
             TEM_ATTR_SCREEN_REVERSE);
-        tems_safe_display(&da, credp, called_from);
+        c.tc_char = TEM_ATTR(attr & ~TEM_ATTR_UNDERLINE) | ' ';
+
+        if (count > tems.ts_c_dimension.width ||
+            col + count > tems.ts_c_dimension.width)
+                count = tems.ts_c_dimension.width - col;
+
+        for (i = 0; i < count; i++)
+                tems.ts_blank_line[i] = c;
+
+        tem_safe_text_display(tem, tems.ts_blank_line, count, row, col,
+                credp, called_from);
 }
 
 void
 tem_safe_pix_display(struct tem_vt_state *tem,
-    uchar_t *string, int count,
+    term_char_t *string, int count,
     screen_pos_t row, screen_pos_t col,
-    text_color_t fg_color, text_color_t bg_color,
     cred_t *credp, enum called_from called_from)
 {
         struct vis_consdisplay da;
         int     i;
 
         ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
             called_from == CALLED_FROM_STANDALONE);
 
         da.data = (uchar_t *)tem->tvs_pix_data;
-        da.width = tems.ts_font.width;
-        da.height = tems.ts_font.height;
+        da.width = (screen_size_t)tems.ts_font.vf_width;
+        da.height = (screen_size_t)tems.ts_font.vf_height;
         da.row = (row * da.height) + tems.ts_p_offset.y;
         da.col = (col * da.width) + tems.ts_p_offset.x;
 
         for (i = 0; i < count; i++) {
-                tem_safe_callback_bit2pix(tem, string[i], fg_color, bg_color);
+                tem_safe_callback_bit2pix(tem, string[i]);
                 tems_safe_display(&da, credp, called_from);
                 da.col += da.width;
         }
 }
 

@@ -1546,13 +1642,14 @@
                  */
                 tem_safe_pix_clear_prom_output(tem, credp, called_from);
         }
         need_clear = B_FALSE;
 
-        ma.s_row = s_row * tems.ts_font.height + tems.ts_p_offset.y;
-        ma.e_row = (e_row + 1) * tems.ts_font.height + tems.ts_p_offset.y - 1;
-        ma.t_row = t_row * tems.ts_font.height + tems.ts_p_offset.y;
+        ma.s_row = s_row * tems.ts_font.vf_height + tems.ts_p_offset.y;
+        ma.e_row = (e_row + 1) * tems.ts_font.vf_height +
+            tems.ts_p_offset.y - 1;
+        ma.t_row = t_row * tems.ts_font.vf_height + tems.ts_p_offset.y;
 
         /*
          * Check if we're in process of clearing OBP's columns area,
          * which only happens when term scrolls up a whole line.
          */

@@ -1560,19 +1657,19 @@
             e_col == tems.ts_c_dimension.width - 1) {
                 /*
                  * We need to clear OBP's columns area outside our kernel
                  * console term. So that we set ma.e_col to entire row here.
                  */
-                ma.s_col = s_col * tems.ts_font.width;
+                ma.s_col = s_col * tems.ts_font.vf_width;
                 ma.e_col = tems.ts_p_dimension.width - 1;
 
-                ma.t_col = t_col * tems.ts_font.width;
+                ma.t_col = t_col * tems.ts_font.vf_width;
         } else {
-                ma.s_col = s_col * tems.ts_font.width + tems.ts_p_offset.x;
-                ma.e_col = (e_col + 1) * tems.ts_font.width +
+                ma.s_col = s_col * tems.ts_font.vf_width + tems.ts_p_offset.x;
+                ma.e_col = (e_col + 1) * tems.ts_font.vf_width +
                     tems.ts_p_offset.x - 1;
-                ma.t_col = t_col * tems.ts_font.width + tems.ts_p_offset.x;
+                ma.t_col = t_col * tems.ts_font.vf_width + tems.ts_p_offset.x;
         }
 
         tems_safe_copy(&ma, credp, called_from);
 
         if (tem->tvs_first_line > 0 && t_row < s_row) {

@@ -1585,29 +1682,39 @@
         }
 
 }
 
 void
-tem_safe_pix_bit2pix(struct tem_vt_state *tem, unsigned char c,
-    unsigned char fg, unsigned char bg)
+tem_safe_pix_bit2pix(struct tem_vt_state *tem, term_char_t c)
 {
-        void (*fp)(struct tem_vt_state *, unsigned char,
+        text_color_t fg, bg;
+        void (*fp)(struct tem_vt_state *, tem_char_t,
             unsigned char, unsigned char);
 
+        tem_safe_get_color(&fg, &bg, c);
         switch (tems.ts_pdepth) {
         case 4:
                 fp = bit_to_pix4;
                 break;
         case 8:
                 fp = bit_to_pix8;
                 break;
+        case 15:
+        case 16:
+                fp = bit_to_pix16;
+                break;
         case 24:
-        case 32:
                 fp = bit_to_pix24;
+                break;
+        case 32:
+                fp = bit_to_pix32;
+                break;
+        default:
+                return;
         }
 
-        fp(tem, c, fg, bg);
+        fp(tem, c.tc_char, fg, bg);
 }
 
 
 /*
  * This function only clears count of columns in one row

@@ -1649,22 +1756,24 @@
  */
 static void
 tem_safe_pix_clear_prom_output(struct tem_vt_state *tem, cred_t *credp,
     enum called_from called_from)
 {
-        int     nrows, ncols, width, height;
+        int     nrows, ncols, width, height, offset;
 
         ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
             called_from == CALLED_FROM_STANDALONE);
 
-        width = tems.ts_font.width;
-        height = tems.ts_font.height;
+        width = tems.ts_font.vf_width;
+        height = tems.ts_font.vf_height;
+        offset = tems.ts_p_offset.y % height;
 
-        nrows = (tems.ts_p_offset.y + (height - 1))/ height;
+        nrows = tems.ts_p_offset.y / height;
         ncols = (tems.ts_p_dimension.width + (width - 1))/ width;
 
-        tem_safe_pix_cls_range(tem, 0, nrows, 0, 0, ncols, 0,
+        if (nrows > 0)
+                tem_safe_pix_cls_range(tem, 0, nrows, offset, 0, ncols, 0,
             B_FALSE, credp, called_from);
 }
 
 /*
  * clear the whole screen for pixel mode, just clear the

@@ -1672,23 +1781,38 @@
  */
 void
 tem_safe_pix_clear_entire_screen(struct tem_vt_state *tem, cred_t *credp,
     enum called_from called_from)
 {
+        struct vis_consclear cl;
+        text_color_t fg_color;
+        text_color_t bg_color;
+        text_attr_t attr;
+        term_char_t c;
         int     nrows, ncols, width, height;
 
         ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
             called_from == CALLED_FROM_STANDALONE);
 
-        width = tems.ts_font.width;
-        height = tems.ts_font.height;
+        /* call driver first, if error, clear terminal area */
+        tem_safe_get_attr(tem, &c.tc_fg_color, &c.tc_bg_color, &attr,
+            TEM_ATTR_SCREEN_REVERSE);
+        c.tc_char = TEM_ATTR(attr);
 
+        tem_safe_get_color(&fg_color, &bg_color, c);
+        cl.bg_color = bg_color;
+        if (tems_cls_layered(&cl, credp) == 0)
+                return;
+
+        width = tems.ts_font.vf_width;
+        height = tems.ts_font.vf_height;
+
         nrows = (tems.ts_p_dimension.height + (height - 1))/ height;
         ncols = (tems.ts_p_dimension.width + (width - 1))/ width;
 
-        tem_safe_pix_cls_range(tem, 0, nrows, 0, 0, ncols, 0,
-            B_FALSE, credp, called_from);
+        tem_safe_pix_cls_range(tem, 0, nrows, tems.ts_p_offset.y, 0, ncols,
+            tems.ts_p_offset.x, B_FALSE, credp, called_from);
 
         /*
          * Since the whole screen is cleared, we don't need
          * to clear OBP output later.
          */

@@ -2002,30 +2126,54 @@
 void
 tem_safe_pix_cursor(struct tem_vt_state *tem, short action,
     cred_t *credp, enum called_from called_from)
 {
         struct vis_conscursor   ca;
+        uint32_t color;
+        text_color_t fg, bg;
+        term_char_t c;
+        text_attr_t attr;
 
         ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
             called_from == CALLED_FROM_STANDALONE);
 
-        ca.row = tem->tvs_c_cursor.row * tems.ts_font.height +
+        ca.row = tem->tvs_c_cursor.row * tems.ts_font.vf_height +
             tems.ts_p_offset.y;
-        ca.col = tem->tvs_c_cursor.col * tems.ts_font.width +
+        ca.col = tem->tvs_c_cursor.col * tems.ts_font.vf_width +
             tems.ts_p_offset.x;
-        ca.width = tems.ts_font.width;
-        ca.height = tems.ts_font.height;
-        if (tems.ts_pdepth == 8 || tems.ts_pdepth == 4) {
+        ca.width = (screen_size_t)tems.ts_font.vf_width;
+        ca.height = (screen_size_t)tems.ts_font.vf_height;
+
+        tem_safe_get_attr(tem, &c.tc_fg_color, &c.tc_bg_color, &attr,
+            TEM_ATTR_REVERSE);
+        c.tc_char = TEM_ATTR(attr);
+
+        tem_safe_get_color(&fg, &bg, c);
+
+        switch (tems.ts_pdepth) {
+        case 4:
+                ca.fg_color.mono = fg;
+                ca.bg_color.mono = bg;
+                break;
+        case 8:
+                ca.fg_color.mono = tems.ts_color_map(fg);
+                ca.bg_color.mono = tems.ts_color_map(bg);
+                break;
+        case 15:
+        case 16:
+                color = tems.ts_color_map(fg);
+                ca.fg_color.sixteen[0] = (color >> 8) & 0xFF;
+                ca.fg_color.sixteen[1] = color & 0xFF;
+                color = tems.ts_color_map(bg);
+                ca.bg_color.sixteen[0] = (color >> 8) & 0xFF;
+                ca.bg_color.sixteen[1] = color & 0xFF;
+                break;
+        case 24:
+        case 32:
+#ifdef _HAVE_TEM_FIRMWARE
+                /* Keeping this block to support old binary only drivers */
                 if (tem->tvs_flags & TEM_ATTR_REVERSE) {
-                        ca.fg_color.mono = TEM_TEXT_WHITE;
-                        ca.bg_color.mono = TEM_TEXT_BLACK;
-                } else {
-                        ca.fg_color.mono = TEM_TEXT_BLACK;
-                        ca.bg_color.mono = TEM_TEXT_WHITE;
-                }
-        } else if (tems.ts_pdepth == 24 || tems.ts_pdepth == 32) {
-                if (tem->tvs_flags & TEM_ATTR_REVERSE) {
                         ca.fg_color.twentyfour[0] = TEM_TEXT_WHITE24_RED;
                         ca.fg_color.twentyfour[1] = TEM_TEXT_WHITE24_GREEN;
                         ca.fg_color.twentyfour[2] = TEM_TEXT_WHITE24_BLUE;
 
                         ca.bg_color.twentyfour[0] = TEM_TEXT_BLACK24_RED;

@@ -2038,88 +2186,153 @@
 
                         ca.bg_color.twentyfour[0] = TEM_TEXT_WHITE24_RED;
                         ca.bg_color.twentyfour[1] = TEM_TEXT_WHITE24_GREEN;
                         ca.bg_color.twentyfour[2] = TEM_TEXT_WHITE24_BLUE;
                 }
+#else
+                color = tems.ts_color_map(fg);
+                ca.fg_color.twentyfour[0] = (color >> 16) & 0xFF;
+                ca.fg_color.twentyfour[1] = (color >> 8) & 0xFF;
+                ca.fg_color.twentyfour[2] = color & 0xFF;
+                color = tems.ts_color_map(bg);
+                ca.bg_color.twentyfour[0] = (color >> 16) & 0xFF;
+                ca.bg_color.twentyfour[1] = (color >> 8) & 0xFF;
+                ca.bg_color.twentyfour[2] = color & 0xFF;
+                break;
+#endif
         }
 
         ca.action = action;
 
         tems_safe_cursor(&ca, credp, called_from);
+
+        if (action == VIS_GET_CURSOR) {
+                tem->tvs_c_cursor.row = 0;
+                tem->tvs_c_cursor.col = 0;
+
+                if (ca.row != 0) {
+                        tem->tvs_c_cursor.row = (ca.row - tems.ts_p_offset.y) /
+                            tems.ts_font.vf_height;
+                }
+                if (ca.col != 0) {
+                        tem->tvs_c_cursor.col = (ca.col - tems.ts_p_offset.x) /
+                            tems.ts_font.vf_width;
+                }
+        }
 }
 
 static void
-bit_to_pix4(struct tem_vt_state *tem, uchar_t c, text_color_t fg_color,
+bit_to_pix4(struct tem_vt_state *tem, tem_char_t c, text_color_t fg_color,
     text_color_t bg_color)
 {
         uint8_t *dest = (uint8_t *)tem->tvs_pix_data;
         font_bit_to_pix4(&tems.ts_font, dest, c, fg_color, bg_color);
 }
 
 static void
-bit_to_pix8(struct tem_vt_state *tem, uchar_t c, text_color_t fg_color,
+bit_to_pix8(struct tem_vt_state *tem, tem_char_t c, text_color_t fg_color,
     text_color_t bg_color)
 {
         uint8_t *dest = (uint8_t *)tem->tvs_pix_data;
+
+        fg_color = (text_color_t)tems.ts_color_map(fg_color);
+        bg_color = (text_color_t)tems.ts_color_map(bg_color);
         font_bit_to_pix8(&tems.ts_font, dest, c, fg_color, bg_color);
 }
 
 static void
-bit_to_pix24(struct tem_vt_state *tem, uchar_t c, text_color_t fg_color4,
+bit_to_pix16(struct tem_vt_state *tem, tem_char_t c, text_color_t fg_color4,
     text_color_t bg_color4)
 {
-        uint32_t fg_color32, bg_color32, *dest;
+        uint16_t fg_color16, bg_color16;
+        uint16_t *dest;
 
         ASSERT(fg_color4 < 16 && bg_color4 < 16);
 
+        fg_color16 = (uint16_t)tems.ts_color_map(fg_color4);
+        bg_color16 = (uint16_t)tems.ts_color_map(bg_color4);
+
+        dest = (uint16_t *)tem->tvs_pix_data;
+        font_bit_to_pix16(&tems.ts_font, dest, c, fg_color16, bg_color16);
+}
+
+static void
+bit_to_pix24(struct tem_vt_state *tem, tem_char_t c, text_color_t fg_color4,
+    text_color_t bg_color4)
+{
+        uint32_t fg_color32, bg_color32;
+        uint8_t *dest;
+
+        ASSERT(fg_color4 < 16 && bg_color4 < 16);
+
+#ifdef _HAVE_TEM_FIRMWARE
         fg_color32 = PIX4TO32(fg_color4);
         bg_color32 = PIX4TO32(bg_color4);
+#else
+        fg_color32 = tems.ts_color_map(fg_color4);
+        bg_color32 = tems.ts_color_map(bg_color4);
+#endif
 
-        dest = (uint32_t *)tem->tvs_pix_data;
+        dest = (uint8_t *)tem->tvs_pix_data;
         font_bit_to_pix24(&tems.ts_font, dest, c, fg_color32, bg_color32);
 }
 
-static text_color_t
-ansi_bg_to_solaris(struct tem_vt_state *tem, int ansi)
+static void
+bit_to_pix32(struct tem_vt_state *tem, tem_char_t c, text_color_t fg_color4,
+    text_color_t bg_color4)
 {
-        if (tem->tvs_flags & TEM_ATTR_BRIGHT_BG)
-                return (brt_xlate[ansi]);
-        else
-                return (dim_xlate[ansi]);
-}
+        uint32_t fg_color32, bg_color32, *dest;
 
-static text_color_t
-ansi_fg_to_solaris(struct tem_vt_state *tem, int ansi)
-{
-        if (tem->tvs_flags & TEM_ATTR_BRIGHT_FG ||
-            tem->tvs_flags & TEM_ATTR_BOLD) {
-                return (brt_xlate[ansi]);
-        } else {
-                return (dim_xlate[ansi]);
-        }
+        ASSERT(fg_color4 < 16 && bg_color4 < 16);
+
+#ifdef _HAVE_TEM_FIRMWARE
+        fg_color32 = PIX4TO32(fg_color4);
+        bg_color32 = PIX4TO32(bg_color4);
+#else
+        fg_color32 = ((uint32_t)0xFF << 24) | tems.ts_color_map(fg_color4);
+        bg_color32 = ((uint32_t)0xFF << 24) | tems.ts_color_map(bg_color4);
+#endif
+
+        dest = (uint32_t *)tem->tvs_pix_data;
+        font_bit_to_pix32(&tems.ts_font, dest, c, fg_color32, bg_color32);
 }
 
 /*
  * flag: TEM_ATTR_SCREEN_REVERSE or TEM_ATTR_REVERSE
  */
 void
-tem_safe_get_color(struct tem_vt_state *tem, text_color_t *fg,
-    text_color_t *bg, uint8_t flag)
+tem_safe_get_attr(struct tem_vt_state *tem, text_color_t *fg,
+    text_color_t *bg, text_attr_t *attr, uint8_t flag)
 {
         if (tem->tvs_flags & flag) {
-                *fg = ansi_fg_to_solaris(tem,
-                    tem->tvs_bg_color);
-                *bg = ansi_bg_to_solaris(tem,
-                    tem->tvs_fg_color);
+                *fg = tem->tvs_bg_color;
+                *bg = tem->tvs_fg_color;
         } else {
-                *fg = ansi_fg_to_solaris(tem,
-                    tem->tvs_fg_color);
-                *bg = ansi_bg_to_solaris(tem,
-                    tem->tvs_bg_color);
+                *fg = tem->tvs_fg_color;
+                *bg = tem->tvs_bg_color;
         }
+
+        if (attr == NULL)
+                return;
+
+        *attr = tem->tvs_flags;
 }
 
+static void
+tem_safe_get_color(text_color_t *fg, text_color_t *bg, term_char_t c)
+{
+        if (TEM_CHAR_ATTR(c.tc_char) & (TEM_ATTR_BRIGHT_FG | TEM_ATTR_BOLD))
+                *fg = brt_xlate[c.tc_fg_color];
+        else
+                *fg = dim_xlate[c.tc_fg_color];
+
+        if (TEM_CHAR_ATTR(c.tc_char) & TEM_ATTR_BRIGHT_BG)
+                *bg = brt_xlate[c.tc_bg_color];
+        else
+                *bg = dim_xlate[c.tc_bg_color];
+}
+
 /*
  * Clear a rectangle of screen for pixel mode.
  *
  * arguments:
  *    row:      start row#

@@ -2139,25 +2352,28 @@
     enum called_from called_from)
 {
         struct vis_consdisplay da;
         int     i, j;
         int     row_add = 0;
-        text_color_t fg_color;
-        text_color_t bg_color;
+        term_char_t c;
+        text_attr_t attr;
 
         ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
             called_from == CALLED_FROM_STANDALONE);
 
         if (sroll_up)
                 row_add = tems.ts_c_dimension.height - 1;
 
-        da.width = tems.ts_font.width;
-        da.height = tems.ts_font.height;
+        da.width = (screen_size_t)tems.ts_font.vf_width;
+        da.height = (screen_size_t)tems.ts_font.vf_height;
 
-        tem_safe_get_color(tem, &fg_color, &bg_color, TEM_ATTR_SCREEN_REVERSE);
+        tem_safe_get_attr(tem, &c.tc_fg_color, &c.tc_bg_color, &attr,
+            TEM_ATTR_SCREEN_REVERSE);
+        /* Make sure we will not draw underlines */
+        c.tc_char = TEM_ATTR(attr & ~TEM_ATTR_UNDERLINE) | ' ';
 
-        tem_safe_callback_bit2pix(tem, ' ', fg_color, bg_color);
+        tem_safe_callback_bit2pix(tem, c);
         da.data = (uchar_t *)tem->tvs_pix_data;
 
         for (i = 0; i < nrows; i++, row++) {
                 da.row = (row + row_add) * da.height + offset_y;
                 da.col = col * da.width + offset_x;

@@ -2170,47 +2386,40 @@
 
 /*
  * virtual screen operations
  */
 static void
-tem_safe_virtual_display(struct tem_vt_state *tem, unsigned char *string,
-    int count, screen_pos_t row, screen_pos_t col,
-    text_color_t fg_color, text_color_t bg_color)
+tem_safe_virtual_display(struct tem_vt_state *tem, term_char_t *string,
+    int count, screen_pos_t row, screen_pos_t col)
 {
         int i, width;
-        unsigned char *addr;
-        text_color_t *pfgcolor;
-        text_color_t *pbgcolor;
+        term_char_t *addr;
 
         if (row < 0 || row >= tems.ts_c_dimension.height ||
             col < 0 || col >= tems.ts_c_dimension.width ||
             col + count > tems.ts_c_dimension.width)
                 return;
 
         width = tems.ts_c_dimension.width;
         addr = tem->tvs_screen_buf +  (row * width + col);
-        pfgcolor = tem->tvs_fg_buf + (row * width + col);
-        pbgcolor = tem->tvs_bg_buf + (row * width + col);
         for (i = 0; i < count; i++) {
                 *addr++ = string[i];
-                *pfgcolor++ = fg_color;
-                *pbgcolor++ = bg_color;
         }
 }
 
 static void
-i_virtual_copy(unsigned char *base,
+i_virtual_copy_tem_chars(term_char_t *base,
     screen_pos_t s_col, screen_pos_t s_row,
     screen_pos_t e_col, screen_pos_t e_row,
     screen_pos_t t_col, screen_pos_t t_row)
 {
-        unsigned char   *from;
-        unsigned char   *to;
+        term_char_t     *from;
+        term_char_t     *to;
         int             cnt;
         screen_size_t chars_per_row;
-        unsigned char   *to_row_start;
-        unsigned char   *from_row_start;
+        term_char_t     *to_row_start;
+        term_char_t     *from_row_start;
         screen_size_t   rows_to_move;
         int             cols = tems.ts_c_dimension.width;
 
         chars_per_row = e_col - s_col + 1;
         rows_to_move = e_row - s_row + 1;

@@ -2273,31 +2482,30 @@
         /* More sanity checks. */
         if (t_row + rows_to_move > rows ||
             t_col + chars_per_row > cols)
                 return;
 
-        i_virtual_copy(tem->tvs_screen_buf, s_col, s_row,
+        i_virtual_copy_tem_chars(tem->tvs_screen_buf, s_col, s_row,
             e_col, e_row, t_col, t_row);
-
-        /* text_color_t is the same size as char */
-        i_virtual_copy((unsigned char *)tem->tvs_fg_buf,
-            s_col, s_row, e_col, e_row, t_col, t_row);
-        i_virtual_copy((unsigned char *)tem->tvs_bg_buf,
-            s_col, s_row, e_col, e_row, t_col, t_row);
-
 }
 
 static void
 tem_safe_virtual_cls(struct tem_vt_state *tem,
     int count, screen_pos_t row, screen_pos_t col)
 {
-        text_color_t fg_color;
-        text_color_t bg_color;
+        int i;
+        text_attr_t attr;
+        term_char_t c;
 
-        tem_safe_get_color(tem, &fg_color, &bg_color, TEM_ATTR_SCREEN_REVERSE);
-        tem_safe_virtual_display(tem, tems.ts_blank_line, count, row, col,
-            fg_color, bg_color);
+        tem_safe_get_attr(tem, &c.tc_fg_color, &c.tc_bg_color, &attr,
+            TEM_ATTR_SCREEN_REVERSE);
+        c.tc_char = TEM_ATTR(attr & ~TEM_ATTR_UNDERLINE) | ' ';
+
+        for (i = 0; i < tems.ts_c_dimension.width; i++)
+                tems.ts_blank_line[i] = c;
+
+        tem_safe_virtual_display(tem, tems.ts_blank_line, count, row, col);
 }
 
 /*
  * only blank screen, not clear our screen buffer
  */

@@ -2327,71 +2535,28 @@
  */
 void
 tem_safe_unblank_screen(struct tem_vt_state *tem, cred_t *credp,
     enum called_from called_from)
 {
-        text_color_t fg_color, fg_last;
-        text_color_t bg_color, bg_last;
-        size_t  tc_size = sizeof (text_color_t);
-        int     row, col, count, col_start;
-        int     width;
-        unsigned char *buf;
+        int     row;
 
         ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
             called_from == CALLED_FROM_STANDALONE);
 
         if (tems.ts_display_mode == VIS_PIXEL)
                 tem_safe_pix_clear_entire_screen(tem, credp, called_from);
 
         tem_safe_callback_cursor(tem, VIS_HIDE_CURSOR, credp, called_from);
 
-        width = tems.ts_c_dimension.width;
-
         /*
          * Display data in tvs_screen_buf to the actual framebuffer in a
          * row by row way.
          * When dealing with one row, output data with the same foreground
          * and background color all together.
          */
         for (row = 0; row < tems.ts_c_dimension.height; row++) {
-                buf = tem->tvs_screen_buf + (row * width);
-                count = col_start = 0;
-                for (col = 0; col < width; col++) {
-                        fg_color =
-                            tem->tvs_fg_buf[(row * width + col) * tc_size];
-                        bg_color =
-                            tem->tvs_bg_buf[(row * width + col) * tc_size];
-                        if (col == 0) {
-                                fg_last = fg_color;
-                                bg_last = bg_color;
+                tem_safe_callback_display(tem, tem->tvs_screen_rows[row],
+                    tems.ts_c_dimension.width, row, 0, credp, called_from);
                         }
 
-                        if ((fg_color != fg_last) || (bg_color != bg_last)) {
-                                /*
-                                 * Call the primitive to render this data.
-                                 */
-                                tem_safe_callback_display(tem,
-                                    buf, count, row, col_start,
-                                    fg_last, bg_last, credp, called_from);
-                                buf += count;
-                                count = 1;
-                                col_start = col;
-                                fg_last = fg_color;
-                                bg_last = bg_color;
-                        } else {
-                                count++;
-                        }
-                }
-
-                if (col_start == (width - 1))
-                        continue;
-
-                /*
-                 * Call the primitive to render this data.
-                 */
-                tem_safe_callback_display(tem,
-                    buf, count, row, col_start,
-                    fg_last, bg_last, credp, called_from);
-        }
-
         tem_safe_callback_cursor(tem, VIS_DISPLAY_CURSOR, credp, called_from);
 }