18e6d016fSToomas Soome /*
28e6d016fSToomas Soome * This file and its contents are supplied under the terms of the
38e6d016fSToomas Soome * Common Development and Distribution License ("CDDL"), version 1.0.
48e6d016fSToomas Soome * You may only use this file in accordance with the terms of version
58e6d016fSToomas Soome * 1.0 of the CDDL.
68e6d016fSToomas Soome *
78e6d016fSToomas Soome * A full copy of the text of the CDDL should have accompanied this
88e6d016fSToomas Soome * source. A copy of the CDDL is also available via the Internet at
98e6d016fSToomas Soome * http://www.illumos.org/license/CDDL.
108e6d016fSToomas Soome */
118e6d016fSToomas Soome
128e6d016fSToomas Soome /*
138e6d016fSToomas Soome * Copyright 2016 Toomas Soome <tsoome@me.com>
148e6d016fSToomas Soome */
158e6d016fSToomas Soome
168e6d016fSToomas Soome /*
178e6d016fSToomas Soome * dboot and early kernel needs simple putchar(int) interface to implement
188e6d016fSToomas Soome * printf() support. So we implement simple interface on top of
198e6d016fSToomas Soome * linear frame buffer, since we can not use tem directly, we are
208e6d016fSToomas Soome * just borrowing bits from it.
218e6d016fSToomas Soome *
228e6d016fSToomas Soome * Note, this implementation is assuming UEFI linear frame buffer and
238e6d016fSToomas Soome * 32-bit depth, which should not be issue as GOP is supposed to provide those.
248e6d016fSToomas Soome * At the time of writing, this is the only case for frame buffer anyhow.
258e6d016fSToomas Soome */
268e6d016fSToomas Soome
278e6d016fSToomas Soome #include <sys/types.h>
288e6d016fSToomas Soome #include <sys/systm.h>
298e6d016fSToomas Soome #include <sys/multiboot2.h>
308e6d016fSToomas Soome #include <sys/framebuffer.h>
318e6d016fSToomas Soome #include <sys/bootinfo.h>
328e6d016fSToomas Soome #include <sys/boot_console.h>
338e6d016fSToomas Soome #include <sys/bootconf.h>
34cbc8e155SToomas Soome #include <sys/rgb.h>
3529a77b73SToomas Soome #include "boot_console_impl.h"
368e6d016fSToomas Soome
378e6d016fSToomas Soome #define P2ROUNDUP(x, align) (-(-(x) & -(align)))
388e6d016fSToomas Soome #define MIN(a, b) ((a) < (b) ? (a) : (b))
39a4e6b9b6SToomas Soome #define nitems(x) (sizeof ((x)) / sizeof ((x)[0]))
408e6d016fSToomas Soome
418e6d016fSToomas Soome /*
428e6d016fSToomas Soome * Simplified visual_io data structures from visual_io.h
438e6d016fSToomas Soome */
448e6d016fSToomas Soome
458e6d016fSToomas Soome struct vis_consdisplay {
468e6d016fSToomas Soome uint16_t row; /* Row to display data at */
478e6d016fSToomas Soome uint16_t col; /* Col to display data at */
488e6d016fSToomas Soome uint16_t width; /* Width of data */
498e6d016fSToomas Soome uint16_t height; /* Height of data */
508e6d016fSToomas Soome uint8_t *data; /* Data to display */
518e6d016fSToomas Soome };
528e6d016fSToomas Soome
538e6d016fSToomas Soome struct vis_conscopy {
548e6d016fSToomas Soome uint16_t s_row; /* Starting row */
558e6d016fSToomas Soome uint16_t s_col; /* Starting col */
568e6d016fSToomas Soome uint16_t e_row; /* Ending row */
578e6d016fSToomas Soome uint16_t e_col; /* Ending col */
588e6d016fSToomas Soome uint16_t t_row; /* Row to move to */
598e6d016fSToomas Soome uint16_t t_col; /* Col to move to */
608e6d016fSToomas Soome };
618e6d016fSToomas Soome
62cbc8e155SToomas Soome /*
63cbc8e155SToomas Soome * We have largest font 16x32 with depth 32. This will allocate 2048
64cbc8e155SToomas Soome * bytes from BSS.
65cbc8e155SToomas Soome */
66cbc8e155SToomas Soome #define MAX_GLYPH (16 * 32 * 4)
67cbc8e155SToomas Soome
68cbc8e155SToomas Soome struct fontlist cf_fontlist;
69cbc8e155SToomas Soome static bitmap_data_t cf_data;
70cbc8e155SToomas Soome static struct font cf_font;
718e6d016fSToomas Soome
728e6d016fSToomas Soome static struct font boot_fb_font; /* set by set_font() */
738e6d016fSToomas Soome static uint8_t glyph[MAX_GLYPH];
748e6d016fSToomas Soome
7529a77b73SToomas Soome static void boot_fb_putchar(int);
7629a77b73SToomas Soome static void boot_fb_eraseline(void);
7729a77b73SToomas Soome static void boot_fb_setpos(int, int);
7829a77b73SToomas Soome static void boot_fb_shiftline(int);
7929a77b73SToomas Soome static void boot_fb_eraseline_impl(uint16_t, uint16_t);
8029a77b73SToomas Soome
81cbc8e155SToomas Soome static void
xbi_init_font(struct xboot_info * xbi)82cbc8e155SToomas Soome xbi_init_font(struct xboot_info *xbi)
83cbc8e155SToomas Soome {
84cbc8e155SToomas Soome uint32_t i, checksum = 0;
85cbc8e155SToomas Soome struct boot_modules *modules;
86cbc8e155SToomas Soome struct font_info *fi;
87cbc8e155SToomas Soome uintptr_t ptr;
88cbc8e155SToomas Soome
89cbc8e155SToomas Soome modules = (struct boot_modules *)(uintptr_t)xbi->bi_modules;
90cbc8e155SToomas Soome for (i = 0; i < xbi->bi_module_cnt; i++) {
91cbc8e155SToomas Soome if (modules[i].bm_type == BMT_FONT)
92cbc8e155SToomas Soome break;
93cbc8e155SToomas Soome }
94cbc8e155SToomas Soome if (i == xbi->bi_module_cnt)
95cbc8e155SToomas Soome return;
96cbc8e155SToomas Soome
97cbc8e155SToomas Soome ptr = (uintptr_t)modules[i].bm_addr;
98cbc8e155SToomas Soome fi = (struct font_info *)ptr;
99cbc8e155SToomas Soome
100cbc8e155SToomas Soome /*
101cbc8e155SToomas Soome * Compute and verify checksum. The total sum of all the fields
102cbc8e155SToomas Soome * must be 0. Note, the return from this point means we will
103cbc8e155SToomas Soome * use default font.
104cbc8e155SToomas Soome */
105cbc8e155SToomas Soome checksum += fi->fi_width;
106cbc8e155SToomas Soome checksum += fi->fi_height;
107cbc8e155SToomas Soome checksum += fi->fi_bitmap_size;
108cbc8e155SToomas Soome for (i = 0; i < VFNT_MAPS; i++)
109cbc8e155SToomas Soome checksum += fi->fi_map_count[i];
110cbc8e155SToomas Soome if (checksum + fi->fi_checksum != 0)
111cbc8e155SToomas Soome return;
112cbc8e155SToomas Soome
113cbc8e155SToomas Soome cf_data.width = fi->fi_width;
114cbc8e155SToomas Soome cf_data.height = fi->fi_height;
115cbc8e155SToomas Soome cf_data.uncompressed_size = fi->fi_bitmap_size;
116cbc8e155SToomas Soome cf_data.font = &cf_font;
117cbc8e155SToomas Soome
118cbc8e155SToomas Soome ptr += sizeof (struct font_info);
119cbc8e155SToomas Soome ptr = P2ROUNDUP(ptr, 8);
120cbc8e155SToomas Soome
121cbc8e155SToomas Soome cf_font.vf_width = fi->fi_width;
122cbc8e155SToomas Soome cf_font.vf_height = fi->fi_height;
123cbc8e155SToomas Soome for (i = 0; i < VFNT_MAPS; i++) {
124cbc8e155SToomas Soome if (fi->fi_map_count[i] == 0)
125cbc8e155SToomas Soome continue;
126cbc8e155SToomas Soome cf_font.vf_map_count[i] = fi->fi_map_count[i];
127cbc8e155SToomas Soome cf_font.vf_map[i] = (struct font_map *)ptr;
128cbc8e155SToomas Soome ptr += (fi->fi_map_count[i] * sizeof (struct font_map));
129cbc8e155SToomas Soome ptr = P2ROUNDUP(ptr, 8);
130cbc8e155SToomas Soome }
131cbc8e155SToomas Soome cf_font.vf_bytes = (uint8_t *)ptr;
132cbc8e155SToomas Soome cf_fontlist.font_name = NULL;
133cbc8e155SToomas Soome cf_fontlist.font_flags = FONT_BOOT;
134cbc8e155SToomas Soome cf_fontlist.font_data = &cf_data;
135cbc8e155SToomas Soome cf_fontlist.font_load = NULL;
136cbc8e155SToomas Soome STAILQ_INSERT_HEAD(&fonts, &cf_fontlist, font_next);
137cbc8e155SToomas Soome }
138cbc8e155SToomas Soome
1398e6d016fSToomas Soome /*
1408e6d016fSToomas Soome * extract data from MB2 framebuffer tag and set up initial frame buffer.
1418e6d016fSToomas Soome */
1428e6d016fSToomas Soome boolean_t
xbi_fb_init(struct xboot_info * xbi,bcons_dev_t * bcons_dev)14329a77b73SToomas Soome xbi_fb_init(struct xboot_info *xbi, bcons_dev_t *bcons_dev)
1448e6d016fSToomas Soome {
1458e6d016fSToomas Soome multiboot_tag_framebuffer_t *tag;
1468e6d016fSToomas Soome boot_framebuffer_t *xbi_fb;
1478e6d016fSToomas Soome
1488e6d016fSToomas Soome xbi_fb = (boot_framebuffer_t *)(uintptr_t)xbi->bi_framebuffer;
1498e6d016fSToomas Soome if (xbi_fb == NULL)
1508e6d016fSToomas Soome return (B_FALSE);
1518e6d016fSToomas Soome
1528e6d016fSToomas Soome #if !defined(_BOOT)
1538e6d016fSToomas Soome /* For early kernel, we get cursor position from dboot. */
1548e6d016fSToomas Soome fb_info.cursor.origin.x = xbi_fb->cursor.origin.x;
1558e6d016fSToomas Soome fb_info.cursor.origin.y = xbi_fb->cursor.origin.y;
1568e6d016fSToomas Soome fb_info.cursor.pos.x = xbi_fb->cursor.pos.x;
1578e6d016fSToomas Soome fb_info.cursor.pos.y = xbi_fb->cursor.pos.y;
1588e6d016fSToomas Soome fb_info.cursor.visible = xbi_fb->cursor.visible;
1598e6d016fSToomas Soome #endif
1608e6d016fSToomas Soome
161b70e9485SToomas Soome xbi_init_font(xbi);
1628e6d016fSToomas Soome tag = (multiboot_tag_framebuffer_t *)(uintptr_t)xbi_fb->framebuffer;
1638e6d016fSToomas Soome if (tag == NULL) {
1648e6d016fSToomas Soome return (B_FALSE);
1658e6d016fSToomas Soome }
1668e6d016fSToomas Soome
1678e6d016fSToomas Soome fb_info.paddr = tag->framebuffer_common.framebuffer_addr;
1688e6d016fSToomas Soome fb_info.pitch = tag->framebuffer_common.framebuffer_pitch;
1698e6d016fSToomas Soome fb_info.depth = tag->framebuffer_common.framebuffer_bpp;
1708e6d016fSToomas Soome fb_info.bpp = P2ROUNDUP(fb_info.depth, 8) >> 3;
1718e6d016fSToomas Soome fb_info.screen.x = tag->framebuffer_common.framebuffer_width;
1728e6d016fSToomas Soome fb_info.screen.y = tag->framebuffer_common.framebuffer_height;
1738e6d016fSToomas Soome fb_info.fb_size = fb_info.screen.y * fb_info.pitch;
1748e6d016fSToomas Soome
17529a77b73SToomas Soome bcons_dev->bd_putchar = boot_fb_putchar;
17629a77b73SToomas Soome bcons_dev->bd_eraseline = boot_fb_eraseline;
17729a77b73SToomas Soome bcons_dev->bd_cursor = boot_fb_cursor;
17829a77b73SToomas Soome bcons_dev->bd_setpos = boot_fb_setpos;
17929a77b73SToomas Soome bcons_dev->bd_shift = boot_fb_shiftline;
18029a77b73SToomas Soome
1818e6d016fSToomas Soome if (fb_info.paddr == 0)
1828e6d016fSToomas Soome fb_info.fb_type = FB_TYPE_UNKNOWN;
1838e6d016fSToomas Soome
1848e6d016fSToomas Soome switch (tag->framebuffer_common.framebuffer_type) {
1858e6d016fSToomas Soome case MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT:
1868e6d016fSToomas Soome fb_info.fb_type = FB_TYPE_EGA_TEXT;
1878e6d016fSToomas Soome return (B_FALSE);
1888e6d016fSToomas Soome
1898e6d016fSToomas Soome case MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED:
1908e6d016fSToomas Soome if (fb_info.paddr != 0)
1918e6d016fSToomas Soome fb_info.fb_type = FB_TYPE_INDEXED;
1928e6d016fSToomas Soome return (B_TRUE);
1938e6d016fSToomas Soome
1948e6d016fSToomas Soome case MULTIBOOT_FRAMEBUFFER_TYPE_RGB:
1958e6d016fSToomas Soome if (fb_info.paddr != 0)
1968e6d016fSToomas Soome fb_info.fb_type = FB_TYPE_RGB;
1978e6d016fSToomas Soome break;
1988e6d016fSToomas Soome
1998e6d016fSToomas Soome default:
2008e6d016fSToomas Soome return (B_FALSE);
2018e6d016fSToomas Soome }
2028e6d016fSToomas Soome
2038e6d016fSToomas Soome fb_info.rgb.red.size = tag->u.fb2.framebuffer_red_mask_size;
2048e6d016fSToomas Soome fb_info.rgb.red.pos = tag->u.fb2.framebuffer_red_field_position;
2058e6d016fSToomas Soome fb_info.rgb.green.size = tag->u.fb2.framebuffer_green_mask_size;
2068e6d016fSToomas Soome fb_info.rgb.green.pos = tag->u.fb2.framebuffer_green_field_position;
2078e6d016fSToomas Soome fb_info.rgb.blue.size = tag->u.fb2.framebuffer_blue_mask_size;
2088e6d016fSToomas Soome fb_info.rgb.blue.pos = tag->u.fb2.framebuffer_blue_field_position;
209*fa9eb222SToomas Soome rgb_info = fb_info.rgb;
2108e6d016fSToomas Soome
2118e6d016fSToomas Soome return (B_TRUE);
2128e6d016fSToomas Soome }
2138e6d016fSToomas Soome
2148e6d016fSToomas Soome /* set font and pass the data to fb_info */
2158e6d016fSToomas Soome static void
boot_fb_set_font(uint16_t height,uint16_t width)2168e6d016fSToomas Soome boot_fb_set_font(uint16_t height, uint16_t width)
2178e6d016fSToomas Soome {
2188e6d016fSToomas Soome short h, w;
219cbc8e155SToomas Soome bitmap_data_t *bp;
220cbc8e155SToomas Soome int i;
2218e6d016fSToomas Soome
2228e6d016fSToomas Soome h = MIN(height, 4096);
2238e6d016fSToomas Soome w = MIN(width, 4096);
2248e6d016fSToomas Soome
225cbc8e155SToomas Soome bp = set_font((short *)&fb_info.terminal.y,
2268e6d016fSToomas Soome (short *)&fb_info.terminal.x, h, w);
227cbc8e155SToomas Soome
228cbc8e155SToomas Soome boot_fb_font.vf_bytes = bp->font->vf_bytes;
229cbc8e155SToomas Soome boot_fb_font.vf_width = bp->font->vf_width;
230cbc8e155SToomas Soome boot_fb_font.vf_height = bp->font->vf_height;
231cbc8e155SToomas Soome for (i = 0; i < VFNT_MAPS; i++) {
232cbc8e155SToomas Soome boot_fb_font.vf_map[i] = bp->font->vf_map[i];
233cbc8e155SToomas Soome boot_fb_font.vf_map_count[i] = bp->font->vf_map_count[i];
234cbc8e155SToomas Soome }
235cbc8e155SToomas Soome
236cbc8e155SToomas Soome fb_info.font_width = boot_fb_font.vf_width;
237cbc8e155SToomas Soome fb_info.font_height = boot_fb_font.vf_height;
2388e6d016fSToomas Soome }
2398e6d016fSToomas Soome
2408e6d016fSToomas Soome /* fill framebuffer */
2418e6d016fSToomas Soome static void
boot_fb_fill(uint8_t * dst,uint32_t data,uint32_t len)2428e6d016fSToomas Soome boot_fb_fill(uint8_t *dst, uint32_t data, uint32_t len)
2438e6d016fSToomas Soome {
2448e6d016fSToomas Soome uint16_t *dst16;
2458e6d016fSToomas Soome uint32_t *dst32;
2468e6d016fSToomas Soome uint32_t i;
2478e6d016fSToomas Soome
2488e6d016fSToomas Soome switch (fb_info.depth) {
2498e6d016fSToomas Soome case 24:
2508e6d016fSToomas Soome case 8:
2518e6d016fSToomas Soome for (i = 0; i < len; i++)
2528e6d016fSToomas Soome dst[i] = (uint8_t)data;
2538e6d016fSToomas Soome break;
2548e6d016fSToomas Soome case 15:
2558e6d016fSToomas Soome case 16:
2568e6d016fSToomas Soome dst16 = (uint16_t *)dst;
2578e6d016fSToomas Soome len /= 2;
25829a77b73SToomas Soome for (i = 0; i < len; i++)
2598e6d016fSToomas Soome dst16[i] = (uint16_t)data;
2608e6d016fSToomas Soome break;
2618e6d016fSToomas Soome case 32:
2628e6d016fSToomas Soome dst32 = (uint32_t *)dst;
2638e6d016fSToomas Soome len /= 4;
26429a77b73SToomas Soome for (i = 0; i < len; i++)
2658e6d016fSToomas Soome dst32[i] = data;
2668e6d016fSToomas Soome break;
2678e6d016fSToomas Soome }
2688e6d016fSToomas Soome }
2698e6d016fSToomas Soome
2708e6d016fSToomas Soome /* copy data to framebuffer */
2718e6d016fSToomas Soome static void
boot_fb_cpy(uint8_t * dst,uint8_t * src,uint32_t len)2728e6d016fSToomas Soome boot_fb_cpy(uint8_t *dst, uint8_t *src, uint32_t len)
2738e6d016fSToomas Soome {
2748e6d016fSToomas Soome uint16_t *dst16, *src16;
2758e6d016fSToomas Soome uint32_t *dst32, *src32;
2768e6d016fSToomas Soome
2778e6d016fSToomas Soome switch (fb_info.depth) {
2788e6d016fSToomas Soome case 24:
2798e6d016fSToomas Soome case 8:
28029a77b73SToomas Soome default:
28129a77b73SToomas Soome if (dst <= src) {
28229a77b73SToomas Soome do {
28329a77b73SToomas Soome *dst++ = *src++;
28429a77b73SToomas Soome } while (--len != 0);
28529a77b73SToomas Soome } else {
28629a77b73SToomas Soome dst += len;
28729a77b73SToomas Soome src += len;
28829a77b73SToomas Soome do {
28929a77b73SToomas Soome *--dst = *--src;
29029a77b73SToomas Soome } while (--len != 0);
29129a77b73SToomas Soome }
2928e6d016fSToomas Soome break;
2938e6d016fSToomas Soome case 15:
2948e6d016fSToomas Soome case 16:
2958e6d016fSToomas Soome dst16 = (uint16_t *)dst;
2968e6d016fSToomas Soome src16 = (uint16_t *)src;
29729a77b73SToomas Soome len /= 2;
29829a77b73SToomas Soome if (dst16 <= src16) {
29929a77b73SToomas Soome do {
30029a77b73SToomas Soome *dst16++ = *src16++;
30129a77b73SToomas Soome } while (--len != 0);
30229a77b73SToomas Soome } else {
30329a77b73SToomas Soome dst16 += len;
30429a77b73SToomas Soome src16 += len;
30529a77b73SToomas Soome do {
30629a77b73SToomas Soome *--dst16 = *--src16;
30729a77b73SToomas Soome } while (--len != 0);
3088e6d016fSToomas Soome }
3098e6d016fSToomas Soome break;
3108e6d016fSToomas Soome case 32:
3118e6d016fSToomas Soome dst32 = (uint32_t *)dst;
3128e6d016fSToomas Soome src32 = (uint32_t *)src;
31329a77b73SToomas Soome len /= 4;
31429a77b73SToomas Soome if (dst32 <= src32) {
31529a77b73SToomas Soome do {
31629a77b73SToomas Soome *dst32++ = *src32++;
31729a77b73SToomas Soome } while (--len != 0);
31829a77b73SToomas Soome } else {
31929a77b73SToomas Soome dst32 += len;
32029a77b73SToomas Soome src32 += len;
32129a77b73SToomas Soome do {
32229a77b73SToomas Soome *--dst32 = *--src32;
32329a77b73SToomas Soome } while (--len != 0);
3248e6d016fSToomas Soome }
3258e6d016fSToomas Soome break;
3268e6d016fSToomas Soome }
3278e6d016fSToomas Soome }
3288e6d016fSToomas Soome
3298e6d016fSToomas Soome /*
3308e6d016fSToomas Soome * Allocate shadow frame buffer, called from fakebop.c when early boot
3318e6d016fSToomas Soome * allocator is ready.
3328e6d016fSToomas Soome */
3338e6d016fSToomas Soome void
boot_fb_shadow_init(bootops_t * bops)3348e6d016fSToomas Soome boot_fb_shadow_init(bootops_t *bops)
3358e6d016fSToomas Soome {
3368e6d016fSToomas Soome if (boot_console_type(NULL) != CONS_FRAMEBUFFER)
3378e6d016fSToomas Soome return; /* nothing to do */
3388e6d016fSToomas Soome
3398e6d016fSToomas Soome fb_info.shadow_fb = (uint8_t *)bops->bsys_alloc(NULL, NULL,
3408e6d016fSToomas Soome fb_info.fb_size, MMU_PAGESIZE);
3418e6d016fSToomas Soome
3428e6d016fSToomas Soome if (fb_info.shadow_fb == NULL)
3438e6d016fSToomas Soome return;
3448e6d016fSToomas Soome
3458e6d016fSToomas Soome /* Copy FB to shadow */
3468e6d016fSToomas Soome boot_fb_cpy(fb_info.shadow_fb, fb_info.fb, fb_info.fb_size);
3478e6d016fSToomas Soome }
3488e6d016fSToomas Soome
3498e6d016fSToomas Soome /*
3508e6d016fSToomas Soome * Translate ansi color based on inverses and brightness.
3518e6d016fSToomas Soome */
35229a77b73SToomas Soome void
boot_get_color(uint32_t * fg,uint32_t * bg)3538e6d016fSToomas Soome boot_get_color(uint32_t *fg, uint32_t *bg)
3548e6d016fSToomas Soome {
3558e6d016fSToomas Soome /* ansi to solaris colors, see also boot_console.c */
3568e6d016fSToomas Soome if (fb_info.inverse == B_TRUE ||
3578e6d016fSToomas Soome fb_info.inverse_screen == B_TRUE) {
358e0721d5aSToomas Soome if (fb_info.fg_color < XLATE_NCOLORS) {
359e0721d5aSToomas Soome /*
360e0721d5aSToomas Soome * white fg -> bright white bg
361e0721d5aSToomas Soome */
362e0721d5aSToomas Soome if (fb_info.fg_color == pc_white)
363e0721d5aSToomas Soome *bg = brt_xlate[fb_info.fg_color];
364e0721d5aSToomas Soome else
365e0721d5aSToomas Soome *bg = dim_xlate[fb_info.fg_color];
366e0721d5aSToomas Soome } else {
367a4e6b9b6SToomas Soome *bg = fb_info.fg_color;
368e0721d5aSToomas Soome }
369a4e6b9b6SToomas Soome
370e0721d5aSToomas Soome if (fb_info.bg_color < XLATE_NCOLORS) {
371e0721d5aSToomas Soome if (fb_info.bg_color == pc_white)
372e0721d5aSToomas Soome *fg = brt_xlate[fb_info.bg_color];
373e0721d5aSToomas Soome else
374e0721d5aSToomas Soome *fg = dim_xlate[fb_info.bg_color];
375e0721d5aSToomas Soome } else {
376a4e6b9b6SToomas Soome *fg = fb_info.bg_color;
377e0721d5aSToomas Soome }
3788e6d016fSToomas Soome } else {
379e0721d5aSToomas Soome if (fb_info.fg_color < XLATE_NCOLORS) {
380e0721d5aSToomas Soome if (fb_info.fg_color == pc_white)
381e0721d5aSToomas Soome *fg = brt_xlate[fb_info.fg_color];
382e0721d5aSToomas Soome else
383e0721d5aSToomas Soome *fg = dim_xlate[fb_info.fg_color];
384e0721d5aSToomas Soome } else {
385e0721d5aSToomas Soome *fg = fb_info.fg_color;
386e0721d5aSToomas Soome }
387e0721d5aSToomas Soome
388e0721d5aSToomas Soome if (fb_info.bg_color < XLATE_NCOLORS) {
389e0721d5aSToomas Soome if (fb_info.bg_color == pc_white)
390a4e6b9b6SToomas Soome *bg = brt_xlate[fb_info.bg_color];
391a4e6b9b6SToomas Soome else
392a4e6b9b6SToomas Soome *bg = dim_xlate[fb_info.bg_color];
393a4e6b9b6SToomas Soome } else {
394a4e6b9b6SToomas Soome *bg = fb_info.bg_color;
395a4e6b9b6SToomas Soome }
3968e6d016fSToomas Soome }
3978e6d016fSToomas Soome }
3988e6d016fSToomas Soome
3998e6d016fSToomas Soome /*
4008e6d016fSToomas Soome * Map indexed color to RGB value.
4018e6d016fSToomas Soome */
402a4e6b9b6SToomas Soome uint32_t
boot_color_map(uint8_t index)4038e6d016fSToomas Soome boot_color_map(uint8_t index)
4048e6d016fSToomas Soome {
405a4e6b9b6SToomas Soome if (fb_info.fb_type != FB_TYPE_RGB) {
406a4e6b9b6SToomas Soome if (index < nitems(solaris_color_to_pc_color))
407a4e6b9b6SToomas Soome return (solaris_color_to_pc_color[index]);
408a4e6b9b6SToomas Soome else
409a4e6b9b6SToomas Soome return (index);
410a4e6b9b6SToomas Soome }
4118e6d016fSToomas Soome
412*fa9eb222SToomas Soome return (rgb_color_map(&fb_info.rgb, index, 0));
4138e6d016fSToomas Soome }
4148e6d016fSToomas Soome
4158e6d016fSToomas Soome /* set up out simple console. */
4168e6d016fSToomas Soome /*ARGSUSED*/
4178e6d016fSToomas Soome void
boot_fb_init(int console)4188e6d016fSToomas Soome boot_fb_init(int console)
4198e6d016fSToomas Soome {
4208e6d016fSToomas Soome fb_info_pixel_coord_t window;
4218e6d016fSToomas Soome
4228e6d016fSToomas Soome /* frame buffer address is mapped in dboot. */
4238e6d016fSToomas Soome fb_info.fb = (uint8_t *)(uintptr_t)fb_info.paddr;
4248e6d016fSToomas Soome
4258e6d016fSToomas Soome boot_fb_set_font(fb_info.screen.y, fb_info.screen.x);
426cbc8e155SToomas Soome window.x = (fb_info.screen.x -
427cbc8e155SToomas Soome fb_info.terminal.x * boot_fb_font.vf_width) / 2;
428cbc8e155SToomas Soome window.y = (fb_info.screen.y -
429cbc8e155SToomas Soome fb_info.terminal.y * boot_fb_font.vf_height) / 2;
4308e6d016fSToomas Soome fb_info.terminal_origin.x = window.x;
4318e6d016fSToomas Soome fb_info.terminal_origin.y = window.y;
4328e6d016fSToomas Soome
4338e6d016fSToomas Soome #if defined(_BOOT)
4348e6d016fSToomas Soome /*
4358e6d016fSToomas Soome * Being called from dboot, we can have cursor terminal
4368e6d016fSToomas Soome * position passed from boot loader. In such case, fix the
4378e6d016fSToomas Soome * cursor screen coords.
4388e6d016fSToomas Soome */
4398e6d016fSToomas Soome if (fb_info.cursor.pos.x != 0 || fb_info.cursor.pos.y != 0) {
4408e6d016fSToomas Soome fb_info.cursor.origin.x = window.x +
441cbc8e155SToomas Soome fb_info.cursor.pos.x * boot_fb_font.vf_width;
4428e6d016fSToomas Soome fb_info.cursor.origin.y = window.y +
443cbc8e155SToomas Soome fb_info.cursor.pos.y * boot_fb_font.vf_height;
4448e6d016fSToomas Soome }
4458e6d016fSToomas Soome #endif
4468e6d016fSToomas Soome
4478e6d016fSToomas Soome /* If the cursor terminal position is 0,0 just reset screen coords */
4488e6d016fSToomas Soome if (fb_info.cursor.pos.x == 0 && fb_info.cursor.pos.y == 0) {
4498e6d016fSToomas Soome fb_info.cursor.origin.x = window.x;
4508e6d016fSToomas Soome fb_info.cursor.origin.y = window.y;
4518e6d016fSToomas Soome }
4528e6d016fSToomas Soome
4538e6d016fSToomas Soome /*
4548e6d016fSToomas Soome * Validate cursor coords with screen/terminal dimensions,
4558e6d016fSToomas Soome * if anything is off, reset to 0,0
4568e6d016fSToomas Soome */
4578e6d016fSToomas Soome if (fb_info.cursor.pos.x > fb_info.terminal.x ||
4588e6d016fSToomas Soome fb_info.cursor.pos.y > fb_info.terminal.y ||
4598e6d016fSToomas Soome fb_info.cursor.origin.x > fb_info.screen.x ||
4608e6d016fSToomas Soome fb_info.cursor.origin.y > fb_info.screen.y) {
4618e6d016fSToomas Soome
4628e6d016fSToomas Soome fb_info.cursor.origin.x = window.x;
4638e6d016fSToomas Soome fb_info.cursor.origin.y = window.y;
4648e6d016fSToomas Soome fb_info.cursor.pos.x = 0;
4658e6d016fSToomas Soome fb_info.cursor.pos.y = 0;
4668e6d016fSToomas Soome }
4678e6d016fSToomas Soome
4688e6d016fSToomas Soome #if defined(_BOOT)
4698e6d016fSToomas Soome /* clear the screen if cursor is set to 0,0 */
47029a77b73SToomas Soome if (fb_info.cursor.pos.x == 0 && fb_info.cursor.pos.y == 0) {
47129a77b73SToomas Soome uint32_t fg, bg, toffset;
47229a77b73SToomas Soome uint16_t y;
4738e6d016fSToomas Soome
4748e6d016fSToomas Soome boot_get_color(&fg, &bg);
4758e6d016fSToomas Soome bg = boot_color_map(bg);
4768e6d016fSToomas Soome
47729a77b73SToomas Soome toffset = 0;
47829a77b73SToomas Soome for (y = 0; y < fb_info.screen.y; y++) {
47929a77b73SToomas Soome uint8_t *dest = fb_info.fb + toffset;
48029a77b73SToomas Soome
4818e6d016fSToomas Soome boot_fb_fill(dest, bg, fb_info.pitch);
48229a77b73SToomas Soome toffset += fb_info.pitch;
4838e6d016fSToomas Soome }
4848e6d016fSToomas Soome }
4858e6d016fSToomas Soome #endif
4868e6d016fSToomas Soome }
4878e6d016fSToomas Soome
4888e6d016fSToomas Soome /* copy rectangle to framebuffer. */
4898e6d016fSToomas Soome static void
boot_fb_blit(struct vis_consdisplay * rect)4908e6d016fSToomas Soome boot_fb_blit(struct vis_consdisplay *rect)
4918e6d016fSToomas Soome {
49229a77b73SToomas Soome uint32_t offset, size; /* write size per scanline */
49329a77b73SToomas Soome uint8_t *fbp, *sfbp = NULL; /* fb + calculated offset */
4948e6d016fSToomas Soome int i;
4958e6d016fSToomas Soome
4968e6d016fSToomas Soome /* make sure we will not write past FB */
4978e6d016fSToomas Soome if (rect->col >= fb_info.screen.x ||
4988e6d016fSToomas Soome rect->row >= fb_info.screen.y ||
4998e6d016fSToomas Soome rect->col + rect->width >= fb_info.screen.x ||
5008e6d016fSToomas Soome rect->row + rect->height >= fb_info.screen.y)
5018e6d016fSToomas Soome return;
5028e6d016fSToomas Soome
5038e6d016fSToomas Soome size = rect->width * fb_info.bpp;
50429a77b73SToomas Soome offset = rect->col * fb_info.bpp + rect->row * fb_info.pitch;
50529a77b73SToomas Soome fbp = fb_info.fb + offset;
50629a77b73SToomas Soome if (fb_info.shadow_fb != NULL)
50729a77b73SToomas Soome sfbp = fb_info.shadow_fb + offset;
5088e6d016fSToomas Soome
5098e6d016fSToomas Soome /* write all scanlines in rectangle */
5108e6d016fSToomas Soome for (i = 0; i < rect->height; i++) {
5118e6d016fSToomas Soome uint8_t *dest = fbp + i * fb_info.pitch;
5128e6d016fSToomas Soome uint8_t *src = rect->data + i * size;
5138e6d016fSToomas Soome boot_fb_cpy(dest, src, size);
5148e6d016fSToomas Soome if (sfbp != NULL) {
5158e6d016fSToomas Soome dest = sfbp + i * fb_info.pitch;
5168e6d016fSToomas Soome boot_fb_cpy(dest, src, size);
5178e6d016fSToomas Soome }
5188e6d016fSToomas Soome }
5198e6d016fSToomas Soome }
5208e6d016fSToomas Soome
5218e6d016fSToomas Soome static void
bit_to_pix(uchar_t c)5228e6d016fSToomas Soome bit_to_pix(uchar_t c)
5238e6d016fSToomas Soome {
5248e6d016fSToomas Soome uint32_t fg, bg;
5258e6d016fSToomas Soome
5268e6d016fSToomas Soome boot_get_color(&fg, &bg);
5278e6d016fSToomas Soome fg = boot_color_map(fg);
5288e6d016fSToomas Soome bg = boot_color_map(bg);
5298e6d016fSToomas Soome
5308e6d016fSToomas Soome switch (fb_info.depth) {
5318e6d016fSToomas Soome case 8:
5328e6d016fSToomas Soome font_bit_to_pix8(&boot_fb_font, (uint8_t *)glyph, c, fg, bg);
5338e6d016fSToomas Soome break;
5348e6d016fSToomas Soome case 15:
5358e6d016fSToomas Soome case 16:
5368e6d016fSToomas Soome font_bit_to_pix16(&boot_fb_font, (uint16_t *)glyph, c,
5378e6d016fSToomas Soome (uint16_t)fg, (uint16_t)bg);
5388e6d016fSToomas Soome break;
5398e6d016fSToomas Soome case 24:
5408e6d016fSToomas Soome font_bit_to_pix24(&boot_fb_font, (uint8_t *)glyph, c, fg, bg);
5418e6d016fSToomas Soome break;
5428e6d016fSToomas Soome case 32:
5438e6d016fSToomas Soome font_bit_to_pix32(&boot_fb_font, (uint32_t *)glyph, c, fg, bg);
5448e6d016fSToomas Soome break;
5458e6d016fSToomas Soome }
5468e6d016fSToomas Soome }
5478e6d016fSToomas Soome
5488e6d016fSToomas Soome static void
boot_fb_eraseline_impl(uint16_t x,uint16_t y)54929a77b73SToomas Soome boot_fb_eraseline_impl(uint16_t x, uint16_t y)
5508e6d016fSToomas Soome {
55129a77b73SToomas Soome uint32_t toffset, size;
5528e6d016fSToomas Soome uint32_t fg, bg;
55329a77b73SToomas Soome uint8_t *dst, *sdst;
5548e6d016fSToomas Soome int i;
5558e6d016fSToomas Soome
5568e6d016fSToomas Soome boot_get_color(&fg, &bg);
5578e6d016fSToomas Soome bg = boot_color_map(bg);
5588e6d016fSToomas Soome
559cbc8e155SToomas Soome size = fb_info.terminal.x * boot_fb_font.vf_width * fb_info.bpp;
56029a77b73SToomas Soome
56129a77b73SToomas Soome toffset = x * fb_info.bpp + y * fb_info.pitch;
56229a77b73SToomas Soome dst = fb_info.fb + toffset;
563a6f5e66aSToomas Soome sdst = fb_info.shadow_fb + toffset;
56429a77b73SToomas Soome
565cbc8e155SToomas Soome for (i = 0; i < boot_fb_font.vf_height; i++) {
56629a77b73SToomas Soome uint8_t *dest = dst + i * fb_info.pitch;
56729a77b73SToomas Soome if (fb_info.fb + fb_info.fb_size >= dest + size)
56829a77b73SToomas Soome boot_fb_fill(dest, bg, size);
56929a77b73SToomas Soome if (fb_info.shadow_fb != NULL) {
57029a77b73SToomas Soome dest = sdst + i * fb_info.pitch;
57129a77b73SToomas Soome if (fb_info.shadow_fb + fb_info.fb_size >=
57229a77b73SToomas Soome dest + size) {
57329a77b73SToomas Soome boot_fb_fill(dest, bg, size);
57429a77b73SToomas Soome }
57529a77b73SToomas Soome }
57629a77b73SToomas Soome }
57729a77b73SToomas Soome }
57829a77b73SToomas Soome
57929a77b73SToomas Soome static void
boot_fb_eraseline(void)58029a77b73SToomas Soome boot_fb_eraseline(void)
58129a77b73SToomas Soome {
58229a77b73SToomas Soome boot_fb_eraseline_impl(fb_info.cursor.origin.x,
58329a77b73SToomas Soome fb_info.cursor.origin.y);
58429a77b73SToomas Soome }
58529a77b73SToomas Soome
58629a77b73SToomas Soome /*
58729a77b73SToomas Soome * Copy rectangle from console to console.
58829a77b73SToomas Soome * If shadow buffer is available, use shadow as source.
58929a77b73SToomas Soome */
59029a77b73SToomas Soome static void
boot_fb_conscopy(struct vis_conscopy * c_copy)59129a77b73SToomas Soome boot_fb_conscopy(struct vis_conscopy *c_copy)
59229a77b73SToomas Soome {
59329a77b73SToomas Soome uint32_t soffset, toffset;
59429a77b73SToomas Soome uint32_t width, height, increment;
59529a77b73SToomas Soome uint8_t *src, *dst, *sdst = NULL;
59629a77b73SToomas Soome int i;
59729a77b73SToomas Soome
59829a77b73SToomas Soome soffset = c_copy->s_col * fb_info.bpp + c_copy->s_row * fb_info.pitch;
59929a77b73SToomas Soome toffset = c_copy->t_col * fb_info.bpp + c_copy->t_row * fb_info.pitch;
60029a77b73SToomas Soome
60129a77b73SToomas Soome src = fb_info.fb + soffset;
60229a77b73SToomas Soome dst = fb_info.fb + toffset;
6038e6d016fSToomas Soome
6048e6d016fSToomas Soome if (fb_info.shadow_fb != NULL) {
6058e6d016fSToomas Soome src = fb_info.shadow_fb + soffset;
6068e6d016fSToomas Soome sdst = fb_info.shadow_fb + toffset;
6078e6d016fSToomas Soome }
6088e6d016fSToomas Soome
60929a77b73SToomas Soome width = (c_copy->e_col - c_copy->s_col + 1) * fb_info.bpp;
61029a77b73SToomas Soome height = c_copy->e_row - c_copy->s_row + 1;
61129a77b73SToomas Soome
6128e6d016fSToomas Soome for (i = 0; i < height; i++) {
61329a77b73SToomas Soome increment = i * fb_info.pitch;
61429a77b73SToomas Soome
61529a77b73SToomas Soome /* Make sure we fit into FB size. */
61629a77b73SToomas Soome if (soffset + increment + width >= fb_info.fb_size ||
61729a77b73SToomas Soome toffset + increment + width >= fb_info.fb_size)
61829a77b73SToomas Soome break;
61929a77b73SToomas Soome
6208e6d016fSToomas Soome boot_fb_cpy(dst + increment, src + increment, width);
62129a77b73SToomas Soome
6228e6d016fSToomas Soome if (sdst != NULL)
6238e6d016fSToomas Soome boot_fb_cpy(sdst + increment, src + increment, width);
6248e6d016fSToomas Soome }
62529a77b73SToomas Soome }
6268e6d016fSToomas Soome
62729a77b73SToomas Soome /* Shift the line content by chars. */
62829a77b73SToomas Soome static void
boot_fb_shiftline(int chars)62929a77b73SToomas Soome boot_fb_shiftline(int chars)
63029a77b73SToomas Soome {
63129a77b73SToomas Soome struct vis_conscopy c_copy;
6328e6d016fSToomas Soome
63329a77b73SToomas Soome c_copy.s_col = fb_info.cursor.origin.x;
63429a77b73SToomas Soome c_copy.s_row = fb_info.cursor.origin.y;
63529a77b73SToomas Soome
636cbc8e155SToomas Soome c_copy.e_col = (fb_info.terminal.x - chars) * boot_fb_font.vf_width;
63729a77b73SToomas Soome c_copy.e_col += fb_info.terminal_origin.x;
638cbc8e155SToomas Soome c_copy.e_row = c_copy.s_row + boot_fb_font.vf_height;
63929a77b73SToomas Soome
640cbc8e155SToomas Soome c_copy.t_col = fb_info.cursor.origin.x + chars * boot_fb_font.vf_width;
64129a77b73SToomas Soome c_copy.t_row = fb_info.cursor.origin.y;
64229a77b73SToomas Soome
64329a77b73SToomas Soome boot_fb_conscopy(&c_copy);
64429a77b73SToomas Soome }
64529a77b73SToomas Soome
64629a77b73SToomas Soome /*
64729a77b73SToomas Soome * move the terminal window lines [1..y] to [0..y-1] and clear last line.
64829a77b73SToomas Soome */
64929a77b73SToomas Soome static void
boot_fb_scroll(void)65029a77b73SToomas Soome boot_fb_scroll(void)
65129a77b73SToomas Soome {
65229a77b73SToomas Soome struct vis_conscopy c_copy;
65329a77b73SToomas Soome
65429a77b73SToomas Soome /* support for scrolling. set up the console copy data and last line */
655cbc8e155SToomas Soome c_copy.s_row = fb_info.terminal_origin.y + boot_fb_font.vf_height;
65629a77b73SToomas Soome c_copy.s_col = fb_info.terminal_origin.x;
65729a77b73SToomas Soome c_copy.e_row = fb_info.screen.y - fb_info.terminal_origin.y;
65829a77b73SToomas Soome c_copy.e_col = fb_info.screen.x - fb_info.terminal_origin.x;
65929a77b73SToomas Soome c_copy.t_row = fb_info.terminal_origin.y;
66029a77b73SToomas Soome c_copy.t_col = fb_info.terminal_origin.x;
66129a77b73SToomas Soome
66229a77b73SToomas Soome boot_fb_conscopy(&c_copy);
66329a77b73SToomas Soome
66429a77b73SToomas Soome /* now clean up the last line */
66529a77b73SToomas Soome boot_fb_eraseline_impl(fb_info.terminal_origin.x,
66629a77b73SToomas Soome fb_info.terminal_origin.y +
667cbc8e155SToomas Soome (fb_info.terminal.y - 1) * boot_fb_font.vf_height);
6688e6d016fSToomas Soome }
6698e6d016fSToomas Soome
6708e6d016fSToomas Soome /*
6718e6d016fSToomas Soome * Very simple block cursor. Save space below the cursor and restore
6728e6d016fSToomas Soome * when cursor is invisible.
6738e6d016fSToomas Soome */
6748e6d016fSToomas Soome void
boot_fb_cursor(boolean_t visible)6758e6d016fSToomas Soome boot_fb_cursor(boolean_t visible)
6768e6d016fSToomas Soome {
677cbc8e155SToomas Soome uint32_t offset, size, j;
6788e6d016fSToomas Soome uint32_t *fb32, *sfb32 = NULL;
6798e6d016fSToomas Soome uint32_t fg, bg;
6808e6d016fSToomas Soome uint16_t *fb16, *sfb16 = NULL;
6818e6d016fSToomas Soome uint8_t *fb8, *sfb8 = NULL;
6828e6d016fSToomas Soome int i, pitch;
6838e6d016fSToomas Soome
6848e6d016fSToomas Soome if (fb_info.cursor.visible == visible)
6858e6d016fSToomas Soome return;
6868e6d016fSToomas Soome
6878e6d016fSToomas Soome boot_get_color(&fg, &bg);
6888e6d016fSToomas Soome fg = boot_color_map(fg);
6898e6d016fSToomas Soome bg = boot_color_map(bg);
6908e6d016fSToomas Soome
6918e6d016fSToomas Soome fb_info.cursor.visible = visible;
6928e6d016fSToomas Soome pitch = fb_info.pitch;
693cbc8e155SToomas Soome size = boot_fb_font.vf_width * fb_info.bpp;
6948e6d016fSToomas Soome
6958e6d016fSToomas Soome /*
6968e6d016fSToomas Soome * Build cursor image. We are building mirror image of data on
6978e6d016fSToomas Soome * frame buffer by (D xor FG) xor BG.
6988e6d016fSToomas Soome */
6998e6d016fSToomas Soome offset = fb_info.cursor.origin.x * fb_info.bpp +
7008e6d016fSToomas Soome fb_info.cursor.origin.y * pitch;
7018e6d016fSToomas Soome switch (fb_info.depth) {
7028e6d016fSToomas Soome case 8:
703cbc8e155SToomas Soome for (i = 0; i < boot_fb_font.vf_height; i++) {
7048e6d016fSToomas Soome fb8 = fb_info.fb + offset + i * pitch;
7058e6d016fSToomas Soome if (fb_info.shadow_fb != NULL)
7068e6d016fSToomas Soome sfb8 = fb_info.shadow_fb + offset + i * pitch;
707cbc8e155SToomas Soome for (j = 0; j < size; j += 1) {
7088e6d016fSToomas Soome fb8[j] = (fb8[j] ^ (fg & 0xff)) ^ (bg & 0xff);
7098e6d016fSToomas Soome
7108e6d016fSToomas Soome if (sfb8 == NULL)
7118e6d016fSToomas Soome continue;
7128e6d016fSToomas Soome
7138e6d016fSToomas Soome sfb8[j] = (sfb8[j] ^ (fg & 0xff)) ^ (bg & 0xff);
7148e6d016fSToomas Soome }
7158e6d016fSToomas Soome }
7168e6d016fSToomas Soome break;
7178e6d016fSToomas Soome case 15:
7188e6d016fSToomas Soome case 16:
719cbc8e155SToomas Soome for (i = 0; i < boot_fb_font.vf_height; i++) {
7208e6d016fSToomas Soome fb16 = (uint16_t *)(fb_info.fb + offset + i * pitch);
7218e6d016fSToomas Soome if (fb_info.shadow_fb != NULL)
7228e6d016fSToomas Soome sfb16 = (uint16_t *)
7238e6d016fSToomas Soome (fb_info.shadow_fb + offset + i * pitch);
724cbc8e155SToomas Soome for (j = 0; j < boot_fb_font.vf_width; j++) {
7258e6d016fSToomas Soome fb16[j] = (fb16[j] ^ (fg & 0xffff)) ^
7268e6d016fSToomas Soome (bg & 0xffff);
7278e6d016fSToomas Soome
7288e6d016fSToomas Soome if (sfb16 == NULL)
7298e6d016fSToomas Soome continue;
7308e6d016fSToomas Soome
7318e6d016fSToomas Soome sfb16[j] = (sfb16[j] ^ (fg & 0xffff)) ^
7328e6d016fSToomas Soome (bg & 0xffff);
7338e6d016fSToomas Soome }
7348e6d016fSToomas Soome }
7358e6d016fSToomas Soome break;
7368e6d016fSToomas Soome case 24:
737cbc8e155SToomas Soome for (i = 0; i < boot_fb_font.vf_height; i++) {
7388e6d016fSToomas Soome fb8 = fb_info.fb + offset + i * pitch;
7398e6d016fSToomas Soome if (fb_info.shadow_fb != NULL)
7408e6d016fSToomas Soome sfb8 = fb_info.shadow_fb + offset + i * pitch;
741cbc8e155SToomas Soome for (j = 0; j < size; j += 3) {
7428e6d016fSToomas Soome fb8[j] = (fb8[j] ^ ((fg >> 16) & 0xff)) ^
7438e6d016fSToomas Soome ((bg >> 16) & 0xff);
7448e6d016fSToomas Soome fb8[j+1] = (fb8[j+1] ^ ((fg >> 8) & 0xff)) ^
7458e6d016fSToomas Soome ((bg >> 8) & 0xff);
7468e6d016fSToomas Soome fb8[j+2] = (fb8[j+2] ^ (fg & 0xff)) ^
7478e6d016fSToomas Soome (bg & 0xff);
7488e6d016fSToomas Soome
7498e6d016fSToomas Soome if (sfb8 == NULL)
7508e6d016fSToomas Soome continue;
7518e6d016fSToomas Soome
7528e6d016fSToomas Soome sfb8[j] = (sfb8[j] ^ ((fg >> 16) & 0xff)) ^
7538e6d016fSToomas Soome ((bg >> 16) & 0xff);
7548e6d016fSToomas Soome sfb8[j+1] = (sfb8[j+1] ^ ((fg >> 8) & 0xff)) ^
7558e6d016fSToomas Soome ((bg >> 8) & 0xff);
7568e6d016fSToomas Soome sfb8[j+2] = (sfb8[j+2] ^ (fg & 0xff)) ^
7578e6d016fSToomas Soome (bg & 0xff);
7588e6d016fSToomas Soome }
7598e6d016fSToomas Soome }
7608e6d016fSToomas Soome break;
7618e6d016fSToomas Soome case 32:
762cbc8e155SToomas Soome for (i = 0; i < boot_fb_font.vf_height; i++) {
7638e6d016fSToomas Soome fb32 = (uint32_t *)(fb_info.fb + offset + i * pitch);
7648e6d016fSToomas Soome if (fb_info.shadow_fb != NULL) {
7658e6d016fSToomas Soome sfb32 = (uint32_t *)
7668e6d016fSToomas Soome (fb_info.shadow_fb + offset + i * pitch);
7678e6d016fSToomas Soome }
768cbc8e155SToomas Soome for (j = 0; j < boot_fb_font.vf_width; j++) {
7698e6d016fSToomas Soome fb32[j] = (fb32[j] ^ fg) ^ bg;
7708e6d016fSToomas Soome
7718e6d016fSToomas Soome if (sfb32 == NULL)
7728e6d016fSToomas Soome continue;
7738e6d016fSToomas Soome
7748e6d016fSToomas Soome sfb32[j] = (sfb32[j] ^ fg) ^ bg;
7758e6d016fSToomas Soome }
7768e6d016fSToomas Soome }
7778e6d016fSToomas Soome break;
7788e6d016fSToomas Soome }
7798e6d016fSToomas Soome }
7808e6d016fSToomas Soome
7818e6d016fSToomas Soome static void
boot_fb_setpos(int row,int col)78229a77b73SToomas Soome boot_fb_setpos(int row, int col)
7838e6d016fSToomas Soome {
78429a77b73SToomas Soome if (row < 0)
78529a77b73SToomas Soome row = 0;
78629a77b73SToomas Soome if (row >= fb_info.terminal.y)
78729a77b73SToomas Soome row = fb_info.terminal.y - 1;
78829a77b73SToomas Soome if (col < 0)
78929a77b73SToomas Soome col = 0;
79029a77b73SToomas Soome if (col >= fb_info.terminal.x)
79129a77b73SToomas Soome col = fb_info.terminal.x - 1;
79229a77b73SToomas Soome
79329a77b73SToomas Soome fb_info.cursor.pos.x = col;
79429a77b73SToomas Soome fb_info.cursor.pos.y = row;
7958e6d016fSToomas Soome fb_info.cursor.origin.x = fb_info.terminal_origin.x;
796cbc8e155SToomas Soome fb_info.cursor.origin.x += col * boot_fb_font.vf_width;
79729a77b73SToomas Soome fb_info.cursor.origin.y = fb_info.terminal_origin.y;
798cbc8e155SToomas Soome fb_info.cursor.origin.y += row * boot_fb_font.vf_height;
7998e6d016fSToomas Soome }
8008e6d016fSToomas Soome
8018e6d016fSToomas Soome static void
boot_fb_putchar(int c)80229a77b73SToomas Soome boot_fb_putchar(int c)
8038e6d016fSToomas Soome {
8048e6d016fSToomas Soome struct vis_consdisplay display;
80529a77b73SToomas Soome int rows, cols;
80629a77b73SToomas Soome
80729a77b73SToomas Soome rows = fb_info.cursor.pos.y;
80829a77b73SToomas Soome cols = fb_info.cursor.pos.x;
80929a77b73SToomas Soome
81029a77b73SToomas Soome if (c == '\n') {
81129a77b73SToomas Soome if (rows < fb_info.terminal.y - 1)
81229a77b73SToomas Soome boot_fb_setpos(rows + 1, cols);
81329a77b73SToomas Soome else
81429a77b73SToomas Soome boot_fb_scroll();
8158e6d016fSToomas Soome return;
8168e6d016fSToomas Soome }
8178e6d016fSToomas Soome
8188e6d016fSToomas Soome bit_to_pix(c);
8198e6d016fSToomas Soome display.col = fb_info.cursor.origin.x;
8208e6d016fSToomas Soome display.row = fb_info.cursor.origin.y;
821cbc8e155SToomas Soome display.width = boot_fb_font.vf_width;
822cbc8e155SToomas Soome display.height = boot_fb_font.vf_height;
8238e6d016fSToomas Soome display.data = glyph;
8248e6d016fSToomas Soome
8258e6d016fSToomas Soome boot_fb_blit(&display);
82629a77b73SToomas Soome if (cols < fb_info.terminal.x - 1)
82729a77b73SToomas Soome boot_fb_setpos(rows, cols + 1);
82829a77b73SToomas Soome else if (rows < fb_info.terminal.y - 1)
82929a77b73SToomas Soome boot_fb_setpos(rows + 1, 0);
83029a77b73SToomas Soome else {
83129a77b73SToomas Soome boot_fb_setpos(rows, 0);
83229a77b73SToomas Soome boot_fb_scroll();
83329a77b73SToomas Soome }
8348e6d016fSToomas Soome }
835