--- old/usr/src/uts/common/io/tem.c	Mon Aug  5 17:32:06 2019
+++ new/usr/src/uts/common/io/tem.c	Mon Aug  5 17:32:06 2019
@@ -121,7 +121,7 @@
 };
 
 static struct modlinkage modlinkage = {
-	MODREV_1, (void *)&modlmisc, NULL
+	MODREV_1, { (void *)&modlmisc, NULL }
 };
 
 int
@@ -209,12 +209,10 @@
 tem_internal_init(struct tem_vt_state *ptem, cred_t *credp,
     boolean_t init_color, boolean_t clear_screen)
 {
-	int i, j;
-	int width, height;
-	int total;
+	unsigned i, j, width, height;
+	text_attr_t attr;
 	text_color_t fg;
 	text_color_t bg;
-	size_t	tc_size = sizeof (text_color_t);
 
 	ASSERT(MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&ptem->tvs_lock));
 
@@ -224,20 +222,19 @@
 		    kmem_alloc(ptem->tvs_pix_data_size, KM_SLEEP);
 	}
 
-	ptem->tvs_outbuf_size = tems.ts_c_dimension.width;
-	ptem->tvs_outbuf =
-	    (unsigned char *)kmem_alloc(ptem->tvs_outbuf_size, KM_SLEEP);
+	ptem->tvs_outbuf_size = tems.ts_c_dimension.width *
+	    sizeof (*ptem->tvs_outbuf);
+	ptem->tvs_outbuf = kmem_alloc(ptem->tvs_outbuf_size, KM_SLEEP);
 
 	width = tems.ts_c_dimension.width;
 	height = tems.ts_c_dimension.height;
-	ptem->tvs_screen_buf_size = width * height;
-	ptem->tvs_screen_buf =
-	    (unsigned char *)kmem_alloc(width * height, KM_SLEEP);
+	ptem->tvs_screen_history_size = height;
 
-	total = width * height * tc_size;
-	ptem->tvs_fg_buf = (text_color_t *)kmem_alloc(total, KM_SLEEP);
-	ptem->tvs_bg_buf = (text_color_t *)kmem_alloc(total, KM_SLEEP);
-	ptem->tvs_color_buf_size = total;
+	ptem->tvs_screen_buf_size = width * ptem->tvs_screen_history_size *
+	    sizeof (*ptem->tvs_screen_buf);
+	ptem->tvs_screen_buf = kmem_alloc(ptem->tvs_screen_buf_size, KM_SLEEP);
+	ptem->tvs_screen_rows = kmem_alloc(ptem->tvs_screen_history_size *
+	    sizeof (term_char_t *), KM_SLEEP);
 
 	tem_safe_reset_display(ptem, credp, CALLED_FROM_NORMAL,
 	    clear_screen, init_color);
@@ -245,16 +242,21 @@
 	ptem->tvs_utf8_left = 0;
 	ptem->tvs_utf8_partial = 0;
 
-	tem_safe_get_color(ptem, &fg, &bg, TEM_ATTR_SCREEN_REVERSE);
-	for (i = 0; i < height; i++)
+	/* Get default attributes and fill up the screen buffer. */
+	tem_safe_get_attr(ptem, &fg, &bg, &attr, TEM_ATTR_SCREEN_REVERSE);
+	for (i = 0; i < ptem->tvs_screen_history_size; i++) {
+		ptem->tvs_screen_rows[i] = &ptem->tvs_screen_buf[i * width];
+
 		for (j = 0; j < width; j++) {
-			ptem->tvs_screen_buf[i * width + j] = ' ';
-			ptem->tvs_fg_buf[(i * width +j) * tc_size] = fg;
-			ptem->tvs_bg_buf[(i * width +j) * tc_size] = bg;
+			ptem->tvs_screen_rows[i][j].tc_fg_color = fg;
+			ptem->tvs_screen_rows[i][j].tc_bg_color = bg;
+			ptem->tvs_screen_rows[i][j].tc_char =
+			    TEM_ATTR(attr) | ' ';
 
 		}
+	}
 
-	ptem->tvs_initialized  = 1;
+	ptem->tvs_initialized = B_TRUE;
 }
 
 int
@@ -264,7 +266,7 @@
 	int ret;
 
 	mutex_enter(&ptem->tvs_lock);
-	ret = ptem->tvs_initialized;
+	ret = ptem->tvs_initialized == B_TRUE? 1 : 0;
 	mutex_exit(&ptem->tvs_lock);
 
 	return (ret);
@@ -288,7 +290,7 @@
 	 * A tem is regarded as initialized only after tem_internal_init(),
 	 * will be set at the end of tem_internal_init().
 	 */
-	ptem->tvs_initialized = 0;
+	ptem->tvs_initialized = B_FALSE;
 
 
 	if (!tems.ts_initialized) {
@@ -335,10 +337,10 @@
 		kmem_free(tem->tvs_pix_data, tem->tvs_pix_data_size);
 	if (tem->tvs_screen_buf != NULL)
 		kmem_free(tem->tvs_screen_buf, tem->tvs_screen_buf_size);
-	if (tem->tvs_fg_buf != NULL)
-		kmem_free(tem->tvs_fg_buf, tem->tvs_color_buf_size);
-	if (tem->tvs_bg_buf != NULL)
-		kmem_free(tem->tvs_bg_buf, tem->tvs_color_buf_size);
+	if (tem->tvs_screen_rows != NULL) {
+		kmem_free(tem->tvs_screen_rows, tem->tvs_screen_history_size *
+		    sizeof (term_char_t *));
+	}
 }
 
 void
@@ -458,6 +460,7 @@
 
 	/* other sanity checks */
 	if (!((temargs.depth == 4) || (temargs.depth == 8) ||
+	    (temargs.depth == 15) || (temargs.depth == 16) ||
 	    (temargs.depth == 24) || (temargs.depth == 32))) {
 		cmn_err(CE_WARN, "terminal emulator: unsupported depth");
 		ret = tems_failed(credp, B_TRUE);
@@ -525,8 +528,10 @@
 static void
 tems_setup_terminal(struct vis_devinit *tp, size_t height, size_t width)
 {
+	bitmap_data_t *font_data;
 	int i;
-	int old_blank_buf_size = tems.ts_c_dimension.width;
+	int old_blank_buf_size = tems.ts_c_dimension.width *
+	    sizeof (*tems.ts_blank_line);
 
 	ASSERT(MUTEX_HELD(&tems.ts_lock));
 
@@ -533,6 +538,7 @@
 	tems.ts_pdepth = tp->depth;
 	tems.ts_linebytes = tp->linebytes;
 	tems.ts_display_mode = tp->mode;
+	tems.ts_color_map = tp->color_map;
 
 	switch (tp->mode) {
 	case VIS_TEXT:
@@ -568,19 +574,28 @@
 		 * default builtin font and adjust the rows and columns
 		 * to fit on the screen.
 		 */
-		set_font(&tems.ts_font,
-		    &tems.ts_c_dimension.height,
+		font_data = set_font(&tems.ts_c_dimension.height,
 		    &tems.ts_c_dimension.width,
 		    tems.ts_p_dimension.height,
 		    tems.ts_p_dimension.width);
 
+		for (i = 0; i < VFNT_MAPS; i++) {
+			tems.ts_font.vf_map[i] =
+			    font_data->font->vf_map[i];
+			tems.ts_font.vf_map_count[i] =
+			    font_data->font->vf_map_count[i];
+		}
+		tems.ts_font.vf_bytes = font_data->font->vf_bytes;
+		tems.ts_font.vf_width = font_data->font->vf_width;
+		tems.ts_font.vf_height = font_data->font->vf_height;
+
 		tems.ts_p_offset.y = (tems.ts_p_dimension.height -
-		    (tems.ts_c_dimension.height * tems.ts_font.height)) / 2;
+		    (tems.ts_c_dimension.height * tems.ts_font.vf_height)) / 2;
 		tems.ts_p_offset.x = (tems.ts_p_dimension.width -
-		    (tems.ts_c_dimension.width * tems.ts_font.width)) / 2;
+		    (tems.ts_c_dimension.width * tems.ts_font.vf_width)) / 2;
 
 		tems.ts_pix_data_size =
-		    tems.ts_font.width * tems.ts_font.height;
+		    tems.ts_font.vf_width * tems.ts_font.vf_height;
 
 		tems.ts_pix_data_size *= 4;
 
@@ -593,10 +608,8 @@
 	if (tems.ts_blank_line)
 		kmem_free(tems.ts_blank_line, old_blank_buf_size);
 
-	tems.ts_blank_line = (unsigned char *)
-	    kmem_alloc(tems.ts_c_dimension.width, KM_SLEEP);
-	for (i = 0; i < tems.ts_c_dimension.width; i++)
-		tems.ts_blank_line[i] = ' ';
+	tems.ts_blank_line = kmem_alloc(tems.ts_c_dimension.width *
+	    sizeof (*tems.ts_blank_line), KM_SLEEP);
 }
 
 /*
@@ -679,14 +692,28 @@
 }
 
 /*
+ * This function is used to clear entire screen via the underlying framebuffer
+ * driver.
+ */
+int
+tems_cls_layered(struct vis_consclear *pda,
+    cred_t *credp)
+{
+	int rval;
+
+	(void) ldi_ioctl(tems.ts_hdl, VIS_CONSCLEAR,
+	    (intptr_t)pda, FKIOCTL, credp, &rval);
+	return (rval);
+}
+
+/*
  * This function is used to display a rectangular blit of data
  * of a given size and location via the underlying framebuffer driver.
  * The blit can be as small as a pixel or as large as the screen.
  */
 void
-tems_display_layered(
-	struct vis_consdisplay *pda,
-	cred_t *credp)
+tems_display_layered(struct vis_consdisplay *pda,
+    cred_t *credp)
 {
 	int rval;
 
@@ -701,9 +728,8 @@
  * such as from vi when deleting characters and words.
  */
 void
-tems_copy_layered(
-	struct vis_conscopy *pma,
-	cred_t *credp)
+tems_copy_layered(struct vis_conscopy *pma,
+    cred_t *credp)
 {
 	int rval;
 
@@ -716,9 +742,8 @@
  * pixel inverting, text block cursor via the underlying framebuffer.
  */
 void
-tems_cursor_layered(
-	struct vis_conscursor *pca,
-	cred_t *credp)
+tems_cursor_layered(struct vis_conscursor *pca,
+    cred_t *credp)
 {
 	int rval;
 
@@ -749,9 +774,12 @@
 	case 8:
 		cm.index = 0;
 		cm.count = 16;
-		cm.red   = cmap4_to_24.red;   /* 8-bits (1/3 of TrueColor 24) */
-		cm.blue  = cmap4_to_24.blue;  /* 8-bits (1/3 of TrueColor 24) */
-		cm.green = cmap4_to_24.green; /* 8-bits (1/3 of TrueColor 24) */
+		/* 8-bits (1/3 of TrueColor 24) */
+		cm.red   = (uint8_t *)cmap4_to_24.red;
+		/* 8-bits (1/3 of TrueColor 24) */
+		cm.blue  = (uint8_t *)cmap4_to_24.blue;
+		/* 8-bits (1/3 of TrueColor 24) */
+		cm.green = (uint8_t *)cmap4_to_24.green;
 		(void) ldi_ioctl(tems.ts_hdl, VIS_PUTCMAP, (intptr_t)&cm,
 		    FKIOCTL, credp, &rval);
 		break;
@@ -792,7 +820,7 @@
 	int	ncols, width;
 
 	/* copy */
-	ma.s_row = nrows * tems.ts_font.height;
+	ma.s_row = nrows * tems.ts_font.vf_height;
 	ma.e_row = tems.ts_p_dimension.height - 1;
 	ma.t_row = 0;
 
@@ -803,7 +831,7 @@
 	tems_safe_copy(&ma, credp, called_from);
 
 	/* clear */
-	width = tems.ts_font.width;
+	width = tems.ts_font.vf_width;
 	ncols = (tems.ts_p_dimension.width + (width - 1))/ width;
 
 	tem_safe_pix_cls_range(tem, 0, nrows, tems.ts_p_offset.y,
@@ -835,8 +863,8 @@
 
 	tem_y = (prom_row + 1) * prom_charheight + prom_window_top -
 	    tems.ts_p_offset.y;
-	tem_row = (tem_y + tems.ts_font.height - 1) /
-	    tems.ts_font.height - 1;
+	tem_row = (tem_y + tems.ts_font.vf_height - 1) /
+	    tems.ts_font.vf_height - 1;
 
 	if (tem_row < 0) {
 		tem_row = 0;
@@ -914,31 +942,32 @@
 
 	pcolor->fg_color = DEFAULT_ANSI_FOREGROUND;
 	pcolor->bg_color = DEFAULT_ANSI_BACKGROUND;
+#ifndef _HAVE_TEM_FIRMWARE
+	plat_tem_get_colors(&pcolor->fg_color, &pcolor->bg_color);
+#endif
 
-	if (plat_stdout_is_framebuffer()) {
-		tems_get_inverses(&inverse, &inverse_screen);
-		if (inverse)
-			flags |= TEM_ATTR_REVERSE;
-		if (inverse_screen)
-			flags |= TEM_ATTR_SCREEN_REVERSE;
+	tems_get_inverses(&inverse, &inverse_screen);
+	if (inverse)
+		flags |= TEM_ATTR_REVERSE;
+	if (inverse_screen)
+		flags |= TEM_ATTR_SCREEN_REVERSE;
 
-		if (flags != 0) {
-			/*
-			 * If either reverse flag is set, the screen is in
-			 * white-on-black mode.  We set the bold flag to
-			 * improve readability.
-			 */
-			flags |= TEM_ATTR_BOLD;
-		} else {
-			/*
-			 * Otherwise, the screen is in black-on-white mode.
-			 * The SPARC PROM console, which starts in this mode,
-			 * uses the bright white background colour so we
-			 * match it here.
-			 */
-			if (pcolor->bg_color == ANSI_COLOR_WHITE)
-				flags |= TEM_ATTR_BRIGHT_BG;
-		}
+	if (flags != 0) {
+		/*
+		 * If either reverse flag is set, the screen is in
+		 * white-on-black mode.  We set the bold flag to
+		 * improve readability.
+		 */
+		flags |= TEM_ATTR_BOLD;
+	} else {
+		/*
+		 * Otherwise, the screen is in black-on-white mode.
+		 * The SPARC PROM console, which starts in this mode,
+		 * uses the bright white background colour so we
+		 * match it here.
+		 */
+		if (pcolor->bg_color == ANSI_COLOR_WHITE)
+			flags |= TEM_ATTR_BRIGHT_BG;
 	}
 
 	pcolor->a_flags = flags;
