1ffedf5deSToomas Soome /*
2199767f8SToomas Soome  * Copyright (c) 2000 Doug Rabson
3199767f8SToomas Soome  * All rights reserved.
4199767f8SToomas Soome  *
5199767f8SToomas Soome  * Redistribution and use in source and binary forms, with or without
6199767f8SToomas Soome  * modification, are permitted provided that the following conditions
7199767f8SToomas Soome  * are met:
8199767f8SToomas Soome  * 1. Redistributions of source code must retain the above copyright
9199767f8SToomas Soome  *    notice, this list of conditions and the following disclaimer.
10199767f8SToomas Soome  * 2. Redistributions in binary form must reproduce the above copyright
11199767f8SToomas Soome  *    notice, this list of conditions and the following disclaimer in the
12199767f8SToomas Soome  *    documentation and/or other materials provided with the distribution.
13199767f8SToomas Soome  *
14199767f8SToomas Soome  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15199767f8SToomas Soome  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16199767f8SToomas Soome  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17199767f8SToomas Soome  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18199767f8SToomas Soome  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19199767f8SToomas Soome  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20199767f8SToomas Soome  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21199767f8SToomas Soome  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22199767f8SToomas Soome  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23199767f8SToomas Soome  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24199767f8SToomas Soome  * SUCH DAMAGE.
25199767f8SToomas Soome  */
26199767f8SToomas Soome 
27199767f8SToomas Soome #include <sys/cdefs.h>
28199767f8SToomas Soome 
29199767f8SToomas Soome #include <efi.h>
30199767f8SToomas Soome #include <efilib.h>
319890ff83SToomas Soome #include <sys/tem_impl.h>
329890ff83SToomas Soome #include <sys/multiboot2.h>
339890ff83SToomas Soome #include <machine/metadata.h>
349890ff83SToomas Soome #include <gfx_fb.h>
35199767f8SToomas Soome 
36199767f8SToomas Soome #include "bootstrap.h"
37199767f8SToomas Soome 
389890ff83SToomas Soome struct efi_fb		efifb;
399890ff83SToomas Soome EFI_GRAPHICS_OUTPUT	*gop;
409890ff83SToomas Soome EFI_UGA_DRAW_PROTOCOL	*uga;
419890ff83SToomas Soome 
429890ff83SToomas Soome static EFI_GUID ccontrol_protocol_guid = EFI_CONSOLE_CONTROL_PROTOCOL_GUID;
439890ff83SToomas Soome static EFI_CONSOLE_CONTROL_PROTOCOL	*console_control;
449890ff83SToomas Soome static EFI_GUID simple_input_ex_guid = EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID;
459890ff83SToomas Soome static EFI_CONSOLE_CONTROL_SCREEN_MODE	console_mode;
46199767f8SToomas Soome static SIMPLE_TEXT_OUTPUT_INTERFACE	*conout;
47199767f8SToomas Soome 
489890ff83SToomas Soome /* mode change callback and argument from tem */
499890ff83SToomas Soome static vis_modechg_cb_t modechg_cb;
509890ff83SToomas Soome static struct vis_modechg_arg *modechg_arg;
519890ff83SToomas Soome static tem_vt_state_t tem;
529890ff83SToomas Soome 
539890ff83SToomas Soome struct efi_console_data {
549890ff83SToomas Soome 	struct visual_ops			*ecd_visual_ops;
559890ff83SToomas Soome 	SIMPLE_INPUT_INTERFACE			*ecd_conin;
569890ff83SToomas Soome 	EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL	*ecd_coninex;
579890ff83SToomas Soome };
58199767f8SToomas Soome 
59199767f8SToomas Soome #define	KEYBUFSZ 10
60c6dd35daSToomas Soome static unsigned keybuf[KEYBUFSZ];	/* keybuf for extended codes */
619890ff83SToomas Soome 
62416f8d72SToomas Soome static int key_pending;
63ffedf5deSToomas Soome 
649890ff83SToomas Soome static const unsigned char solaris_color_to_efi_color[16] = {
659890ff83SToomas Soome 	EFI_WHITE,
669890ff83SToomas Soome 	EFI_BLACK,
679890ff83SToomas Soome 	EFI_BLUE,
689890ff83SToomas Soome 	EFI_GREEN,
699890ff83SToomas Soome 	EFI_CYAN,
709890ff83SToomas Soome 	EFI_RED,
719890ff83SToomas Soome 	EFI_MAGENTA,
729890ff83SToomas Soome 	EFI_BROWN,
739890ff83SToomas Soome 	EFI_LIGHTGRAY,
749890ff83SToomas Soome 	EFI_DARKGRAY,
759890ff83SToomas Soome 	EFI_LIGHTBLUE,
769890ff83SToomas Soome 	EFI_LIGHTGREEN,
779890ff83SToomas Soome 	EFI_LIGHTCYAN,
789890ff83SToomas Soome 	EFI_LIGHTRED,
799890ff83SToomas Soome 	EFI_LIGHTMAGENTA,
809890ff83SToomas Soome 	EFI_YELLOW
819890ff83SToomas Soome };
82199767f8SToomas Soome 
839890ff83SToomas Soome #define	DEFAULT_FGCOLOR	EFI_LIGHTGRAY
849890ff83SToomas Soome #define	DEFAULT_BGCOLOR	EFI_BLACK
859890ff83SToomas Soome 
869890ff83SToomas Soome extern int efi_find_framebuffer(struct efi_fb *efifb);
87199767f8SToomas Soome 
889890ff83SToomas Soome static void efi_framebuffer_setup(void);
89199767f8SToomas Soome static void efi_cons_probe(struct console *);
90199767f8SToomas Soome static int efi_cons_init(struct console *, int);
919890ff83SToomas Soome static void efi_cons_putchar(struct console *, int);
929890ff83SToomas Soome static void efi_cons_efiputchar(int);
939890ff83SToomas Soome static int efi_cons_getchar(struct console *);
949890ff83SToomas Soome static int efi_cons_poll(struct console *);
959890ff83SToomas Soome static int efi_cons_ioctl(struct console *cp, int cmd, void *data);
9680e47917SToomas Soome static void efi_cons_devinfo(struct console *);
979890ff83SToomas Soome 
989890ff83SToomas Soome static int efi_fb_devinit(struct vis_devinit *);
999890ff83SToomas Soome static void efi_cons_cursor(struct vis_conscursor *);
1009890ff83SToomas Soome 
1019890ff83SToomas Soome static int efi_text_devinit(struct vis_devinit *);
1029890ff83SToomas Soome static int efi_text_cons_clear(struct vis_consclear *);
1039890ff83SToomas Soome static void efi_text_cons_copy(struct vis_conscopy *);
1049890ff83SToomas Soome static void efi_text_cons_display(struct vis_consdisplay *);
105199767f8SToomas Soome 
106199767f8SToomas Soome struct console efi_console = {
1079890ff83SToomas Soome 	.c_name = "text",
1089890ff83SToomas Soome 	.c_desc = "EFI console",
1099890ff83SToomas Soome 	.c_flags = C_WIDEOUT,
1109890ff83SToomas Soome 	.c_probe = efi_cons_probe,
1119890ff83SToomas Soome 	.c_init = efi_cons_init,
1129890ff83SToomas Soome 	.c_out = efi_cons_putchar,
1139890ff83SToomas Soome 	.c_in = efi_cons_getchar,
1149890ff83SToomas Soome 	.c_ready = efi_cons_poll,
1159890ff83SToomas Soome 	.c_ioctl = efi_cons_ioctl,
11680e47917SToomas Soome 	.c_devinfo = efi_cons_devinfo,
1179890ff83SToomas Soome 	.c_private = NULL
118199767f8SToomas Soome };
119199767f8SToomas Soome 
1209890ff83SToomas Soome static struct vis_identifier fb_ident = { "efi_fb" };
1219890ff83SToomas Soome static struct vis_identifier text_ident = { "efi_text" };
1229890ff83SToomas Soome 
1239890ff83SToomas Soome struct visual_ops fb_ops = {
1249890ff83SToomas Soome 	.ident = &fb_ident,
1259890ff83SToomas Soome 	.kdsetmode = NULL,
1269890ff83SToomas Soome 	.devinit = efi_fb_devinit,
1272d84dc94SToomas Soome 	.cons_copy = gfx_fb_cons_copy,
1282d84dc94SToomas Soome 	.cons_display = gfx_fb_cons_display,
1299890ff83SToomas Soome 	.cons_cursor = efi_cons_cursor,
1302d84dc94SToomas Soome 	.cons_clear = gfx_fb_cons_clear,
1319890ff83SToomas Soome 	.cons_put_cmap = NULL
1329890ff83SToomas Soome };
133199767f8SToomas Soome 
1349890ff83SToomas Soome struct visual_ops text_ops = {
1359890ff83SToomas Soome 	.ident = &text_ident,
1369890ff83SToomas Soome 	.kdsetmode = NULL,
1379890ff83SToomas Soome 	.devinit = efi_text_devinit,
1389890ff83SToomas Soome 	.cons_copy = efi_text_cons_copy,
1399890ff83SToomas Soome 	.cons_display = efi_text_cons_display,
1409890ff83SToomas Soome 	.cons_cursor = efi_cons_cursor,
1419890ff83SToomas Soome 	.cons_clear = efi_text_cons_clear,
1429890ff83SToomas Soome 	.cons_put_cmap = NULL
1439890ff83SToomas Soome };
1449890ff83SToomas Soome 
1459890ff83SToomas Soome /*
1469890ff83SToomas Soome  * platform specific functions for tem
1479890ff83SToomas Soome  */
1489890ff83SToomas Soome int
plat_stdout_is_framebuffer(void)1499890ff83SToomas Soome plat_stdout_is_framebuffer(void)
150199767f8SToomas Soome {
1519890ff83SToomas Soome 	return (console_mode == EfiConsoleControlScreenGraphics);
152199767f8SToomas Soome }
153199767f8SToomas Soome 
154199767f8SToomas Soome void
plat_tem_hide_prom_cursor(void)1559890ff83SToomas Soome plat_tem_hide_prom_cursor(void)
156199767f8SToomas Soome {
157*190f051bSToomas Soome 	if (has_boot_services)
158*190f051bSToomas Soome 		conout->EnableCursor(conout, FALSE);
1599890ff83SToomas Soome }
1609890ff83SToomas Soome 
1619890ff83SToomas Soome static void
plat_tem_display_prom_cursor(screen_pos_t row,screen_pos_t col)1629890ff83SToomas Soome plat_tem_display_prom_cursor(screen_pos_t row, screen_pos_t col)
1639890ff83SToomas Soome {
1649890ff83SToomas Soome 
165*190f051bSToomas Soome 	if (has_boot_services) {
166*190f051bSToomas Soome 		conout->SetCursorPosition(conout, col, row);
167*190f051bSToomas Soome 		conout->EnableCursor(conout, TRUE);
168*190f051bSToomas Soome 	}
169199767f8SToomas Soome }
170199767f8SToomas Soome 
171199767f8SToomas Soome void
plat_tem_get_prom_pos(uint32_t * row,uint32_t * col)1729890ff83SToomas Soome plat_tem_get_prom_pos(uint32_t *row, uint32_t *col)
173199767f8SToomas Soome {
1749890ff83SToomas Soome 	if (console_mode == EfiConsoleControlScreenText) {
1759890ff83SToomas Soome 		*col = (uint32_t)conout->Mode->CursorColumn;
1769890ff83SToomas Soome 		*row = (uint32_t)conout->Mode->CursorRow;
1779890ff83SToomas Soome 	} else {
1789890ff83SToomas Soome 		*col = 0;
1799890ff83SToomas Soome 		*row = 0;
1809890ff83SToomas Soome 	}
181199767f8SToomas Soome }
182199767f8SToomas Soome 
1839890ff83SToomas Soome /*
1849890ff83SToomas Soome  * plat_tem_get_prom_size() is supposed to return screen size
1859890ff83SToomas Soome  * in chars. Return real data for text mode and TEM defaults for graphical
1869890ff83SToomas Soome  * mode, so the tem can compute values based on default and font.
1879890ff83SToomas Soome  */
1889890ff83SToomas Soome void
plat_tem_get_prom_size(size_t * height,size_t * width)1899890ff83SToomas Soome plat_tem_get_prom_size(size_t *height, size_t *width)
1909890ff83SToomas Soome {
1919890ff83SToomas Soome 	UINTN cols, rows;
1929890ff83SToomas Soome 	if (console_mode == EfiConsoleControlScreenText) {
1939890ff83SToomas Soome 		(void) conout->QueryMode(conout, conout->Mode->Mode,
1949890ff83SToomas Soome 		    &cols, &rows);
1959890ff83SToomas Soome 		*height = (size_t)rows;
1969890ff83SToomas Soome 		*width = (size_t)cols;
1979890ff83SToomas Soome 	} else {
1989890ff83SToomas Soome 		*height = TEM_DEFAULT_ROWS;
1999890ff83SToomas Soome 		*width = TEM_DEFAULT_COLS;
2009890ff83SToomas Soome 	}
2019890ff83SToomas Soome }
202199767f8SToomas Soome 
2039890ff83SToomas Soome /*
2049890ff83SToomas Soome  * Callback to notify about console mode change.
2059890ff83SToomas Soome  * mode is value from enum EFI_CONSOLE_CONTROL_SCREEN_MODE.
2069890ff83SToomas Soome  */
2079890ff83SToomas Soome void
plat_cons_update_mode(int mode)2089890ff83SToomas Soome plat_cons_update_mode(int mode)
209199767f8SToomas Soome {
2109890ff83SToomas Soome 	UINTN cols, rows;
2119890ff83SToomas Soome 	struct vis_devinit devinit;
2129890ff83SToomas Soome 	struct efi_console_data *ecd = efi_console.c_private;
2139890ff83SToomas Soome 
2149890ff83SToomas Soome 	/* Make sure we have usable console. */
2159890ff83SToomas Soome 	if (efi_find_framebuffer(&efifb)) {
2169890ff83SToomas Soome 		console_mode = EfiConsoleControlScreenText;
2179890ff83SToomas Soome 	} else {
2189890ff83SToomas Soome 		efi_framebuffer_setup();
2199890ff83SToomas Soome 		if (mode != -1 && console_mode != mode)
2209890ff83SToomas Soome 			console_mode = mode;
2219890ff83SToomas Soome 	}
2229890ff83SToomas Soome 
2239890ff83SToomas Soome 	if (console_control != NULL)
224c6dd35daSToomas Soome 		(void) console_control->SetMode(console_control, console_mode);
2259890ff83SToomas Soome 
2269890ff83SToomas Soome 	/* some firmware enables the cursor when switching modes */
2279890ff83SToomas Soome 	conout->EnableCursor(conout, FALSE);
2289890ff83SToomas Soome 	if (console_mode == EfiConsoleControlScreenText) {
229c6dd35daSToomas Soome 		(void) conout->QueryMode(conout, conout->Mode->Mode,
2309890ff83SToomas Soome 		    &cols, &rows);
2319890ff83SToomas Soome 		devinit.version = VIS_CONS_REV;
2329890ff83SToomas Soome 		devinit.width = cols;
2339890ff83SToomas Soome 		devinit.height = rows;
2349890ff83SToomas Soome 		devinit.depth = 4;
2359890ff83SToomas Soome 		devinit.linebytes = cols;
2369890ff83SToomas Soome 		devinit.color_map = NULL;
2379890ff83SToomas Soome 		devinit.mode = VIS_TEXT;
2389890ff83SToomas Soome 		ecd->ecd_visual_ops = &text_ops;
2399890ff83SToomas Soome 	} else {
2409890ff83SToomas Soome 		devinit.version = VIS_CONS_REV;
2419890ff83SToomas Soome 		devinit.width = gfx_fb.framebuffer_common.framebuffer_width;
2429890ff83SToomas Soome 		devinit.height = gfx_fb.framebuffer_common.framebuffer_height;
2439890ff83SToomas Soome 		devinit.depth = gfx_fb.framebuffer_common.framebuffer_bpp;
2449890ff83SToomas Soome 		devinit.linebytes = gfx_fb.framebuffer_common.framebuffer_pitch;
2459890ff83SToomas Soome 		devinit.color_map = gfx_fb_color_map;
2469890ff83SToomas Soome 		devinit.mode = VIS_PIXEL;
2479890ff83SToomas Soome 		ecd->ecd_visual_ops = &fb_ops;
2489890ff83SToomas Soome 	}
2499890ff83SToomas Soome 
2509890ff83SToomas Soome 	modechg_cb(modechg_arg, &devinit);
251199767f8SToomas Soome }
252199767f8SToomas Soome 
253199767f8SToomas Soome static int
efi_fb_devinit(struct vis_devinit * data)2549890ff83SToomas Soome efi_fb_devinit(struct vis_devinit *data)
255199767f8SToomas Soome {
2569890ff83SToomas Soome 	if (console_mode != EfiConsoleControlScreenGraphics)
2579890ff83SToomas Soome 		return (1);
2589890ff83SToomas Soome 
2599890ff83SToomas Soome 	data->version = VIS_CONS_REV;
2609890ff83SToomas Soome 	data->width = gfx_fb.framebuffer_common.framebuffer_width;
2619890ff83SToomas Soome 	data->height = gfx_fb.framebuffer_common.framebuffer_height;
2629890ff83SToomas Soome 	data->depth = gfx_fb.framebuffer_common.framebuffer_bpp;
2639890ff83SToomas Soome 	data->linebytes = gfx_fb.framebuffer_common.framebuffer_pitch;
2649890ff83SToomas Soome 	data->color_map = gfx_fb_color_map;
2659890ff83SToomas Soome 	data->mode = VIS_PIXEL;
2669890ff83SToomas Soome 
2679890ff83SToomas Soome 	modechg_cb = data->modechg_cb;
2689890ff83SToomas Soome 	modechg_arg = data->modechg_arg;
2699890ff83SToomas Soome 
2709890ff83SToomas Soome 	return (0);
271199767f8SToomas Soome }
272199767f8SToomas Soome 
2739890ff83SToomas Soome static int
efi_text_devinit(struct vis_devinit * data)2749890ff83SToomas Soome efi_text_devinit(struct vis_devinit *data)
275199767f8SToomas Soome {
2769890ff83SToomas Soome 	UINTN cols, rows;
2779890ff83SToomas Soome 
2789890ff83SToomas Soome 	if (console_mode != EfiConsoleControlScreenText)
2799890ff83SToomas Soome 		return (1);
2809890ff83SToomas Soome 
281c6dd35daSToomas Soome 	(void) conout->QueryMode(conout, conout->Mode->Mode, &cols, &rows);
2829890ff83SToomas Soome 	data->version = VIS_CONS_REV;
2839890ff83SToomas Soome 	data->width = cols;
2849890ff83SToomas Soome 	data->height = rows;
2859890ff83SToomas Soome 	data->depth = 4;
2869890ff83SToomas Soome 	data->linebytes = cols;
2879890ff83SToomas Soome 	data->color_map = NULL;
2889890ff83SToomas Soome 	data->mode = VIS_TEXT;
2899890ff83SToomas Soome 
2909890ff83SToomas Soome 	modechg_cb = data->modechg_cb;
2919890ff83SToomas Soome 	modechg_arg = data->modechg_arg;
2929890ff83SToomas Soome 
2939890ff83SToomas Soome 	return (0);
294199767f8SToomas Soome }
295199767f8SToomas Soome 
2969890ff83SToomas Soome static int
efi_text_cons_clear(struct vis_consclear * ca)2979890ff83SToomas Soome efi_text_cons_clear(struct vis_consclear *ca)
298199767f8SToomas Soome {
2999890ff83SToomas Soome 	EFI_STATUS st;
3009890ff83SToomas Soome 	UINTN attr = conout->Mode->Attribute & 0x0F;
3011b61d0d2SToomas Soome 	uint8_t bg;
302199767f8SToomas Soome 
303*190f051bSToomas Soome 	if (!has_boot_services)
304*190f051bSToomas Soome 		return (0);
305*190f051bSToomas Soome 
306fa9eb222SToomas Soome 	bg = solaris_color_to_efi_color[ca->bg_color.four & 0xF] & 0x7;
3071b61d0d2SToomas Soome 
3081b61d0d2SToomas Soome 	attr = EFI_TEXT_ATTR(attr, bg);
3099890ff83SToomas Soome 	st = conout->SetAttribute(conout, attr);
3109890ff83SToomas Soome 	if (EFI_ERROR(st))
3119890ff83SToomas Soome 		return (1);
3129890ff83SToomas Soome 	st = conout->ClearScreen(conout);
3139890ff83SToomas Soome 	if (EFI_ERROR(st))
3149890ff83SToomas Soome 		return (1);
3159890ff83SToomas Soome 	return (0);
316199767f8SToomas Soome }
317199767f8SToomas Soome 
318199767f8SToomas Soome static void
efi_text_cons_copy(struct vis_conscopy * ma)3199890ff83SToomas Soome efi_text_cons_copy(struct vis_conscopy *ma)
3209890ff83SToomas Soome {
3219890ff83SToomas Soome 	UINTN col, row;
322199767f8SToomas Soome 
323*190f051bSToomas Soome 	if (!has_boot_services)
324*190f051bSToomas Soome 		return;
325*190f051bSToomas Soome 
3269890ff83SToomas Soome 	col = 0;
3279890ff83SToomas Soome 	row = ma->e_row;
3289890ff83SToomas Soome 	conout->SetCursorPosition(conout, col, row);
329199767f8SToomas Soome 
3309890ff83SToomas Soome 	efi_cons_efiputchar('\n');
331199767f8SToomas Soome }
332199767f8SToomas Soome 
333199767f8SToomas Soome static void
efi_text_cons_display(struct vis_consdisplay * da)3349890ff83SToomas Soome efi_text_cons_display(struct vis_consdisplay *da)
335199767f8SToomas Soome {
3369890ff83SToomas Soome 	EFI_STATUS st;
3379890ff83SToomas Soome 	UINTN attr;
3389890ff83SToomas Soome 	UINTN row, col;
3399890ff83SToomas Soome 	tem_char_t *data;
3401b61d0d2SToomas Soome 	uint8_t fg, bg;
3419890ff83SToomas Soome 	int i;
342199767f8SToomas Soome 
343*190f051bSToomas Soome 	if (!has_boot_services)
344*190f051bSToomas Soome 		return;
345*190f051bSToomas Soome 
346c6dd35daSToomas Soome 	(void) conout->QueryMode(conout, conout->Mode->Mode, &col, &row);
3479890ff83SToomas Soome 
3489890ff83SToomas Soome 	/* reduce clear line on bottom row by one to prevent autoscroll */
3499890ff83SToomas Soome 	if (row - 1 == da->row && da->col == 0 && da->width == col)
3509890ff83SToomas Soome 		da->width--;
3519890ff83SToomas Soome 
3529890ff83SToomas Soome 	data = (tem_char_t *)da->data;
353fa9eb222SToomas Soome 	fg = solaris_color_to_efi_color[da->fg_color.four & 0xf];
354fa9eb222SToomas Soome 	bg = solaris_color_to_efi_color[da->bg_color.four & 0xf] & 0x7;
3551b61d0d2SToomas Soome 	attr = EFI_TEXT_ATTR(fg, bg);
3561b61d0d2SToomas Soome 
3579890ff83SToomas Soome 	st = conout->SetAttribute(conout, attr);
3589890ff83SToomas Soome 	if (EFI_ERROR(st))
3599890ff83SToomas Soome 		return;
3609890ff83SToomas Soome 	row = da->row;
3619890ff83SToomas Soome 	col = da->col;
3629890ff83SToomas Soome 	conout->SetCursorPosition(conout, col, row);
3639890ff83SToomas Soome 	for (i = 0; i < da->width; i++)
3649890ff83SToomas Soome 		efi_cons_efiputchar(data[i]);
365199767f8SToomas Soome }
366199767f8SToomas Soome 
efi_cons_cursor(struct vis_conscursor * cc)3679890ff83SToomas Soome static void efi_cons_cursor(struct vis_conscursor *cc)
368199767f8SToomas Soome {
3699890ff83SToomas Soome 	switch (cc->action) {
3709890ff83SToomas Soome 	case VIS_HIDE_CURSOR:
3719890ff83SToomas Soome 		if (plat_stdout_is_framebuffer())
3729890ff83SToomas Soome 			gfx_fb_display_cursor(cc);
3739890ff83SToomas Soome 		else
3749890ff83SToomas Soome 			plat_tem_hide_prom_cursor();
375199767f8SToomas Soome 		break;
3769890ff83SToomas Soome 	case VIS_DISPLAY_CURSOR:
3779890ff83SToomas Soome 		if (plat_stdout_is_framebuffer())
3789890ff83SToomas Soome 			gfx_fb_display_cursor(cc);
3799890ff83SToomas Soome 		else
3809890ff83SToomas Soome 			plat_tem_display_prom_cursor(cc->row, cc->col);
381199767f8SToomas Soome 		break;
3829890ff83SToomas Soome 	case VIS_GET_CURSOR: {	/* only used at startup */
3839890ff83SToomas Soome 		uint32_t row, col;
3849890ff83SToomas Soome 
385c6dd35daSToomas Soome 		row = col = 0;
3869890ff83SToomas Soome 		plat_tem_get_prom_pos(&row, &col);
3879890ff83SToomas Soome 		cc->row = row;
3889890ff83SToomas Soome 		cc->col = col;
3899890ff83SToomas Soome 		}
390199767f8SToomas Soome 		break;
391199767f8SToomas Soome 	}
3929890ff83SToomas Soome }
393199767f8SToomas Soome 
3949890ff83SToomas Soome static int
efi_cons_ioctl(struct console * cp,int cmd,void * data)3959890ff83SToomas Soome efi_cons_ioctl(struct console *cp, int cmd, void *data)
3969890ff83SToomas Soome {
3979890ff83SToomas Soome 	struct efi_console_data *ecd = cp->c_private;
3989890ff83SToomas Soome 	struct visual_ops *ops = ecd->ecd_visual_ops;
399199767f8SToomas Soome 
4009890ff83SToomas Soome 	switch (cmd) {
4019890ff83SToomas Soome 	case VIS_GETIDENTIFIER:
4029890ff83SToomas Soome 		memmove(data, ops->ident, sizeof (struct vis_identifier));
4039890ff83SToomas Soome 		break;
4049890ff83SToomas Soome 	case VIS_DEVINIT:
4059890ff83SToomas Soome 		return (ops->devinit(data));
4069890ff83SToomas Soome 	case VIS_CONSCLEAR:
4079890ff83SToomas Soome 		return (ops->cons_clear(data));
4089890ff83SToomas Soome 	case VIS_CONSCOPY:
4099890ff83SToomas Soome 		ops->cons_copy(data);
4109890ff83SToomas Soome 		break;
4119890ff83SToomas Soome 	case VIS_CONSDISPLAY:
4129890ff83SToomas Soome 		ops->cons_display(data);
4139890ff83SToomas Soome 		break;
4149890ff83SToomas Soome 	case VIS_CONSCURSOR:
4159890ff83SToomas Soome 		ops->cons_cursor(data);
4169890ff83SToomas Soome 		break;
4179890ff83SToomas Soome 	default:
4189890ff83SToomas Soome 		return (EINVAL);
419199767f8SToomas Soome 	}
4209890ff83SToomas Soome 	return (0);
421199767f8SToomas Soome }
422199767f8SToomas Soome 
423199767f8SToomas Soome static void
efi_framebuffer_setup(void)4249890ff83SToomas Soome efi_framebuffer_setup(void)
425199767f8SToomas Soome {
4269890ff83SToomas Soome 	int bpp, pos;
4279890ff83SToomas Soome 
4289890ff83SToomas Soome 	bpp = fls(efifb.fb_mask_red | efifb.fb_mask_green |
4299890ff83SToomas Soome 	    efifb.fb_mask_blue | efifb.fb_mask_reserved);
4309890ff83SToomas Soome 
4319890ff83SToomas Soome 	gfx_fb.framebuffer_common.mb_type = MULTIBOOT_TAG_TYPE_FRAMEBUFFER;
4329890ff83SToomas Soome 	gfx_fb.framebuffer_common.mb_size = sizeof (gfx_fb);
4339890ff83SToomas Soome 	gfx_fb.framebuffer_common.framebuffer_addr = efifb.fb_addr;
4349890ff83SToomas Soome 	gfx_fb.framebuffer_common.framebuffer_width = efifb.fb_width;
4359890ff83SToomas Soome 	gfx_fb.framebuffer_common.framebuffer_height = efifb.fb_height;
4369890ff83SToomas Soome 	gfx_fb.framebuffer_common.framebuffer_bpp = bpp;
4379890ff83SToomas Soome 	gfx_fb.framebuffer_common.framebuffer_pitch =
4389890ff83SToomas Soome 	    efifb.fb_stride * (bpp >> 3);
4399890ff83SToomas Soome 	gfx_fb.framebuffer_common.framebuffer_type =
4409890ff83SToomas Soome 	    MULTIBOOT_FRAMEBUFFER_TYPE_RGB;
4419890ff83SToomas Soome 	gfx_fb.framebuffer_common.mb_reserved = 0;
4429890ff83SToomas Soome 
4439890ff83SToomas Soome 	pos = ffs(efifb.fb_mask_red);
4449890ff83SToomas Soome 	if (pos != 0)
4459890ff83SToomas Soome 		pos--;
4469890ff83SToomas Soome 	gfx_fb.u.fb2.framebuffer_red_mask_size = fls(efifb.fb_mask_red >> pos);
4479890ff83SToomas Soome 	gfx_fb.u.fb2.framebuffer_red_field_position = pos;
4489890ff83SToomas Soome 	pos = ffs(efifb.fb_mask_green);
4499890ff83SToomas Soome 	if (pos != 0)
4509890ff83SToomas Soome 		pos--;
4519890ff83SToomas Soome 	gfx_fb.u.fb2.framebuffer_green_mask_size =
4529890ff83SToomas Soome 	    fls(efifb.fb_mask_green >> pos);
4539890ff83SToomas Soome 	gfx_fb.u.fb2.framebuffer_green_field_position = pos;
4549890ff83SToomas Soome 	pos = ffs(efifb.fb_mask_blue);
4559890ff83SToomas Soome 	if (pos != 0)
4569890ff83SToomas Soome 		pos--;
457