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 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 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 161*b70e9485SToomas 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; 2098e6d016fSToomas Soome 2108e6d016fSToomas Soome return (B_TRUE); 2118e6d016fSToomas Soome } 2128e6d016fSToomas Soome 2138e6d016fSToomas Soome /* set font and pass the data to fb_info */ 2148e6d016fSToomas Soome static void 2158e6d016fSToomas Soome boot_fb_set_font(uint16_t height, uint16_t width) 2168e6d016fSToomas Soome { 2178e6d016fSToomas Soome short h, w; 218cbc8e155SToomas Soome bitmap_data_t *bp; 219cbc8e155SToomas Soome int i; 2208e6d016fSToomas Soome 2218e6d016fSToomas Soome h = MIN(height, 4096); 2228e6d016fSToomas Soome w = MIN(width, 4096); 2238e6d016fSToomas Soome 224cbc8e155SToomas Soome bp = set_font((short *)&fb_info.terminal.y, 2258e6d016fSToomas Soome (short *)&fb_info.terminal.x, h, w); 226cbc8e155SToomas Soome 227cbc8e155SToomas Soome boot_fb_font.vf_bytes = bp->font->vf_bytes; 228cbc8e155SToomas Soome boot_fb_font.vf_width = bp->font->vf_width; 229cbc8e155SToomas Soome boot_fb_font.vf_height = bp->font->vf_height; 230cbc8e155SToomas Soome for (i = 0; i < VFNT_MAPS; i++) { 231cbc8e155SToomas Soome boot_fb_font.vf_map[i] = bp->font->vf_map[i]; 232cbc8e155SToomas Soome boot_fb_font.vf_map_count[i] = bp->font->vf_map_count[i]; 233cbc8e155SToomas Soome } 234cbc8e155SToomas Soome 235cbc8e155SToomas Soome fb_info.font_width = boot_fb_font.vf_width; 236cbc8e155SToomas Soome fb_info.font_height = boot_fb_font.vf_height; 2378e6d016fSToomas Soome } 2388e6d016fSToomas Soome 2398e6d016fSToomas Soome /* fill framebuffer */ 2408e6d016fSToomas Soome static void 2418e6d016fSToomas Soome boot_fb_fill(uint8_t *dst, uint32_t data, uint32_t len) 2428e6d016fSToomas Soome { 2438e6d016fSToomas Soome uint16_t *dst16; 2448e6d016fSToomas Soome uint32_t *dst32; 2458e6d016fSToomas Soome uint32_t i; 2468e6d016fSToomas Soome 2478e6d016fSToomas Soome switch (fb_info.depth) { 2488e6d016fSToomas Soome case 24: 2498e6d016fSToomas Soome case 8: 2508e6d016fSToomas Soome for (i = 0; i < len; i++) 2518e6d016fSToomas Soome dst[i] = (uint8_t)data; 2528e6d016fSToomas Soome break; 2538e6d016fSToomas Soome case 15: 2548e6d016fSToomas Soome case 16: 2558e6d016fSToomas Soome dst16 = (uint16_t *)dst; 2568e6d016fSToomas Soome len /= 2; 25729a77b73SToomas Soome for (i = 0; i < len; i++) 2588e6d016fSToomas Soome dst16[i] = (uint16_t)data; 2598e6d016fSToomas Soome break; 2608e6d016fSToomas Soome case 32: 2618e6d016fSToomas Soome dst32 = (uint32_t *)dst; 2628e6d016fSToomas Soome len /= 4; 26329a77b73SToomas Soome for (i = 0; i < len; i++) 2648e6d016fSToomas Soome dst32[i] = data; 2658e6d016fSToomas Soome break; 2668e6d016fSToomas Soome } 2678e6d016fSToomas Soome } 2688e6d016fSToomas Soome 2698e6d016fSToomas Soome /* copy data to framebuffer */ 2708e6d016fSToomas Soome static void 2718e6d016fSToomas Soome boot_fb_cpy(uint8_t *dst, uint8_t *src, uint32_t len) 2728e6d016fSToomas Soome { 2738e6d016fSToomas Soome uint16_t *dst16, *src16; 2748e6d016fSToomas Soome uint32_t *dst32, *src32; 2758e6d016fSToomas Soome 2768e6d016fSToomas Soome switch (fb_info.depth) { 2778e6d016fSToomas Soome case 24: 2788e6d016fSToomas Soome case 8: 27929a77b73SToomas Soome default: 28029a77b73SToomas Soome if (dst <= src) { 28129a77b73SToomas Soome do { 28229a77b73SToomas Soome *dst++ = *src++; 28329a77b73SToomas Soome } while (--len != 0); 28429a77b73SToomas Soome } else { 28529a77b73SToomas Soome dst += len; 28629a77b73SToomas Soome src += len; 28729a77b73SToomas Soome do { 28829a77b73SToomas Soome *--dst = *--src; 28929a77b73SToomas Soome } while (--len != 0); 29029a77b73SToomas Soome } 2918e6d016fSToomas Soome break; 2928e6d016fSToomas Soome case 15: 2938e6d016fSToomas Soome case 16: 2948e6d016fSToomas Soome dst16 = (uint16_t *)dst; 2958e6d016fSToomas Soome src16 = (uint16_t *)src; 29629a77b73SToomas Soome len /= 2; 29729a77b73SToomas Soome if (dst16 <= src16) { 29829a77b73SToomas Soome do { 29929a77b73SToomas Soome *dst16++ = *src16++; 30029a77b73SToomas Soome } while (--len != 0); 30129a77b73SToomas Soome } else { 30229a77b73SToomas Soome dst16 += len; 30329a77b73SToomas Soome src16 += len; 30429a77b73SToomas Soome do { 30529a77b73SToomas Soome *--dst16 = *--src16; 30629a77b73SToomas Soome } while (--len != 0); 3078e6d016fSToomas Soome } 3088e6d016fSToomas Soome break; 3098e6d016fSToomas Soome case 32: 3108e6d016fSToomas Soome dst32 = (uint32_t *)dst; 3118e6d016fSToomas Soome src32 = (uint32_t *)src; 31229a77b73SToomas Soome len /= 4; 31329a77b73SToomas Soome if (dst32 <= src32) { 31429a77b73SToomas Soome do { 31529a77b73SToomas Soome *dst32++ = *src32++; 31629a77b73SToomas Soome } while (--len != 0); 31729a77b73SToomas Soome } else { 31829a77b73SToomas Soome dst32 += len; 31929a77b73SToomas Soome src32 += len; 32029a77b73SToomas Soome do { 32129a77b73SToomas Soome *--dst32 = *--src32; 32229a77b73SToomas Soome } while (--len != 0); 3238e6d016fSToomas Soome } 3248e6d016fSToomas Soome break; 3258e6d016fSToomas Soome } 3268e6d016fSToomas Soome } 3278e6d016fSToomas Soome 3288e6d016fSToomas Soome /* 3298e6d016fSToomas Soome * Allocate shadow frame buffer, called from fakebop.c when early boot 3308e6d016fSToomas Soome * allocator is ready. 3318e6d016fSToomas Soome */ 3328e6d016fSToomas Soome void 3338e6d016fSToomas Soome boot_fb_shadow_init(bootops_t *bops) 3348e6d016fSToomas Soome { 3358e6d016fSToomas Soome if (boot_console_type(NULL) != CONS_FRAMEBUFFER) 3368e6d016fSToomas Soome return; /* nothing to do */ 3378e6d016fSToomas Soome 3388e6d016fSToomas Soome fb_info.shadow_fb = (uint8_t *)bops->bsys_alloc(NULL, NULL, 3398e6d016fSToomas Soome fb_info.fb_size, MMU_PAGESIZE); 3408e6d016fSToomas Soome 3418e6d016fSToomas Soome if (fb_info.shadow_fb == NULL) 3428e6d016fSToomas Soome return; 3438e6d016fSToomas Soome 3448e6d016fSToomas Soome /* Copy FB to shadow */ 3458e6d016fSToomas Soome boot_fb_cpy(fb_info.shadow_fb, fb_info.fb, fb_info.fb_size); 3468e6d016fSToomas Soome } 3478e6d016fSToomas Soome 3488e6d016fSToomas Soome /* 3498e6d016fSToomas Soome * Translate ansi color based on inverses and brightness. 3508e6d016fSToomas Soome */ 35129a77b73SToomas Soome void 3528e6d016fSToomas Soome boot_get_color(uint32_t *fg, uint32_t *bg) 3538e6d016fSToomas Soome { 3548e6d016fSToomas Soome /* ansi to solaris colors, see also boot_console.c */ 3558e6d016fSToomas Soome if (fb_info.inverse == B_TRUE || 3568e6d016fSToomas Soome fb_info.inverse_screen == B_TRUE) { 357a4e6b9b6SToomas Soome if (fb_info.fg_color < 16) 358a4e6b9b6SToomas Soome *bg = dim_xlate[fb_info.fg_color]; 359a4e6b9b6SToomas Soome else 360a4e6b9b6SToomas Soome *bg = fb_info.fg_color; 361a4e6b9b6SToomas Soome 362a4e6b9b6SToomas Soome if (fb_info.bg_color < 16) 363a4e6b9b6SToomas Soome *fg = brt_xlate[fb_info.bg_color]; 364a4e6b9b6SToomas Soome else 365a4e6b9b6SToomas Soome *fg = fb_info.bg_color; 3668e6d016fSToomas Soome } else { 367a4e6b9b6SToomas Soome if (fb_info.bg_color < 16) { 368a4e6b9b6SToomas Soome if (fb_info.bg_color == 7) 369a4e6b9b6SToomas Soome *bg = brt_xlate[fb_info.bg_color]; 370a4e6b9b6SToomas Soome else 371a4e6b9b6SToomas Soome *bg = dim_xlate[fb_info.bg_color]; 372a4e6b9b6SToomas Soome } else { 373a4e6b9b6SToomas Soome *bg = fb_info.bg_color; 374a4e6b9b6SToomas Soome } 375a4e6b9b6SToomas Soome if (fb_info.fg_color < 16) 376a4e6b9b6SToomas Soome *fg = dim_xlate[fb_info.fg_color]; 3778e6d016fSToomas Soome else 378a4e6b9b6SToomas Soome *fg = fb_info.fg_color; 3798e6d016fSToomas Soome } 3808e6d016fSToomas Soome } 3818e6d016fSToomas Soome 3828e6d016fSToomas Soome /* 3838e6d016fSToomas Soome * Map indexed color to RGB value. 3848e6d016fSToomas Soome */ 385a4e6b9b6SToomas Soome uint32_t 3868e6d016fSToomas Soome boot_color_map(uint8_t index) 3878e6d016fSToomas Soome { 388a4e6b9b6SToomas Soome if (fb_info.fb_type != FB_TYPE_RGB) { 389a4e6b9b6SToomas Soome if (index < nitems(solaris_color_to_pc_color)) 390a4e6b9b6SToomas Soome return (solaris_color_to_pc_color[index]); 391a4e6b9b6SToomas Soome else 392a4e6b9b6SToomas Soome return (index); 393a4e6b9b6SToomas Soome } 3948e6d016fSToomas Soome 395a4e6b9b6SToomas Soome return (rgb_color_map(&fb_info.rgb, index)); 3968e6d016fSToomas Soome } 3978e6d016fSToomas Soome 3988e6d016fSToomas Soome /* set up out simple console. */ 3998e6d016fSToomas Soome /*ARGSUSED*/ 4008e6d016fSToomas Soome void 4018e6d016fSToomas Soome boot_fb_init(int console) 4028e6d016fSToomas Soome { 4038e6d016fSToomas Soome fb_info_pixel_coord_t window; 4048e6d016fSToomas Soome 4058e6d016fSToomas Soome /* frame buffer address is mapped in dboot. */ 4068e6d016fSToomas Soome fb_info.fb = (uint8_t *)(uintptr_t)fb_info.paddr; 4078e6d016fSToomas Soome 4088e6d016fSToomas Soome boot_fb_set_font(fb_info.screen.y, fb_info.screen.x); 409cbc8e155SToomas Soome window.x = (fb_info.screen.x - 410cbc8e155SToomas Soome fb_info.terminal.x * boot_fb_font.vf_width) / 2; 411cbc8e155SToomas Soome window.y = (fb_info.screen.y - 412cbc8e155SToomas Soome fb_info.terminal.y * boot_fb_font.vf_height) / 2; 4138e6d016fSToomas Soome fb_info.terminal_origin.x = window.x; 4148e6d016fSToomas Soome fb_info.terminal_origin.y = window.y; 4158e6d016fSToomas Soome 4168e6d016fSToomas Soome #if defined(_BOOT) 4178e6d016fSToomas Soome /* 4188e6d016fSToomas Soome * Being called from dboot, we can have cursor terminal 4198e6d016fSToomas Soome * position passed from boot loader. In such case, fix the 4208e6d016fSToomas Soome * cursor screen coords. 4218e6d016fSToomas Soome */ 4228e6d016fSToomas Soome if (fb_info.cursor.pos.x != 0 || fb_info.cursor.pos.y != 0) { 4238e6d016fSToomas Soome fb_info.cursor.origin.x = window.x + 424cbc8e155SToomas Soome fb_info.cursor.pos.x * boot_fb_font.vf_width; 4258e6d016fSToomas Soome fb_info.cursor.origin.y = window.y + 426cbc8e155SToomas Soome fb_info.cursor.pos.y * boot_fb_font.vf_height; 4278e6d016fSToomas Soome } 4288e6d016fSToomas Soome #endif 4298e6d016fSToomas Soome 4308e6d016fSToomas Soome /* If the cursor terminal position is 0,0 just reset screen coords */ 4318e6d016fSToomas Soome if (fb_info.cursor.pos.x == 0 && fb_info.cursor.pos.y == 0) { 4328e6d016fSToomas Soome fb_info.cursor.origin.x = window.x; 4338e6d016fSToomas Soome fb_info.cursor.origin.y = window.y; 4348e6d016fSToomas Soome } 4358e6d016fSToomas Soome 4368e6d016fSToomas Soome /* 4378e6d016fSToomas Soome * Validate cursor coords with screen/terminal dimensions, 4388e6d016fSToomas Soome * if anything is off, reset to 0,0 4398e6d016fSToomas Soome */ 4408e6d016fSToomas Soome if (fb_info.cursor.pos.x > fb_info.terminal.x || 4418e6d016fSToomas Soome fb_info.cursor.pos.y > fb_info.terminal.y || 4428e6d016fSToomas Soome fb_info.cursor.origin.x > fb_info.screen.x || 4438e6d016fSToomas Soome fb_info.cursor.origin.y > fb_info.screen.y) { 4448e6d016fSToomas Soome 4458e6d016fSToomas Soome fb_info.cursor.origin.x = window.x; 4468e6d016fSToomas Soome fb_info.cursor.origin.y = window.y; 4478e6d016fSToomas Soome fb_info.cursor.pos.x = 0; 4488e6d016fSToomas Soome fb_info.cursor.pos.y = 0; 4498e6d016fSToomas Soome } 4508e6d016fSToomas Soome 4518e6d016fSToomas Soome #if defined(_BOOT) 4528e6d016fSToomas Soome /* clear the screen if cursor is set to 0,0 */ 45329a77b73SToomas Soome if (fb_info.cursor.pos.x == 0 && fb_info.cursor.pos.y == 0) { 45429a77b73SToomas Soome uint32_t fg, bg, toffset; 45529a77b73SToomas Soome uint16_t y; 4568e6d016fSToomas Soome 4578e6d016fSToomas Soome boot_get_color(&fg, &bg); 4588e6d016fSToomas Soome bg = boot_color_map(bg); 4598e6d016fSToomas Soome 46029a77b73SToomas Soome toffset = 0; 46129a77b73SToomas Soome for (y = 0; y < fb_info.screen.y; y++) { 46229a77b73SToomas Soome uint8_t *dest = fb_info.fb + toffset; 46329a77b73SToomas Soome 4648e6d016fSToomas Soome boot_fb_fill(dest, bg, fb_info.pitch); 46529a77b73SToomas Soome toffset += fb_info.pitch; 4668e6d016fSToomas Soome } 4678e6d016fSToomas Soome } 4688e6d016fSToomas Soome #endif 4698e6d016fSToomas Soome } 4708e6d016fSToomas Soome 4718e6d016fSToomas Soome /* copy rectangle to framebuffer. */ 4728e6d016fSToomas Soome static void 4738e6d016fSToomas Soome boot_fb_blit(struct vis_consdisplay *rect) 4748e6d016fSToomas Soome { 47529a77b73SToomas Soome uint32_t offset, size; /* write size per scanline */ 47629a77b73SToomas Soome uint8_t *fbp, *sfbp = NULL; /* fb + calculated offset */ 4778e6d016fSToomas Soome int i; 4788e6d016fSToomas Soome 4798e6d016fSToomas Soome /* make sure we will not write past FB */ 4808e6d016fSToomas Soome if (rect->col >= fb_info.screen.x || 4818e6d016fSToomas Soome rect->row >= fb_info.screen.y || 4828e6d016fSToomas Soome rect->col + rect->width >= fb_info.screen.x || 4838e6d016fSToomas Soome rect->row + rect->height >= fb_info.screen.y) 4848e6d016fSToomas Soome return; 4858e6d016fSToomas Soome 4868e6d016fSToomas Soome size = rect->width * fb_info.bpp; 48729a77b73SToomas Soome offset = rect->col * fb_info.bpp + rect->row * fb_info.pitch; 48829a77b73SToomas Soome fbp = fb_info.fb + offset; 48929a77b73SToomas Soome if (fb_info.shadow_fb != NULL) 49029a77b73SToomas Soome sfbp = fb_info.shadow_fb + offset; 4918e6d016fSToomas Soome 4928e6d016fSToomas Soome /* write all scanlines in rectangle */ 4938e6d016fSToomas Soome for (i = 0; i < rect->height; i++) { 4948e6d016fSToomas Soome uint8_t *dest = fbp + i * fb_info.pitch; 4958e6d016fSToomas Soome uint8_t *src = rect->data + i * size; 4968e6d016fSToomas Soome boot_fb_cpy(dest, src, size); 4978e6d016fSToomas Soome if (sfbp != NULL) { 4988e6d016fSToomas Soome dest = sfbp + i * fb_info.pitch; 4998e6d016fSToomas Soome boot_fb_cpy(dest, src, size); 5008e6d016fSToomas Soome } 5018e6d016fSToomas Soome } 5028e6d016fSToomas Soome } 5038e6d016fSToomas Soome 5048e6d016fSToomas Soome static void 5058e6d016fSToomas Soome bit_to_pix(uchar_t c) 5068e6d016fSToomas Soome { 5078e6d016fSToomas Soome uint32_t fg, bg; 5088e6d016fSToomas Soome 5098e6d016fSToomas Soome boot_get_color(&fg, &bg); 5108e6d016fSToomas Soome fg = boot_color_map(fg); 5118e6d016fSToomas Soome bg = boot_color_map(bg); 5128e6d016fSToomas Soome 5138e6d016fSToomas Soome switch (fb_info.depth) { 5148e6d016fSToomas Soome case 8: 5158e6d016fSToomas Soome font_bit_to_pix8(&boot_fb_font, (uint8_t *)glyph, c, fg, bg); 5168e6d016fSToomas Soome break; 5178e6d016fSToomas Soome case 15: 5188e6d016fSToomas Soome case 16: 5198e6d016fSToomas Soome font_bit_to_pix16(&boot_fb_font, (uint16_t *)glyph, c, 5208e6d016fSToomas Soome (uint16_t)fg, (uint16_t)bg); 5218e6d016fSToomas Soome break; 5228e6d016fSToomas Soome case 24: 5238e6d016fSToomas Soome font_bit_to_pix24(&boot_fb_font, (uint8_t *)glyph, c, fg, bg); 5248e6d016fSToomas Soome break; 5258e6d016fSToomas Soome case 32: 5268e6d016fSToomas Soome font_bit_to_pix32(&boot_fb_font, (uint32_t *)glyph, c, fg, bg); 5278e6d016fSToomas Soome break; 5288e6d016fSToomas Soome } 5298e6d016fSToomas Soome } 5308e6d016fSToomas Soome 5318e6d016fSToomas Soome static void 53229a77b73SToomas Soome boot_fb_eraseline_impl(uint16_t x, uint16_t y) 5338e6d016fSToomas Soome { 53429a77b73SToomas Soome uint32_t toffset, size; 5358e6d016fSToomas Soome uint32_t fg, bg; 53629a77b73SToomas Soome uint8_t *dst, *sdst; 5378e6d016fSToomas Soome int i; 5388e6d016fSToomas Soome 5398e6d016fSToomas Soome boot_get_color(&fg, &bg); 5408e6d016fSToomas Soome bg = boot_color_map(bg); 5418e6d016fSToomas Soome 542cbc8e155SToomas Soome size = fb_info.terminal.x * boot_fb_font.vf_width * fb_info.bpp; 54329a77b73SToomas Soome 54429a77b73SToomas Soome toffset = x * fb_info.bpp + y * fb_info.pitch; 54529a77b73SToomas Soome dst = fb_info.fb + toffset; 546a6f5e66aSToomas Soome sdst = fb_info.shadow_fb + toffset; 54729a77b73SToomas Soome 548cbc8e155SToomas Soome for (i = 0; i < boot_fb_font.vf_height; i++) { 54929a77b73SToomas Soome uint8_t *dest = dst + i * fb_info.pitch; 55029a77b73SToomas Soome if (fb_info.fb + fb_info.fb_size >= dest + size) 55129a77b73SToomas Soome boot_fb_fill(dest, bg, size); 55229a77b73SToomas Soome if (fb_info.shadow_fb != NULL) { 55329a77b73SToomas Soome dest = sdst + i * fb_info.pitch; 55429a77b73SToomas Soome if (fb_info.shadow_fb + fb_info.fb_size >= 55529a77b73SToomas Soome dest + size) { 55629a77b73SToomas Soome boot_fb_fill(dest, bg, size); 55729a77b73SToomas Soome } 55829a77b73SToomas Soome } 55929a77b73SToomas Soome } 56029a77b73SToomas Soome } 56129a77b73SToomas Soome 56229a77b73SToomas Soome static void 56329a77b73SToomas Soome boot_fb_eraseline(void) 56429a77b73SToomas Soome { 56529a77b73SToomas Soome boot_fb_eraseline_impl(fb_info.cursor.origin.x, 56629a77b73SToomas Soome fb_info.cursor.origin.y); 56729a77b73SToomas Soome } 56829a77b73SToomas Soome 56929a77b73SToomas Soome /* 57029a77b73SToomas Soome * Copy rectangle from console to console. 57129a77b73SToomas Soome * If shadow buffer is available, use shadow as source. 57229a77b73SToomas Soome */ 57329a77b73SToomas Soome static void 57429a77b73SToomas Soome boot_fb_conscopy(struct vis_conscopy *c_copy) 57529a77b73SToomas Soome { 57629a77b73SToomas Soome uint32_t soffset, toffset; 57729a77b73SToomas Soome uint32_t width, height, increment; 57829a77b73SToomas Soome uint8_t *src, *dst, *sdst = NULL; 57929a77b73SToomas Soome int i; 58029a77b73SToomas Soome 58129a77b73SToomas Soome soffset = c_copy->s_col * fb_info.bpp + c_copy->s_row * fb_info.pitch; 58229a77b73SToomas Soome toffset = c_copy->t_col * fb_info.bpp + c_copy->t_row * fb_info.pitch; 58329a77b73SToomas Soome 58429a77b73SToomas Soome src = fb_info.fb + soffset; 58529a77b73SToomas Soome dst = fb_info.fb + toffset; 5868e6d016fSToomas Soome 5878e6d016fSToomas Soome if (fb_info.shadow_fb != NULL) { 5888e6d016fSToomas Soome src = fb_info.shadow_fb + soffset; 5898e6d016fSToomas Soome sdst = fb_info.shadow_fb + toffset; 5908e6d016fSToomas Soome } 5918e6d016fSToomas Soome 59229a77b73SToomas Soome width = (c_copy->e_col - c_copy->s_col + 1) * fb_info.bpp; 59329a77b73SToomas Soome height = c_copy->e_row - c_copy->s_row + 1; 59429a77b73SToomas Soome 5958e6d016fSToomas Soome for (i = 0; i < height; i++) { 59629a77b73SToomas Soome increment = i * fb_info.pitch; 59729a77b73SToomas Soome 59829a77b73SToomas Soome /* Make sure we fit into FB size. */ 59929a77b73SToomas Soome if (soffset + increment + width >= fb_info.fb_size || 60029a77b73SToomas Soome toffset + increment + width >= fb_info.fb_size) 60129a77b73SToomas Soome break; 60229a77b73SToomas Soome 6038e6d016fSToomas Soome boot_fb_cpy(dst + increment, src + increment, width); 60429a77b73SToomas Soome 6058e6d016fSToomas Soome if (sdst != NULL) 6068e6d016fSToomas Soome boot_fb_cpy(sdst + increment, src + increment, width); 6078e6d016fSToomas Soome } 60829a77b73SToomas Soome } 6098e6d016fSToomas Soome 61029a77b73SToomas Soome /* Shift the line content by chars. */ 61129a77b73SToomas Soome static void 61229a77b73SToomas Soome boot_fb_shiftline(int chars) 61329a77b73SToomas Soome { 61429a77b73SToomas Soome struct vis_conscopy c_copy; 6158e6d016fSToomas Soome 61629a77b73SToomas Soome c_copy.s_col = fb_info.cursor.origin.x; 61729a77b73SToomas Soome c_copy.s_row = fb_info.cursor.origin.y; 61829a77b73SToomas Soome 619cbc8e155SToomas Soome c_copy.e_col = (fb_info.terminal.x - chars) * boot_fb_font.vf_width; 62029a77b73SToomas Soome c_copy.e_col += fb_info.terminal_origin.x; 621cbc8e155SToomas Soome c_copy.e_row = c_copy.s_row + boot_fb_font.vf_height; 62229a77b73SToomas Soome 623cbc8e155SToomas Soome c_copy.t_col = fb_info.cursor.origin.x + chars * boot_fb_font.vf_width; 62429a77b73SToomas Soome c_copy.t_row = fb_info.cursor.origin.y; 62529a77b73SToomas Soome 62629a77b73SToomas Soome boot_fb_conscopy(&c_copy); 62729a77b73SToomas Soome } 62829a77b73SToomas Soome 62929a77b73SToomas Soome /* 63029a77b73SToomas Soome * move the terminal window lines [1..y] to [0..y-1] and clear last line. 63129a77b73SToomas Soome */ 63229a77b73SToomas Soome static void 63329a77b73SToomas Soome boot_fb_scroll(void) 63429a77b73SToomas Soome { 63529a77b73SToomas Soome struct vis_conscopy c_copy; 63629a77b73SToomas Soome 63729a77b73SToomas Soome /* support for scrolling. set up the console copy data and last line */ 638cbc8e155SToomas Soome c_copy.s_row = fb_info.terminal_origin.y + boot_fb_font.vf_height; 63929a77b73SToomas Soome c_copy.s_col = fb_info.terminal_origin.x; 64029a77b73SToomas Soome c_copy.e_row = fb_info.screen.y - fb_info.terminal_origin.y; 64129a77b73SToomas Soome c_copy.e_col = fb_info.screen.x - fb_info.terminal_origin.x; 64229a77b73SToomas Soome c_copy.t_row = fb_info.terminal_origin.y; 64329a77b73SToomas Soome c_copy.t_col = fb_info.terminal_origin.x; 64429a77b73SToomas Soome 64529a77b73SToomas Soome boot_fb_conscopy(&c_copy); 64629a77b73SToomas Soome 64729a77b73SToomas Soome /* now clean up the last line */ 64829a77b73SToomas Soome boot_fb_eraseline_impl(fb_info.terminal_origin.x, 64929a77b73SToomas Soome fb_info.terminal_origin.y + 650cbc8e155SToomas Soome (fb_info.terminal.y - 1) * boot_fb_font.vf_height); 6518e6d016fSToomas Soome } 6528e6d016fSToomas Soome 6538e6d016fSToomas Soome /* 6548e6d016fSToomas Soome * Very simple block cursor. Save space below the cursor and restore 6558e6d016fSToomas Soome * when cursor is invisible. 6568e6d016fSToomas Soome */ 6578e6d016fSToomas Soome void 6588e6d016fSToomas Soome boot_fb_cursor(boolean_t visible) 6598e6d016fSToomas Soome { 660cbc8e155SToomas Soome uint32_t offset, size, j; 6618e6d016fSToomas Soome uint32_t *fb32, *sfb32 = NULL; 6628e6d016fSToomas Soome uint32_t fg, bg; 6638e6d016fSToomas Soome uint16_t *fb16, *sfb16 = NULL; 6648e6d016fSToomas Soome uint8_t *fb8, *sfb8 = NULL; 6658e6d016fSToomas Soome int i, pitch; 6668e6d016fSToomas Soome 6678e6d016fSToomas Soome if (fb_info.cursor.visible == visible) 6688e6d016fSToomas Soome return; 6698e6d016fSToomas Soome 6708e6d016fSToomas Soome boot_get_color(&fg, &bg); 6718e6d016fSToomas Soome fg = boot_color_map(fg); 6728e6d016fSToomas Soome bg = boot_color_map(bg); 6738e6d016fSToomas Soome 6748e6d016fSToomas Soome fb_info.cursor.visible = visible; 6758e6d016fSToomas Soome pitch = fb_info.pitch; 676cbc8e155SToomas Soome size = boot_fb_font.vf_width * fb_info.bpp; 6778e6d016fSToomas Soome 6788e6d016fSToomas Soome /* 6798e6d016fSToomas Soome * Build cursor image. We are building mirror image of data on 6808e6d016fSToomas Soome * frame buffer by (D xor FG) xor BG. 6818e6d016fSToomas Soome */ 6828e6d016fSToomas Soome offset = fb_info.cursor.origin.x * fb_info.bpp + 6838e6d016fSToomas Soome fb_info.cursor.origin.y * pitch; 6848e6d016fSToomas Soome switch (fb_info.depth) { 6858e6d016fSToomas Soome case 8: 686cbc8e155SToomas Soome for (i = 0; i < boot_fb_font.vf_height; i++) { 6878e6d016fSToomas Soome fb8 = fb_info.fb + offset + i * pitch; 6888e6d016fSToomas Soome if (fb_info.shadow_fb != NULL) 6898e6d016fSToomas Soome sfb8 = fb_info.shadow_fb + offset + i * pitch; 690cbc8e155SToomas Soome for (j = 0; j < size; j += 1) { 6918e6d016fSToomas Soome fb8[j] = (fb8[j] ^ (fg & 0xff)) ^ (bg & 0xff); 6928e6d016fSToomas Soome 6938e6d016fSToomas Soome if (sfb8 == NULL) 6948e6d016fSToomas Soome continue; 6958e6d016fSToomas Soome 6968e6d016fSToomas Soome sfb8[j] = (sfb8[j] ^ (fg & 0xff)) ^ (bg & 0xff); 6978e6d016fSToomas Soome } 6988e6d016fSToomas Soome } 6998e6d016fSToomas Soome break; 7008e6d016fSToomas Soome case 15: 7018e6d016fSToomas Soome case 16: 702cbc8e155SToomas Soome for (i = 0; i < boot_fb_font.vf_height; i++) { 7038e6d016fSToomas Soome fb16 = (uint16_t *)(fb_info.fb + offset + i * pitch); 7048e6d016fSToomas Soome if (fb_info.shadow_fb != NULL) 7058e6d016fSToomas Soome sfb16 = (uint16_t *) 7068e6d016fSToomas Soome (fb_info.shadow_fb + offset + i * pitch); 707cbc8e155SToomas Soome for (j = 0; j < boot_fb_font.vf_width; j++) { 7088e6d016fSToomas Soome fb16[j] = (fb16[j] ^ (fg & 0xffff)) ^ 7098e6d016fSToomas Soome (bg & 0xffff); 7108e6d016fSToomas Soome 7118e6d016fSToomas Soome if (sfb16 == NULL) 7128e6d016fSToomas Soome continue; 7138e6d016fSToomas Soome 7148e6d016fSToomas Soome sfb16[j] = (sfb16[j] ^ (fg & 0xffff)) ^ 7158e6d016fSToomas Soome (bg & 0xffff); 7168e6d016fSToomas Soome } 7178e6d016fSToomas Soome } 7188e6d016fSToomas Soome break; 7198e6d016fSToomas Soome case 24: 720cbc8e155SToomas Soome for (i = 0; i < boot_fb_font.vf_height; i++) { 7218e6d016fSToomas Soome fb8 = fb_info.fb + offset + i * pitch; 7228e6d016fSToomas Soome if (fb_info.shadow_fb != NULL) 7238e6d016fSToomas Soome sfb8 = fb_info.shadow_fb + offset + i * pitch; 724cbc8e155SToomas Soome for (j = 0; j < size; j += 3) { 7258e6d016fSToomas Soome fb8[j] = (fb8[j] ^ ((fg >> 16) & 0xff)) ^ 7268e6d016fSToomas Soome ((bg >> 16) & 0xff); 7278e6d016fSToomas Soome fb8[j+1] = (fb8[j+1] ^ ((fg >> 8) & 0xff)) ^ 7288e6d016fSToomas Soome ((bg >> 8) & 0xff); 7298e6d016fSToomas Soome fb8[j+2] = (fb8[j+2] ^ (fg & 0xff)) ^ 7308e6d016fSToomas Soome (bg & 0xff); 7318e6d016fSToomas Soome 7328e6d016fSToomas Soome if (sfb8 == NULL) 7338e6d016fSToomas Soome continue; 7348e6d016fSToomas Soome 7358e6d016fSToomas Soome sfb8[j] = (sfb8[j] ^ ((fg >> 16) & 0xff)) ^ 7368e6d016fSToomas Soome ((bg >> 16) & 0xff); 7378e6d016fSToomas Soome sfb8[j+1] = (sfb8[j+1] ^ ((fg >> 8) & 0xff)) ^ 7388e6d016fSToomas Soome ((bg >> 8) & 0xff); 7398e6d016fSToomas Soome sfb8[j+2] = (sfb8[j+2] ^ (fg & 0xff)) ^ 7408e6d016fSToomas Soome (bg & 0xff); 7418e6d016fSToomas Soome } 7428e6d016fSToomas Soome } 7438e6d016fSToomas Soome break; 7448e6d016fSToomas Soome case 32: 745cbc8e155SToomas Soome for (i = 0; i < boot_fb_font.vf_height; i++) { 7468e6d016fSToomas Soome fb32 = (uint32_t *)(fb_info.fb + offset + i * pitch); 7478e6d016fSToomas Soome if (fb_info.shadow_fb != NULL) { 7488e6d016fSToomas Soome sfb32 = (uint32_t *) 7498e6d016fSToomas Soome (fb_info.shadow_fb + offset + i * pitch); 7508e6d016fSToomas Soome } 751cbc8e155SToomas Soome for (j = 0; j < boot_fb_font.vf_width; j++) { 7528e6d016fSToomas Soome fb32[j] = (fb32[j] ^ fg) ^ bg; 7538e6d016fSToomas Soome 7548e6d016fSToomas Soome if (sfb32 == NULL) 7558e6d016fSToomas Soome continue; 7568e6d016fSToomas Soome 7578e6d016fSToomas Soome sfb32[j] = (sfb32[j] ^ fg) ^ bg; 7588e6d016fSToomas Soome } 7598e6d016fSToomas Soome } 7608e6d016fSToomas Soome break; 7618e6d016fSToomas Soome } 7628e6d016fSToomas Soome } 7638e6d016fSToomas Soome 7648e6d016fSToomas Soome static void 76529a77b73SToomas Soome boot_fb_setpos(int row, int col) 7668e6d016fSToomas Soome { 76729a77b73SToomas Soome if (row < 0) 76829a77b73SToomas Soome row = 0; 76929a77b73SToomas Soome if (row >= fb_info.terminal.y) 77029a77b73SToomas Soome row = fb_info.terminal.y - 1; 77129a77b73SToomas Soome if (col < 0) 77229a77b73SToomas Soome col = 0; 77329a77b73SToomas Soome if (col >= fb_info.terminal.x) 77429a77b73SToomas Soome col = fb_info.terminal.x - 1; 77529a77b73SToomas Soome 77629a77b73SToomas Soome fb_info.cursor.pos.x = col; 77729a77b73SToomas Soome fb_info.cursor.pos.y = row; 7788e6d016fSToomas Soome fb_info.cursor.origin.x = fb_info.terminal_origin.x; 779cbc8e155SToomas Soome fb_info.cursor.origin.x += col * boot_fb_font.vf_width; 78029a77b73SToomas Soome fb_info.cursor.origin.y = fb_info.terminal_origin.y; 781cbc8e155SToomas Soome fb_info.cursor.origin.y += row * boot_fb_font.vf_height; 7828e6d016fSToomas Soome } 7838e6d016fSToomas Soome 7848e6d016fSToomas Soome static void 78529a77b73SToomas Soome boot_fb_putchar(int c) 7868e6d016fSToomas Soome { 7878e6d016fSToomas Soome struct vis_consdisplay display; 78829a77b73SToomas Soome int rows, cols; 78929a77b73SToomas Soome 79029a77b73SToomas Soome rows = fb_info.cursor.pos.y; 79129a77b73SToomas Soome cols = fb_info.cursor.pos.x; 79229a77b73SToomas Soome 79329a77b73SToomas Soome if (c == '\n') { 79429a77b73SToomas Soome if (rows < fb_info.terminal.y - 1) 79529a77b73SToomas Soome boot_fb_setpos(rows + 1, cols); 79629a77b73SToomas Soome else 79729a77b73SToomas Soome boot_fb_scroll(); 7988e6d016fSToomas Soome return; 7998e6d016fSToomas Soome } 8008e6d016fSToomas Soome 8018e6d016fSToomas Soome bit_to_pix(c); 8028e6d016fSToomas Soome display.col = fb_info.cursor.origin.x; 8038e6d016fSToomas Soome display.row = fb_info.cursor.origin.y; 804cbc8e155SToomas Soome display.width = boot_fb_font.vf_width; 805cbc8e155SToomas Soome display.height = boot_fb_font.vf_height; 8068e6d016fSToomas Soome display.data = glyph; 8078e6d016fSToomas Soome 8088e6d016fSToomas Soome boot_fb_blit(&display); 80929a77b73SToomas Soome if (cols < fb_info.terminal.x - 1) 81029a77b73SToomas Soome boot_fb_setpos(rows, cols + 1); 81129a77b73SToomas Soome else if (rows < fb_info.terminal.y - 1) 81229a77b73SToomas Soome boot_fb_setpos(rows + 1, 0); 81329a77b73SToomas Soome else { 81429a77b73SToomas Soome boot_fb_setpos(rows, 0); 81529a77b73SToomas Soome boot_fb_scroll(); 81629a77b73SToomas Soome } 8178e6d016fSToomas Soome } 818