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)) 39*a4e6b9b6SToomas 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 1618e6d016fSToomas Soome tag = (multiboot_tag_framebuffer_t *)(uintptr_t)xbi_fb->framebuffer; 1628e6d016fSToomas Soome if (tag == NULL) { 1638e6d016fSToomas Soome return (B_FALSE); 1648e6d016fSToomas Soome } 1658e6d016fSToomas Soome 166cbc8e155SToomas Soome xbi_init_font(xbi); 167cbc8e155SToomas Soome 1688e6d016fSToomas Soome fb_info.paddr = tag->framebuffer_common.framebuffer_addr; 1698e6d016fSToomas Soome fb_info.pitch = tag->framebuffer_common.framebuffer_pitch; 1708e6d016fSToomas Soome fb_info.depth = tag->framebuffer_common.framebuffer_bpp; 1718e6d016fSToomas Soome fb_info.bpp = P2ROUNDUP(fb_info.depth, 8) >> 3; 1728e6d016fSToomas Soome fb_info.screen.x = tag->framebuffer_common.framebuffer_width; 1738e6d016fSToomas Soome fb_info.screen.y = tag->framebuffer_common.framebuffer_height; 1748e6d016fSToomas Soome fb_info.fb_size = fb_info.screen.y * fb_info.pitch; 1758e6d016fSToomas Soome 17629a77b73SToomas Soome bcons_dev->bd_putchar = boot_fb_putchar; 17729a77b73SToomas Soome bcons_dev->bd_eraseline = boot_fb_eraseline; 17829a77b73SToomas Soome bcons_dev->bd_cursor = boot_fb_cursor; 17929a77b73SToomas Soome bcons_dev->bd_setpos = boot_fb_setpos; 18029a77b73SToomas Soome bcons_dev->bd_shift = boot_fb_shiftline; 18129a77b73SToomas Soome 1828e6d016fSToomas Soome if (fb_info.paddr == 0) 1838e6d016fSToomas Soome fb_info.fb_type = FB_TYPE_UNKNOWN; 1848e6d016fSToomas Soome 1858e6d016fSToomas Soome switch (tag->framebuffer_common.framebuffer_type) { 1868e6d016fSToomas Soome case MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT: 1878e6d016fSToomas Soome fb_info.fb_type = FB_TYPE_EGA_TEXT; 1888e6d016fSToomas Soome return (B_FALSE); 1898e6d016fSToomas Soome 1908e6d016fSToomas Soome case MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED: 1918e6d016fSToomas Soome if (fb_info.paddr != 0) 1928e6d016fSToomas Soome fb_info.fb_type = FB_TYPE_INDEXED; 1938e6d016fSToomas Soome return (B_TRUE); 1948e6d016fSToomas Soome 1958e6d016fSToomas Soome case MULTIBOOT_FRAMEBUFFER_TYPE_RGB: 1968e6d016fSToomas Soome if (fb_info.paddr != 0) 1978e6d016fSToomas Soome fb_info.fb_type = FB_TYPE_RGB; 1988e6d016fSToomas Soome break; 1998e6d016fSToomas Soome 2008e6d016fSToomas Soome default: 2018e6d016fSToomas Soome return (B_FALSE); 2028e6d016fSToomas Soome } 2038e6d016fSToomas Soome 2048e6d016fSToomas Soome fb_info.rgb.red.size = tag->u.fb2.framebuffer_red_mask_size; 2058e6d016fSToomas Soome fb_info.rgb.red.pos = tag->u.fb2.framebuffer_red_field_position; 2068e6d016fSToomas Soome fb_info.rgb.green.size = tag->u.fb2.framebuffer_green_mask_size; 2078e6d016fSToomas Soome fb_info.rgb.green.pos = tag->u.fb2.framebuffer_green_field_position; 2088e6d016fSToomas Soome fb_info.rgb.blue.size = tag->u.fb2.framebuffer_blue_mask_size; 2098e6d016fSToomas Soome fb_info.rgb.blue.pos = tag->u.fb2.framebuffer_blue_field_position; 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 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 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 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 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 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) { 358*a4e6b9b6SToomas Soome if (fb_info.fg_color < 16) 359*a4e6b9b6SToomas Soome *bg = dim_xlate[fb_info.fg_color]; 360*a4e6b9b6SToomas Soome else 361*a4e6b9b6SToomas Soome *bg = fb_info.fg_color; 362*a4e6b9b6SToomas Soome 363*a4e6b9b6SToomas Soome if (fb_info.bg_color < 16) 364*a4e6b9b6SToomas Soome *fg = brt_xlate[fb_info.bg_color]; 365*a4e6b9b6SToomas Soome else 366*a4e6b9b6SToomas Soome *fg = fb_info.bg_color; 3678e6d016fSToomas Soome } else { 368*a4e6b9b6SToomas Soome if (fb_info.bg_color < 16) { 369*a4e6b9b6SToomas Soome if (fb_info.bg_color == 7) 370*a4e6b9b6SToomas Soome *bg = brt_xlate[fb_info.bg_color]; 371*a4e6b9b6SToomas Soome else 372*a4e6b9b6SToomas Soome *bg = dim_xlate[fb_info.bg_color]; 373*a4e6b9b6SToomas Soome } else { 374*a4e6b9b6SToomas Soome *bg = fb_info.bg_color; 375*a4e6b9b6SToomas Soome } 376*a4e6b9b6SToomas Soome if (fb_info.fg_color < 16) 377*a4e6b9b6SToomas Soome *fg = dim_xlate[fb_info.fg_color]; 3788e6d016fSToomas Soome else 379*a4e6b9b6SToomas Soome *fg = fb_info.fg_color; 3808e6d016fSToomas Soome } 3818e6d016fSToomas Soome } 3828e6d016fSToomas Soome 3838e6d016fSToomas Soome /* 3848e6d016fSToomas Soome * Map indexed color to RGB value. 3858e6d016fSToomas Soome */ 386*a4e6b9b6SToomas Soome uint32_t 3878e6d016fSToomas Soome boot_color_map(uint8_t index) 3888e6d016fSToomas Soome { 389*a4e6b9b6SToomas Soome if (fb_info.fb_type != FB_TYPE_RGB) { 390*a4e6b9b6SToomas Soome if (index < nitems(solaris_color_to_pc_color)) 391*a4e6b9b6SToomas Soome return (solaris_color_to_pc_color[index]); 392*a4e6b9b6SToomas Soome else 393*a4e6b9b6SToomas Soome return (index); 394*a4e6b9b6SToomas Soome } 3958e6d016fSToomas Soome 396*a4e6b9b6SToomas Soome return (rgb_color_map(&fb_info.rgb, index)); 3978e6d016fSToomas Soome } 3988e6d016fSToomas Soome 3998e6d016fSToomas Soome /* set up out simple console. */ 4008e6d016fSToomas Soome /*ARGSUSED*/ 4018e6d016fSToomas Soome void 4028e6d016fSToomas Soome boot_fb_init(int console) 4038e6d016fSToomas Soome { 4048e6d016fSToomas Soome fb_info_pixel_coord_t window; 4058e6d016fSToomas Soome 4068e6d016fSToomas Soome /* frame buffer address is mapped in dboot. */ 4078e6d016fSToomas Soome fb_info.fb = (uint8_t *)(uintptr_t)fb_info.paddr; 4088e6d016fSToomas Soome 4098e6d016fSToomas Soome boot_fb_set_font(fb_info.screen.y, fb_info.screen.x); 410cbc8e155SToomas Soome window.x = (fb_info.screen.x - 411cbc8e155SToomas Soome fb_info.terminal.x * boot_fb_font.vf_width) / 2; 412cbc8e155SToomas Soome window.y = (fb_info.screen.y - 413cbc8e155SToomas Soome fb_info.terminal.y * boot_fb_font.vf_height) / 2; 4148e6d016fSToomas Soome fb_info.terminal_origin.x = window.x; 4158e6d016fSToomas Soome fb_info.terminal_origin.y = window.y; 4168e6d016fSToomas Soome 4178e6d016fSToomas Soome #if defined(_BOOT) 4188e6d016fSToomas Soome /* 4198e6d016fSToomas Soome * Being called from dboot, we can have cursor terminal 4208e6d016fSToomas Soome * position passed from boot loader. In such case, fix the 4218e6d016fSToomas Soome * cursor screen coords. 4228e6d016fSToomas Soome */ 4238e6d016fSToomas Soome if (fb_info.cursor.pos.x != 0 || fb_info.cursor.pos.y != 0) { 4248e6d016fSToomas Soome fb_info.cursor.origin.x = window.x + 425cbc8e155SToomas Soome fb_info.cursor.pos.x * boot_fb_font.vf_width; 4268e6d016fSToomas Soome fb_info.cursor.origin.y = window.y + 427cbc8e155SToomas Soome fb_info.cursor.pos.y * boot_fb_font.vf_height; 4288e6d016fSToomas Soome } 4298e6d016fSToomas Soome #endif 4308e6d016fSToomas Soome 4318e6d016fSToomas Soome /* If the cursor terminal position is 0,0 just reset screen coords */ 4328e6d016fSToomas Soome if (fb_info.cursor.pos.x == 0 && fb_info.cursor.pos.y == 0) { 4338e6d016fSToomas Soome fb_info.cursor.origin.x = window.x; 4348e6d016fSToomas Soome fb_info.cursor.origin.y = window.y; 4358e6d016fSToomas Soome } 4368e6d016fSToomas Soome 4378e6d016fSToomas Soome /* 4388e6d016fSToomas Soome * Validate cursor coords with screen/terminal dimensions, 4398e6d016fSToomas Soome * if anything is off, reset to 0,0 4408e6d016fSToomas Soome */ 4418e6d016fSToomas Soome if (fb_info.cursor.pos.x > fb_info.terminal.x || 4428e6d016fSToomas Soome fb_info.cursor.pos.y > fb_info.terminal.y || 4438e6d016fSToomas Soome fb_info.cursor.origin.x > fb_info.screen.x || 4448e6d016fSToomas Soome fb_info.cursor.origin.y > fb_info.screen.y) { 4458e6d016fSToomas Soome 4468e6d016fSToomas Soome fb_info.cursor.origin.x = window.x; 4478e6d016fSToomas Soome fb_info.cursor.origin.y = window.y; 4488e6d016fSToomas Soome fb_info.cursor.pos.x = 0; 4498e6d016fSToomas Soome fb_info.cursor.pos.y = 0; 4508e6d016fSToomas Soome } 4518e6d016fSToomas Soome 4528e6d016fSToomas Soome #if defined(_BOOT) 4538e6d016fSToomas Soome /* clear the screen if cursor is set to 0,0 */ 45429a77b73SToomas Soome if (fb_info.cursor.pos.x == 0 && fb_info.cursor.pos.y == 0) { 45529a77b73SToomas Soome uint32_t fg, bg, toffset; 45629a77b73SToomas Soome uint16_t y; 4578e6d016fSToomas Soome 4588e6d016fSToomas Soome boot_get_color(&fg, &bg); 4598e6d016fSToomas Soome bg = boot_color_map(bg); 4608e6d016fSToomas Soome 46129a77b73SToomas Soome toffset = 0; 46229a77b73SToomas Soome for (y = 0; y < fb_info.screen.y; y++) { 46329a77b73SToomas Soome uint8_t *dest = fb_info.fb + toffset; 46429a77b73SToomas Soome 4658e6d016fSToomas Soome boot_fb_fill(dest, bg, fb_info.pitch); 46629a77b73SToomas Soome toffset += fb_info.pitch; 4678e6d016fSToomas Soome } 4688e6d016fSToomas Soome } 4698e6d016fSToomas Soome #endif 4708e6d016fSToomas Soome } 4718e6d016fSToomas Soome 4728e6d016fSToomas Soome /* copy rectangle to framebuffer. */ 4738e6d016fSToomas Soome static void 4748e6d016fSToomas Soome boot_fb_blit(struct vis_consdisplay *rect) 4758e6d016fSToomas Soome { 47629a77b73SToomas Soome uint32_t offset, size; /* write size per scanline */ 47729a77b73SToomas Soome uint8_t *fbp, *sfbp = NULL; /* fb + calculated offset */ 4788e6d016fSToomas Soome int i; 4798e6d016fSToomas Soome 4808e6d016fSToomas Soome /* make sure we will not write past FB */ 4818e6d016fSToomas Soome if (rect->col >= fb_info.screen.x || 4828e6d016fSToomas Soome rect->row >= fb_info.screen.y || 4838e6d016fSToomas Soome rect->col + rect->width >= fb_info.screen.x || 4848e6d016fSToomas Soome rect->row + rect->height >= fb_info.screen.y) 4858e6d016fSToomas Soome return; 4868e6d016fSToomas Soome 4878e6d016fSToomas Soome size = rect->width * fb_info.bpp; 48829a77b73SToomas Soome offset = rect->col * fb_info.bpp + rect->row * fb_info.pitch; 48929a77b73SToomas Soome fbp = fb_info.fb + offset; 49029a77b73SToomas Soome if (fb_info.shadow_fb != NULL) 49129a77b73SToomas Soome sfbp = fb_info.shadow_fb + offset; 4928e6d016fSToomas Soome 4938e6d016fSToomas Soome /* write all scanlines in rectangle */ 4948e6d016fSToomas Soome for (i = 0; i < rect->height; i++) { 4958e6d016fSToomas Soome uint8_t *dest = fbp + i * fb_info.pitch; 4968e6d016fSToomas Soome uint8_t *src = rect->data + i * size; 4978e6d016fSToomas Soome boot_fb_cpy(dest, src, size); 4988e6d016fSToomas Soome if (sfbp != NULL) { 4998e6d016fSToomas Soome dest = sfbp + i * fb_info.pitch; 5008e6d016fSToomas Soome boot_fb_cpy(dest, src, size); 5018e6d016fSToomas Soome } 5028e6d016fSToomas Soome } 5038e6d016fSToomas Soome } 5048e6d016fSToomas Soome 5058e6d016fSToomas Soome static void 5068e6d016fSToomas Soome bit_to_pix(uchar_t c) 5078e6d016fSToomas Soome { 5088e6d016fSToomas Soome uint32_t fg, bg; 5098e6d016fSToomas Soome 5108e6d016fSToomas Soome boot_get_color(&fg, &bg); 5118e6d016fSToomas Soome fg = boot_color_map(fg); 5128e6d016fSToomas Soome bg = boot_color_map(bg); 5138e6d016fSToomas Soome 5148e6d016fSToomas Soome switch (fb_info.depth) { 5158e6d016fSToomas Soome case 8: 5168e6d016fSToomas Soome font_bit_to_pix8(&boot_fb_font, (uint8_t *)glyph, c, fg, bg); 5178e6d016fSToomas Soome break; 5188e6d016fSToomas Soome case 15: 5198e6d016fSToomas Soome case 16: 5208e6d016fSToomas Soome font_bit_to_pix16(&boot_fb_font, (uint16_t *)glyph, c, 5218e6d016fSToomas Soome (uint16_t)fg, (uint16_t)bg); 5228e6d016fSToomas Soome break; 5238e6d016fSToomas Soome case 24: 5248e6d016fSToomas Soome font_bit_to_pix24(&boot_fb_font, (uint8_t *)glyph, c, fg, bg); 5258e6d016fSToomas Soome break; 5268e6d016fSToomas Soome case 32: 5278e6d016fSToomas Soome font_bit_to_pix32(&boot_fb_font, (uint32_t *)glyph, c, fg, bg); 5288e6d016fSToomas Soome break; 5298e6d016fSToomas Soome } 5308e6d016fSToomas Soome } 5318e6d016fSToomas Soome 5328e6d016fSToomas Soome static void 53329a77b73SToomas Soome boot_fb_eraseline_impl(uint16_t x, uint16_t y) 5348e6d016fSToomas Soome { 53529a77b73SToomas Soome uint32_t toffset, size; 5368e6d016fSToomas Soome uint32_t fg, bg; 53729a77b73SToomas Soome uint8_t *dst, *sdst; 5388e6d016fSToomas Soome int i; 5398e6d016fSToomas Soome 5408e6d016fSToomas Soome boot_get_color(&fg, &bg); 5418e6d016fSToomas Soome bg = boot_color_map(bg); 5428e6d016fSToomas Soome 543cbc8e155SToomas Soome size = fb_info.terminal.x * boot_fb_font.vf_width * fb_info.bpp; 54429a77b73SToomas Soome 54529a77b73SToomas Soome toffset = x * fb_info.bpp + y * fb_info.pitch; 54629a77b73SToomas Soome dst = fb_info.fb + toffset; 547a6f5e66aSToomas Soome sdst = fb_info.shadow_fb + toffset; 54829a77b73SToomas Soome 549cbc8e155SToomas Soome for (i = 0; i < boot_fb_font.vf_height; i++) { 55029a77b73SToomas Soome uint8_t *dest = dst + i * fb_info.pitch; 55129a77b73SToomas Soome if (fb_info.fb + fb_info.fb_size >= dest + size) 55229a77b73SToomas Soome boot_fb_fill(dest, bg, size); 55329a77b73SToomas Soome if (fb_info.shadow_fb != NULL) { 55429a77b73SToomas Soome dest = sdst + i * fb_info.pitch; 55529a77b73SToomas Soome if (fb_info.shadow_fb + fb_info.fb_size >= 55629a77b73SToomas Soome dest + size) { 55729a77b73SToomas Soome boot_fb_fill(dest, bg, size); 55829a77b73SToomas Soome } 55929a77b73SToomas Soome } 56029a77b73SToomas Soome } 56129a77b73SToomas Soome } 56229a77b73SToomas Soome 56329a77b73SToomas Soome static void 56429a77b73SToomas Soome boot_fb_eraseline(void) 56529a77b73SToomas Soome { 56629a77b73SToomas Soome boot_fb_eraseline_impl(fb_info.cursor.origin.x, 56729a77b73SToomas Soome fb_info.cursor.origin.y); 56829a77b73SToomas Soome } 56929a77b73SToomas Soome 57029a77b73SToomas Soome /* 57129a77b73SToomas Soome * Copy rectangle from console to console. 57229a77b73SToomas Soome * If shadow buffer is available, use shadow as source. 57329a77b73SToomas Soome */ 57429a77b73SToomas Soome static void 57529a77b73SToomas Soome boot_fb_conscopy(struct vis_conscopy *c_copy) 57629a77b73SToomas Soome { 57729a77b73SToomas Soome uint32_t soffset, toffset; 57829a77b73SToomas Soome uint32_t width, height, increment; 57929a77b73SToomas Soome uint8_t *src, *dst, *sdst = NULL; 58029a77b73SToomas Soome int i; 58129a77b73SToomas Soome 58229a77b73SToomas Soome soffset = c_copy->s_col * fb_info.bpp + c_copy->s_row * fb_info.pitch; 58329a77b73SToomas Soome toffset = c_copy->t_col * fb_info.bpp + c_copy->t_row * fb_info.pitch; 58429a77b73SToomas Soome 58529a77b73SToomas Soome src = fb_info.fb + soffset; 58629a77b73SToomas Soome dst = fb_info.fb + toffset; 5878e6d016fSToomas Soome 5888e6d016fSToomas Soome if (fb_info.shadow_fb != NULL) { 5898e6d016fSToomas Soome src = fb_info.shadow_fb + soffset; 5908e6d016fSToomas Soome sdst = fb_info.shadow_fb + toffset; 5918e6d016fSToomas Soome } 5928e6d016fSToomas Soome 59329a77b73SToomas Soome width = (c_copy->e_col - c_copy->s_col + 1) * fb_info.bpp; 59429a77b73SToomas Soome height = c_copy->e_row - c_copy->s_row + 1; 59529a77b73SToomas Soome 5968e6d016fSToomas Soome for (i = 0; i < height; i++) { 59729a77b73SToomas Soome increment = i * fb_info.pitch; 59829a77b73SToomas Soome 59929a77b73SToomas Soome /* Make sure we fit into FB size. */ 60029a77b73SToomas Soome if (soffset + increment + width >= fb_info.fb_size || 60129a77b73SToomas Soome toffset + increment + width >= fb_info.fb_size) 60229a77b73SToomas Soome break; 60329a77b73SToomas Soome 6048e6d016fSToomas Soome boot_fb_cpy(dst + increment, src + increment, width); 60529a77b73SToomas Soome 6068e6d016fSToomas Soome if (sdst != NULL) 6078e6d016fSToomas Soome boot_fb_cpy(sdst + increment, src + increment, width); 6088e6d016fSToomas Soome } 60929a77b73SToomas Soome } 6108e6d016fSToomas Soome 61129a77b73SToomas Soome /* Shift the line content by chars. */ 61229a77b73SToomas Soome static void 61329a77b73SToomas Soome boot_fb_shiftline(int chars) 61429a77b73SToomas Soome { 61529a77b73SToomas Soome struct vis_conscopy c_copy; 6168e6d016fSToomas Soome 61729a77b73SToomas Soome c_copy.s_col = fb_info.cursor.origin.x; 61829a77b73SToomas Soome c_copy.s_row = fb_info.cursor.origin.y; 61929a77b73SToomas Soome 620cbc8e155SToomas Soome c_copy.e_col = (fb_info.terminal.x - chars) * boot_fb_font.vf_width; 62129a77b73SToomas Soome c_copy.e_col += fb_info.terminal_origin.x; 622cbc8e155SToomas Soome c_copy.e_row = c_copy.s_row + boot_fb_font.vf_height; 62329a77b73SToomas Soome 624cbc8e155SToomas Soome c_copy.t_col = fb_info.cursor.origin.x + chars * boot_fb_font.vf_width; 62529a77b73SToomas Soome c_copy.t_row = fb_info.cursor.origin.y; 62629a77b73SToomas Soome 62729a77b73SToomas Soome boot_fb_conscopy(&c_copy); 62829a77b73SToomas Soome } 62929a77b73SToomas Soome 63029a77b73SToomas Soome /* 63129a77b73SToomas Soome * move the terminal window lines [1..y] to [0..y-1] and clear last line. 63229a77b73SToomas Soome */ 63329a77b73SToomas Soome static void 63429a77b73SToomas Soome boot_fb_scroll(void) 63529a77b73SToomas Soome { 63629a77b73SToomas Soome struct vis_conscopy c_copy; 63729a77b73SToomas Soome 63829a77b73SToomas Soome /* support for scrolling. set up the console copy data and last line */ 639cbc8e155SToomas Soome c_copy.s_row = fb_info.terminal_origin.y + boot_fb_font.vf_height; 64029a77b73SToomas Soome c_copy.s_col = fb_info.terminal_origin.x; 64129a77b73SToomas Soome c_copy.e_row = fb_info.screen.y - fb_info.terminal_origin.y; 64229a77b73SToomas Soome c_copy.e_col = fb_info.screen.x - fb_info.terminal_origin.x; 64329a77b73SToomas Soome c_copy.t_row = fb_info.terminal_origin.y; 64429a77b73SToomas Soome c_copy.t_col = fb_info.terminal_origin.x; 64529a77b73SToomas Soome 64629a77b73SToomas Soome boot_fb_conscopy(&c_copy); 64729a77b73SToomas Soome 64829a77b73SToomas Soome /* now clean up the last line */ 64929a77b73SToomas Soome boot_fb_eraseline_impl(fb_info.terminal_origin.x, 65029a77b73SToomas Soome fb_info.terminal_origin.y + 651cbc8e155SToomas Soome (fb_info.terminal.y - 1) * boot_fb_font.vf_height); 6528e6d016fSToomas Soome } 6538e6d016fSToomas Soome 6548e6d016fSToomas Soome /* 6558e6d016fSToomas Soome * Very simple block cursor. Save space below the cursor and restore 6568e6d016fSToomas Soome * when cursor is invisible. 6578e6d016fSToomas Soome */ 6588e6d016fSToomas Soome void 6598e6d016fSToomas Soome boot_fb_cursor(boolean_t visible) 6608e6d016fSToomas Soome { 661cbc8e155SToomas Soome uint32_t offset, size, j; 6628e6d016fSToomas Soome uint32_t *fb32, *sfb32 = NULL; 6638e6d016fSToomas Soome uint32_t fg, bg; 6648e6d016fSToomas Soome uint16_t *fb16, *sfb16 = NULL; 6658e6d016fSToomas Soome uint8_t *fb8, *sfb8 = NULL; 6668e6d016fSToomas Soome int i, pitch; 6678e6d016fSToomas Soome 6688e6d016fSToomas Soome if (fb_info.cursor.visible == visible) 6698e6d016fSToomas Soome return; 6708e6d016fSToomas Soome 6718e6d016fSToomas Soome boot_get_color(&fg, &bg); 6728e6d016fSToomas Soome fg = boot_color_map(fg); 6738e6d016fSToomas Soome bg = boot_color_map(bg); 6748e6d016fSToomas Soome 6758e6d016fSToomas Soome fb_info.cursor.visible = visible; 6768e6d016fSToomas Soome pitch = fb_info.pitch; 677cbc8e155SToomas Soome size = boot_fb_font.vf_width * fb_info.bpp; 6788e6d016fSToomas Soome 6798e6d016fSToomas Soome /* 6808e6d016fSToomas Soome * Build cursor image. We are building mirror image of data on 6818e6d016fSToomas Soome * frame buffer by (D xor FG) xor BG. 6828e6d016fSToomas Soome */ 6838e6d016fSToomas Soome offset = fb_info.cursor.origin.x * fb_info.bpp + 6848e6d016fSToomas Soome fb_info.cursor.origin.y * pitch; 6858e6d016fSToomas Soome switch (fb_info.depth) { 6868e6d016fSToomas Soome case 8: 687cbc8e155SToomas Soome for (i = 0; i < boot_fb_font.vf_height; i++) { 6888e6d016fSToomas Soome fb8 = fb_info.fb + offset + i * pitch; 6898e6d016fSToomas Soome if (fb_info.shadow_fb != NULL) 6908e6d016fSToomas Soome sfb8 = fb_info.shadow_fb + offset + i * pitch; 691cbc8e155SToomas Soome for (j = 0; j < size; j += 1) { 6928e6d016fSToomas Soome fb8[j] = (fb8[j] ^ (fg & 0xff)) ^ (bg & 0xff); 6938e6d016fSToomas Soome 6948e6d016fSToomas Soome if (sfb8 == NULL) 6958e6d016fSToomas Soome continue; 6968e6d016fSToomas Soome 6978e6d016fSToomas Soome sfb8[j] = (sfb8[j] ^ (fg & 0xff)) ^ (bg & 0xff); 6988e6d016fSToomas Soome } 6998e6d016fSToomas Soome } 7008e6d016fSToomas Soome break; 7018e6d016fSToomas Soome case 15: 7028e6d016fSToomas Soome case 16: 703cbc8e155SToomas Soome for (i = 0; i < boot_fb_font.vf_height; i++) { 7048e6d016fSToomas Soome fb16 = (uint16_t *)(fb_info.fb + offset + i * pitch); 7058e6d016fSToomas Soome if (fb_info.shadow_fb != NULL) 7068e6d016fSToomas Soome sfb16 = (uint16_t *) 7078e6d016fSToomas Soome (fb_info.shadow_fb + offset + i * pitch); 708cbc8e155SToomas Soome for (j = 0; j < boot_fb_font.vf_width; j++) { 7098e6d016fSToomas Soome fb16[j] = (fb16[j] ^ (fg & 0xffff)) ^ 7108e6d016fSToomas Soome (bg & 0xffff); 7118e6d016fSToomas Soome 7128e6d016fSToomas Soome if (sfb16 == NULL) 7138e6d016fSToomas Soome continue; 7148e6d016fSToomas Soome 7158e6d016fSToomas Soome sfb16[j] = (sfb16[j] ^ (fg & 0xffff)) ^ 7168e6d016fSToomas Soome (bg & 0xffff); 7178e6d016fSToomas Soome } 7188e6d016fSToomas Soome } 7198e6d016fSToomas Soome break; 7208e6d016fSToomas Soome case 24: 721cbc8e155SToomas Soome for (i = 0; i < boot_fb_font.vf_height; i++) { 7228e6d016fSToomas Soome fb8 = fb_info.fb + offset + i * pitch; 7238e6d016fSToomas Soome if (fb_info.shadow_fb != NULL) 7248e6d016fSToomas Soome sfb8 = fb_info.shadow_fb + offset + i * pitch; 725cbc8e155SToomas Soome for (j = 0; j < size; j += 3) { 7268e6d016fSToomas Soome fb8[j] = (fb8[j] ^ ((fg >> 16) & 0xff)) ^ 7278e6d016fSToomas Soome ((bg >> 16) & 0xff); 7288e6d016fSToomas Soome fb8[j+1] = (fb8[j+1] ^ ((fg >> 8) & 0xff)) ^ 7298e6d016fSToomas Soome ((bg >> 8) & 0xff); 7308e6d016fSToomas Soome fb8[j+2] = (fb8[j+2] ^ (fg & 0xff)) ^ 7318e6d016fSToomas Soome (bg & 0xff); 7328e6d016fSToomas Soome 7338e6d016fSToomas Soome if (sfb8 == NULL) 7348e6d016fSToomas Soome continue; 7358e6d016fSToomas Soome 7368e6d016fSToomas Soome sfb8[j] = (sfb8[j] ^ ((fg >> 16) & 0xff)) ^ 7378e6d016fSToomas Soome ((bg >> 16) & 0xff); 7388e6d016fSToomas Soome sfb8[j+1] = (sfb8[j+1] ^ ((fg >> 8) & 0xff)) ^ 7398e6d016fSToomas Soome ((bg >> 8) & 0xff); 7408e6d016fSToomas Soome sfb8[j+2] = (sfb8[j+2] ^ (fg & 0xff)) ^ 7418e6d016fSToomas Soome (bg & 0xff); 7428e6d016fSToomas Soome } 7438e6d016fSToomas Soome } 7448e6d016fSToomas Soome break; 7458e6d016fSToomas Soome case 32: 746cbc8e155SToomas Soome for (i = 0; i < boot_fb_font.vf_height; i++) { 7478e6d016fSToomas Soome fb32 = (uint32_t *)(fb_info.fb + offset + i * pitch); 7488e6d016fSToomas Soome if (fb_info.shadow_fb != NULL) { 7498e6d016fSToomas Soome sfb32 = (uint32_t *) 7508e6d016fSToomas Soome (fb_info.shadow_fb + offset + i * pitch); 7518e6d016fSToomas Soome } 752cbc8e155SToomas Soome for (j = 0; j < boot_fb_font.vf_width; j++) { 7538e6d016fSToomas Soome fb32[j] = (fb32[j] ^ fg) ^ bg; 7548e6d016fSToomas Soome 7558e6d016fSToomas Soome if (sfb32 == NULL) 7568e6d016fSToomas Soome continue; 7578e6d016fSToomas Soome 7588e6d016fSToomas Soome sfb32[j] = (sfb32[j] ^ fg) ^ bg; 7598e6d016fSToomas Soome } 7608e6d016fSToomas Soome } 7618e6d016fSToomas Soome break; 7628e6d016fSToomas Soome } 7638e6d016fSToomas Soome } 7648e6d016fSToomas Soome 7658e6d016fSToomas Soome static void 76629a77b73SToomas Soome boot_fb_setpos(int row, int col) 7678e6d016fSToomas Soome { 76829a77b73SToomas Soome if (row < 0) 76929a77b73SToomas Soome row = 0; 77029a77b73SToomas Soome if (row >= fb_info.terminal.y) 77129a77b73SToomas Soome row = fb_info.terminal.y - 1; 77229a77b73SToomas Soome if (col < 0) 77329a77b73SToomas Soome col = 0; 77429a77b73SToomas Soome if (col >= fb_info.terminal.x) 77529a77b73SToomas Soome col = fb_info.terminal.x - 1; 77629a77b73SToomas Soome 77729a77b73SToomas Soome fb_info.cursor.pos.x = col; 77829a77b73SToomas Soome fb_info.cursor.pos.y = row; 7798e6d016fSToomas Soome fb_info.cursor.origin.x = fb_info.terminal_origin.x; 780cbc8e155SToomas Soome fb_info.cursor.origin.x += col * boot_fb_font.vf_width; 78129a77b73SToomas Soome fb_info.cursor.origin.y = fb_info.terminal_origin.y; 782cbc8e155SToomas Soome fb_info.cursor.origin.y += row * boot_fb_font.vf_height; 7838e6d016fSToomas Soome } 7848e6d016fSToomas Soome 7858e6d016fSToomas Soome static void 78629a77b73SToomas Soome boot_fb_putchar(int c) 7878e6d016fSToomas Soome { 7888e6d016fSToomas Soome struct vis_consdisplay display; 78929a77b73SToomas Soome int rows, cols; 79029a77b73SToomas Soome 79129a77b73SToomas Soome rows = fb_info.cursor.pos.y; 79229a77b73SToomas Soome cols = fb_info.cursor.pos.x; 79329a77b73SToomas Soome 79429a77b73SToomas Soome if (c == '\n') { 79529a77b73SToomas Soome if (rows < fb_info.terminal.y - 1) 79629a77b73SToomas Soome boot_fb_setpos(rows + 1, cols); 79729a77b73SToomas Soome else 79829a77b73SToomas Soome boot_fb_scroll(); 7998e6d016fSToomas Soome return; 8008e6d016fSToomas Soome } 8018e6d016fSToomas Soome 8028e6d016fSToomas Soome bit_to_pix(c); 8038e6d016fSToomas Soome display.col = fb_info.cursor.origin.x; 8048e6d016fSToomas Soome display.row = fb_info.cursor.origin.y; 805cbc8e155SToomas Soome display.width = boot_fb_font.vf_width; 806cbc8e155SToomas Soome display.height = boot_fb_font.vf_height; 8078e6d016fSToomas Soome display.data = glyph; 8088e6d016fSToomas Soome 8098e6d016fSToomas Soome boot_fb_blit(&display); 81029a77b73SToomas Soome if (cols < fb_info.terminal.x - 1) 81129a77b73SToomas Soome boot_fb_setpos(rows, cols + 1); 81229a77b73SToomas Soome else if (rows < fb_info.terminal.y - 1) 81329a77b73SToomas Soome boot_fb_setpos(rows + 1, 0); 81429a77b73SToomas Soome else { 81529a77b73SToomas Soome boot_fb_setpos(rows, 0); 81629a77b73SToomas Soome boot_fb_scroll(); 81729a77b73SToomas Soome } 8188e6d016fSToomas Soome } 819