1/* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12/* 13 * Copyright 2016 Toomas Soome <tsoome@me.com> 14 */ 15 16/* 17 * dboot and early kernel needs simple putchar(int) interface to implement 18 * printf() support. So we implement simple interface on top of 19 * linear frame buffer, since we can not use tem directly, we are 20 * just borrowing bits from it. 21 * 22 * Note, this implementation is assuming UEFI linear frame buffer and 23 * 32-bit depth, which should not be issue as GOP is supposed to provide those. 24 * At the time of writing, this is the only case for frame buffer anyhow. 25 */ 26 27#include <sys/types.h> 28#include <sys/systm.h> 29#include <sys/multiboot2.h> 30#include <sys/framebuffer.h> 31#include <sys/bootinfo.h> 32#include <sys/boot_console.h> 33#include <sys/bootconf.h>
| 1/* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12/* 13 * Copyright 2016 Toomas Soome <tsoome@me.com> 14 */ 15 16/* 17 * dboot and early kernel needs simple putchar(int) interface to implement 18 * printf() support. So we implement simple interface on top of 19 * linear frame buffer, since we can not use tem directly, we are 20 * just borrowing bits from it. 21 * 22 * Note, this implementation is assuming UEFI linear frame buffer and 23 * 32-bit depth, which should not be issue as GOP is supposed to provide those. 24 * At the time of writing, this is the only case for frame buffer anyhow. 25 */ 26 27#include <sys/types.h> 28#include <sys/systm.h> 29#include <sys/multiboot2.h> 30#include <sys/framebuffer.h> 31#include <sys/bootinfo.h> 32#include <sys/boot_console.h> 33#include <sys/bootconf.h>
|
| 34#include "boot_console_impl.h"
|
34 35#define P2ROUNDUP(x, align) (-(-(x) & -(align))) 36#define MIN(a, b) ((a) < (b) ? (a) : (b)) 37 38/* 39 * Simplified visual_io data structures from visual_io.h 40 */ 41 42struct vis_consdisplay { 43 uint16_t row; /* Row to display data at */ 44 uint16_t col; /* Col to display data at */ 45 uint16_t width; /* Width of data */ 46 uint16_t height; /* Height of data */ 47 uint8_t *data; /* Data to display */ 48}; 49 50struct vis_conscopy { 51 uint16_t s_row; /* Starting row */ 52 uint16_t s_col; /* Starting col */ 53 uint16_t e_row; /* Ending row */ 54 uint16_t e_col; /* Ending col */ 55 uint16_t t_row; /* Row to move to */ 56 uint16_t t_col; /* Col to move to */ 57}; 58 59/* we have built in fonts 12x22, 6x10, 7x14 and depth 32. */ 60#define MAX_GLYPH (12 * 22 * 4) 61 62static struct font boot_fb_font; /* set by set_font() */ 63static uint8_t glyph[MAX_GLYPH];
| 35 36#define P2ROUNDUP(x, align) (-(-(x) & -(align))) 37#define MIN(a, b) ((a) < (b) ? (a) : (b)) 38 39/* 40 * Simplified visual_io data structures from visual_io.h 41 */ 42 43struct vis_consdisplay { 44 uint16_t row; /* Row to display data at */ 45 uint16_t col; /* Col to display data at */ 46 uint16_t width; /* Width of data */ 47 uint16_t height; /* Height of data */ 48 uint8_t *data; /* Data to display */ 49}; 50 51struct vis_conscopy { 52 uint16_t s_row; /* Starting row */ 53 uint16_t s_col; /* Starting col */ 54 uint16_t e_row; /* Ending row */ 55 uint16_t e_col; /* Ending col */ 56 uint16_t t_row; /* Row to move to */ 57 uint16_t t_col; /* Col to move to */ 58}; 59 60/* we have built in fonts 12x22, 6x10, 7x14 and depth 32. */ 61#define MAX_GLYPH (12 * 22 * 4) 62 63static struct font boot_fb_font; /* set by set_font() */ 64static uint8_t glyph[MAX_GLYPH];
|
64static uint32_t last_line_size; 65static fb_info_pixel_coord_t last_line;
| |
66 67/* color translation */ 68typedef struct { 69 uint8_t red[16]; 70 uint8_t green[16]; 71 uint8_t blue[16]; 72} text_cmap_t; 73 74/* BEGIN CSTYLED */ 75/* Bk Rd Gr Br Bl Mg Cy Wh */ 76static uint8_t dim_xlate[] = { 1, 5, 3, 7, 2, 6, 4, 8 }; 77static uint8_t brt_xlate[] = { 9, 13, 11, 15, 10, 14, 12, 0 }; 78/* END CSTYLED */ 79 80static text_cmap_t cmap4_to_24 = { 81/* BEGIN CSTYLED */ 82/* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 83 Wh+ Bk Bl Gr Cy Rd Mg Br Wh Bk+ Bl+ Gr+ Cy+ Rd+ Mg+ Yw */ 84 0xff,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x40,0x00,0x00,0x00,0xff,0xff,0xff, 85 0xff,0x00,0x00,0x80,0x80,0x00,0x00,0x80,0x80,0x40,0x00,0xff,0xff,0x00,0x00,0xff, 86 0xff,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x40,0xff,0x00,0xff,0x00,0xff,0x00 87/* END CSTYLED */ 88}; 89
| 65 66/* color translation */ 67typedef struct { 68 uint8_t red[16]; 69 uint8_t green[16]; 70 uint8_t blue[16]; 71} text_cmap_t; 72 73/* BEGIN CSTYLED */ 74/* Bk Rd Gr Br Bl Mg Cy Wh */ 75static uint8_t dim_xlate[] = { 1, 5, 3, 7, 2, 6, 4, 8 }; 76static uint8_t brt_xlate[] = { 9, 13, 11, 15, 10, 14, 12, 0 }; 77/* END CSTYLED */ 78 79static text_cmap_t cmap4_to_24 = { 80/* BEGIN CSTYLED */ 81/* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 82 Wh+ Bk Bl Gr Cy Rd Mg Br Wh Bk+ Bl+ Gr+ Cy+ Rd+ Mg+ Yw */ 83 0xff,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x40,0x00,0x00,0x00,0xff,0xff,0xff, 84 0xff,0x00,0x00,0x80,0x80,0x00,0x00,0x80,0x80,0x40,0x00,0xff,0xff,0x00,0x00,0xff, 85 0xff,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x40,0xff,0x00,0xff,0x00,0xff,0x00 86/* END CSTYLED */ 87}; 88
|
| 89static void boot_fb_putchar(int); 90static void boot_fb_eraseline(void); 91static void boot_fb_setpos(int, int); 92static void boot_fb_shiftline(int); 93static void boot_fb_eraseline_impl(uint16_t, uint16_t); 94
|
90/* 91 * extract data from MB2 framebuffer tag and set up initial frame buffer. 92 */ 93boolean_t
| 95/* 96 * extract data from MB2 framebuffer tag and set up initial frame buffer. 97 */ 98boolean_t
|
94xbi_fb_init(struct xboot_info *xbi)
| 99xbi_fb_init(struct xboot_info *xbi, bcons_dev_t *bcons_dev)
|
95{ 96 multiboot_tag_framebuffer_t *tag; 97 boot_framebuffer_t *xbi_fb; 98 99 xbi_fb = (boot_framebuffer_t *)(uintptr_t)xbi->bi_framebuffer; 100 if (xbi_fb == NULL) 101 return (B_FALSE); 102 103#if !defined(_BOOT) 104 /* For early kernel, we get cursor position from dboot. */ 105 fb_info.cursor.origin.x = xbi_fb->cursor.origin.x; 106 fb_info.cursor.origin.y = xbi_fb->cursor.origin.y; 107 fb_info.cursor.pos.x = xbi_fb->cursor.pos.x; 108 fb_info.cursor.pos.y = xbi_fb->cursor.pos.y; 109 fb_info.cursor.visible = xbi_fb->cursor.visible; 110#endif 111 112 tag = (multiboot_tag_framebuffer_t *)(uintptr_t)xbi_fb->framebuffer; 113 if (tag == NULL) { 114 return (B_FALSE); 115 } 116 117 fb_info.paddr = tag->framebuffer_common.framebuffer_addr; 118 fb_info.pitch = tag->framebuffer_common.framebuffer_pitch; 119 fb_info.depth = tag->framebuffer_common.framebuffer_bpp; 120 fb_info.bpp = P2ROUNDUP(fb_info.depth, 8) >> 3; 121 fb_info.screen.x = tag->framebuffer_common.framebuffer_width; 122 fb_info.screen.y = tag->framebuffer_common.framebuffer_height; 123 fb_info.fb_size = fb_info.screen.y * fb_info.pitch; 124
| 100{ 101 multiboot_tag_framebuffer_t *tag; 102 boot_framebuffer_t *xbi_fb; 103 104 xbi_fb = (boot_framebuffer_t *)(uintptr_t)xbi->bi_framebuffer; 105 if (xbi_fb == NULL) 106 return (B_FALSE); 107 108#if !defined(_BOOT) 109 /* For early kernel, we get cursor position from dboot. */ 110 fb_info.cursor.origin.x = xbi_fb->cursor.origin.x; 111 fb_info.cursor.origin.y = xbi_fb->cursor.origin.y; 112 fb_info.cursor.pos.x = xbi_fb->cursor.pos.x; 113 fb_info.cursor.pos.y = xbi_fb->cursor.pos.y; 114 fb_info.cursor.visible = xbi_fb->cursor.visible; 115#endif 116 117 tag = (multiboot_tag_framebuffer_t *)(uintptr_t)xbi_fb->framebuffer; 118 if (tag == NULL) { 119 return (B_FALSE); 120 } 121 122 fb_info.paddr = tag->framebuffer_common.framebuffer_addr; 123 fb_info.pitch = tag->framebuffer_common.framebuffer_pitch; 124 fb_info.depth = tag->framebuffer_common.framebuffer_bpp; 125 fb_info.bpp = P2ROUNDUP(fb_info.depth, 8) >> 3; 126 fb_info.screen.x = tag->framebuffer_common.framebuffer_width; 127 fb_info.screen.y = tag->framebuffer_common.framebuffer_height; 128 fb_info.fb_size = fb_info.screen.y * fb_info.pitch; 129
|
| 130 bcons_dev->bd_putchar = boot_fb_putchar; 131 bcons_dev->bd_eraseline = boot_fb_eraseline; 132 bcons_dev->bd_cursor = boot_fb_cursor; 133 bcons_dev->bd_setpos = boot_fb_setpos; 134 bcons_dev->bd_shift = boot_fb_shiftline; 135
|
125 if (fb_info.paddr == 0) 126 fb_info.fb_type = FB_TYPE_UNKNOWN; 127 128 switch (tag->framebuffer_common.framebuffer_type) { 129 case MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT: 130 fb_info.fb_type = FB_TYPE_EGA_TEXT; 131 return (B_FALSE); 132 133 case MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED: 134 if (fb_info.paddr != 0) 135 fb_info.fb_type = FB_TYPE_INDEXED; 136 return (B_TRUE); 137 138 case MULTIBOOT_FRAMEBUFFER_TYPE_RGB: 139 if (fb_info.paddr != 0) 140 fb_info.fb_type = FB_TYPE_RGB; 141 break; 142 143 default: 144 return (B_FALSE); 145 } 146 147 fb_info.rgb.red.size = tag->u.fb2.framebuffer_red_mask_size; 148 fb_info.rgb.red.pos = tag->u.fb2.framebuffer_red_field_position; 149 fb_info.rgb.green.size = tag->u.fb2.framebuffer_green_mask_size; 150 fb_info.rgb.green.pos = tag->u.fb2.framebuffer_green_field_position; 151 fb_info.rgb.blue.size = tag->u.fb2.framebuffer_blue_mask_size; 152 fb_info.rgb.blue.pos = tag->u.fb2.framebuffer_blue_field_position; 153 154 return (B_TRUE); 155} 156 157/* set font and pass the data to fb_info */ 158static void 159boot_fb_set_font(uint16_t height, uint16_t width) 160{ 161 short h, w; 162 163 h = MIN(height, 4096); 164 w = MIN(width, 4096); 165 166 set_font(&boot_fb_font, (short *)&fb_info.terminal.y, 167 (short *)&fb_info.terminal.x, h, w); 168 fb_info.font_width = boot_fb_font.width; 169 fb_info.font_height = boot_fb_font.height; 170} 171 172/* fill framebuffer */ 173static void 174boot_fb_fill(uint8_t *dst, uint32_t data, uint32_t len) 175{ 176 uint16_t *dst16; 177 uint32_t *dst32; 178 uint32_t i; 179 180 switch (fb_info.depth) { 181 case 24: 182 case 8: 183 for (i = 0; i < len; i++) 184 dst[i] = (uint8_t)data; 185 break; 186 case 15: 187 case 16: 188 dst16 = (uint16_t *)dst; 189 len /= 2;
| 136 if (fb_info.paddr == 0) 137 fb_info.fb_type = FB_TYPE_UNKNOWN; 138 139 switch (tag->framebuffer_common.framebuffer_type) { 140 case MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT: 141 fb_info.fb_type = FB_TYPE_EGA_TEXT; 142 return (B_FALSE); 143 144 case MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED: 145 if (fb_info.paddr != 0) 146 fb_info.fb_type = FB_TYPE_INDEXED; 147 return (B_TRUE); 148 149 case MULTIBOOT_FRAMEBUFFER_TYPE_RGB: 150 if (fb_info.paddr != 0) 151 fb_info.fb_type = FB_TYPE_RGB; 152 break; 153 154 default: 155 return (B_FALSE); 156 } 157 158 fb_info.rgb.red.size = tag->u.fb2.framebuffer_red_mask_size; 159 fb_info.rgb.red.pos = tag->u.fb2.framebuffer_red_field_position; 160 fb_info.rgb.green.size = tag->u.fb2.framebuffer_green_mask_size; 161 fb_info.rgb.green.pos = tag->u.fb2.framebuffer_green_field_position; 162 fb_info.rgb.blue.size = tag->u.fb2.framebuffer_blue_mask_size; 163 fb_info.rgb.blue.pos = tag->u.fb2.framebuffer_blue_field_position; 164 165 return (B_TRUE); 166} 167 168/* set font and pass the data to fb_info */ 169static void 170boot_fb_set_font(uint16_t height, uint16_t width) 171{ 172 short h, w; 173 174 h = MIN(height, 4096); 175 w = MIN(width, 4096); 176 177 set_font(&boot_fb_font, (short *)&fb_info.terminal.y, 178 (short *)&fb_info.terminal.x, h, w); 179 fb_info.font_width = boot_fb_font.width; 180 fb_info.font_height = boot_fb_font.height; 181} 182 183/* fill framebuffer */ 184static void 185boot_fb_fill(uint8_t *dst, uint32_t data, uint32_t len) 186{ 187 uint16_t *dst16; 188 uint32_t *dst32; 189 uint32_t i; 190 191 switch (fb_info.depth) { 192 case 24: 193 case 8: 194 for (i = 0; i < len; i++) 195 dst[i] = (uint8_t)data; 196 break; 197 case 15: 198 case 16: 199 dst16 = (uint16_t *)dst; 200 len /= 2;
|
190 for (i = 0; i < len; i++) {
| 201 for (i = 0; i < len; i++)
|
191 dst16[i] = (uint16_t)data;
| 202 dst16[i] = (uint16_t)data;
|
192 }
| |
193 break; 194 case 32: 195 dst32 = (uint32_t *)dst; 196 len /= 4;
| 203 break; 204 case 32: 205 dst32 = (uint32_t *)dst; 206 len /= 4;
|
197 for (i = 0; i < len; i++) {
| 207 for (i = 0; i < len; i++)
|
198 dst32[i] = data;
| 208 dst32[i] = data;
|
199 }
| |
200 break; 201 } 202} 203 204/* copy data to framebuffer */ 205static void 206boot_fb_cpy(uint8_t *dst, uint8_t *src, uint32_t len) 207{ 208 uint16_t *dst16, *src16; 209 uint32_t *dst32, *src32;
| 209 break; 210 } 211} 212 213/* copy data to framebuffer */ 214static void 215boot_fb_cpy(uint8_t *dst, uint8_t *src, uint32_t len) 216{ 217 uint16_t *dst16, *src16; 218 uint32_t *dst32, *src32;
|
210 uint32_t i;
| |
211 212 switch (fb_info.depth) { 213 case 24: 214 case 8:
| 219 220 switch (fb_info.depth) { 221 case 24: 222 case 8:
|
215 for (i = 0; i < len; i++) 216 dst[i] = src[i];
| 223 default: 224 if (dst <= src) { 225 do { 226 *dst++ = *src++; 227 } while (--len != 0); 228 } else { 229 dst += len; 230 src += len; 231 do { 232 *--dst = *--src; 233 } while (--len != 0); 234 }
|
217 break; 218 case 15: 219 case 16: 220 dst16 = (uint16_t *)dst; 221 src16 = (uint16_t *)src;
| 235 break; 236 case 15: 237 case 16: 238 dst16 = (uint16_t *)dst; 239 src16 = (uint16_t *)src;
|
222 for (i = 0; i < len >> 1; i++) { 223 dst16[i] = src16[i];
| 240 len /= 2; 241 if (dst16 <= src16) { 242 do { 243 *dst16++ = *src16++; 244 } while (--len != 0); 245 } else { 246 dst16 += len; 247 src16 += len; 248 do { 249 *--dst16 = *--src16; 250 } while (--len != 0);
|
224 } 225 break; 226 case 32: 227 dst32 = (uint32_t *)dst; 228 src32 = (uint32_t *)src;
| 251 } 252 break; 253 case 32: 254 dst32 = (uint32_t *)dst; 255 src32 = (uint32_t *)src;
|
229 for (i = 0; i < len >> 2; i++) { 230 dst32[i] = src32[i];
| 256 len /= 4; 257 if (dst32 <= src32) { 258 do { 259 *dst32++ = *src32++; 260 } while (--len != 0); 261 } else { 262 dst32 += len; 263 src32 += len; 264 do { 265 *--dst32 = *--src32; 266 } while (--len != 0);
|
231 } 232 break; 233 } 234} 235 236/* 237 * Allocate shadow frame buffer, called from fakebop.c when early boot 238 * allocator is ready. 239 */ 240void 241boot_fb_shadow_init(bootops_t *bops) 242{ 243 if (boot_console_type(NULL) != CONS_FRAMEBUFFER) 244 return; /* nothing to do */ 245 246 fb_info.shadow_fb = (uint8_t *)bops->bsys_alloc(NULL, NULL, 247 fb_info.fb_size, MMU_PAGESIZE); 248 249 if (fb_info.shadow_fb == NULL) 250 return; 251 252 /* Copy FB to shadow */ 253 boot_fb_cpy(fb_info.shadow_fb, fb_info.fb, fb_info.fb_size); 254} 255 256/* 257 * Translate ansi color based on inverses and brightness. 258 */
| 267 } 268 break; 269 } 270} 271 272/* 273 * Allocate shadow frame buffer, called from fakebop.c when early boot 274 * allocator is ready. 275 */ 276void 277boot_fb_shadow_init(bootops_t *bops) 278{ 279 if (boot_console_type(NULL) != CONS_FRAMEBUFFER) 280 return; /* nothing to do */ 281 282 fb_info.shadow_fb = (uint8_t *)bops->bsys_alloc(NULL, NULL, 283 fb_info.fb_size, MMU_PAGESIZE); 284 285 if (fb_info.shadow_fb == NULL) 286 return; 287 288 /* Copy FB to shadow */ 289 boot_fb_cpy(fb_info.shadow_fb, fb_info.fb, fb_info.fb_size); 290} 291 292/* 293 * Translate ansi color based on inverses and brightness. 294 */
|
259static void
| 295void
|
260boot_get_color(uint32_t *fg, uint32_t *bg) 261{ 262 /* ansi to solaris colors, see also boot_console.c */ 263 if (fb_info.inverse == B_TRUE || 264 fb_info.inverse_screen == B_TRUE) { 265 *bg = dim_xlate[fb_info.fg_color]; 266 *fg = brt_xlate[fb_info.bg_color]; 267 } else { 268 if (fb_info.bg_color == 7) 269 *bg = brt_xlate[fb_info.bg_color]; 270 else 271 *bg = dim_xlate[fb_info.bg_color]; 272 *fg = dim_xlate[fb_info.fg_color]; 273 } 274} 275 276/* 277 * Map indexed color to RGB value. 278 */ 279static uint32_t 280boot_color_map(uint8_t index) 281{ 282 uint8_t c; 283 int pos, size; 284 uint32_t color; 285 286 /* 8bit depth is for indexed colors */ 287 if (fb_info.depth == 8) 288 return (index); 289 290 if (index >= sizeof (cmap4_to_24.red)) 291 index = 0; 292 293 c = cmap4_to_24.red[index]; 294 pos = fb_info.rgb.red.pos; 295 size = fb_info.rgb.red.size; 296 color = ((c >> 8 - size) & ((1 << size) - 1)) << pos; 297 298 c = cmap4_to_24.green[index]; 299 pos = fb_info.rgb.green.pos; 300 size = fb_info.rgb.green.size; 301 color |= ((c >> 8 - size) & ((1 << size) - 1)) << pos; 302 303 c = cmap4_to_24.blue[index]; 304 pos = fb_info.rgb.blue.pos; 305 size = fb_info.rgb.blue.size; 306 color |= ((c >> 8 - size) & ((1 << size) - 1)) << pos; 307 308 return (color); 309} 310 311/* set up out simple console. */ 312/*ARGSUSED*/ 313void 314boot_fb_init(int console) 315{ 316 fb_info_pixel_coord_t window; 317 318 /* frame buffer address is mapped in dboot. */ 319 fb_info.fb = (uint8_t *)(uintptr_t)fb_info.paddr; 320 321 boot_fb_set_font(fb_info.screen.y, fb_info.screen.x); 322 window.x = 323 (fb_info.screen.x - fb_info.terminal.x * boot_fb_font.width) / 2; 324 window.y = 325 (fb_info.screen.y - fb_info.terminal.y * boot_fb_font.height) / 2; 326 fb_info.terminal_origin.x = window.x; 327 fb_info.terminal_origin.y = window.y; 328 329#if defined(_BOOT) 330 /* 331 * Being called from dboot, we can have cursor terminal 332 * position passed from boot loader. In such case, fix the 333 * cursor screen coords. 334 */ 335 if (fb_info.cursor.pos.x != 0 || fb_info.cursor.pos.y != 0) { 336 fb_info.cursor.origin.x = window.x + 337 fb_info.cursor.pos.x * boot_fb_font.width; 338 fb_info.cursor.origin.y = window.y + 339 fb_info.cursor.pos.y * boot_fb_font.height; 340 } 341#endif 342 343 /* If the cursor terminal position is 0,0 just reset screen coords */ 344 if (fb_info.cursor.pos.x == 0 && fb_info.cursor.pos.y == 0) { 345 fb_info.cursor.origin.x = window.x; 346 fb_info.cursor.origin.y = window.y; 347 } 348 349 /* 350 * Validate cursor coords with screen/terminal dimensions, 351 * if anything is off, reset to 0,0 352 */ 353 if (fb_info.cursor.pos.x > fb_info.terminal.x || 354 fb_info.cursor.pos.y > fb_info.terminal.y || 355 fb_info.cursor.origin.x > fb_info.screen.x || 356 fb_info.cursor.origin.y > fb_info.screen.y) { 357 358 fb_info.cursor.origin.x = window.x; 359 fb_info.cursor.origin.y = window.y; 360 fb_info.cursor.pos.x = 0; 361 fb_info.cursor.pos.y = 0; 362 } 363 364#if defined(_BOOT) 365 /* clear the screen if cursor is set to 0,0 */
| 296boot_get_color(uint32_t *fg, uint32_t *bg) 297{ 298 /* ansi to solaris colors, see also boot_console.c */ 299 if (fb_info.inverse == B_TRUE || 300 fb_info.inverse_screen == B_TRUE) { 301 *bg = dim_xlate[fb_info.fg_color]; 302 *fg = brt_xlate[fb_info.bg_color]; 303 } else { 304 if (fb_info.bg_color == 7) 305 *bg = brt_xlate[fb_info.bg_color]; 306 else 307 *bg = dim_xlate[fb_info.bg_color]; 308 *fg = dim_xlate[fb_info.fg_color]; 309 } 310} 311 312/* 313 * Map indexed color to RGB value. 314 */ 315static uint32_t 316boot_color_map(uint8_t index) 317{ 318 uint8_t c; 319 int pos, size; 320 uint32_t color; 321 322 /* 8bit depth is for indexed colors */ 323 if (fb_info.depth == 8) 324 return (index); 325 326 if (index >= sizeof (cmap4_to_24.red)) 327 index = 0; 328 329 c = cmap4_to_24.red[index]; 330 pos = fb_info.rgb.red.pos; 331 size = fb_info.rgb.red.size; 332 color = ((c >> 8 - size) & ((1 << size) - 1)) << pos; 333 334 c = cmap4_to_24.green[index]; 335 pos = fb_info.rgb.green.pos; 336 size = fb_info.rgb.green.size; 337 color |= ((c >> 8 - size) & ((1 << size) - 1)) << pos; 338 339 c = cmap4_to_24.blue[index]; 340 pos = fb_info.rgb.blue.pos; 341 size = fb_info.rgb.blue.size; 342 color |= ((c >> 8 - size) & ((1 << size) - 1)) << pos; 343 344 return (color); 345} 346 347/* set up out simple console. */ 348/*ARGSUSED*/ 349void 350boot_fb_init(int console) 351{ 352 fb_info_pixel_coord_t window; 353 354 /* frame buffer address is mapped in dboot. */ 355 fb_info.fb = (uint8_t *)(uintptr_t)fb_info.paddr; 356 357 boot_fb_set_font(fb_info.screen.y, fb_info.screen.x); 358 window.x = 359 (fb_info.screen.x - fb_info.terminal.x * boot_fb_font.width) / 2; 360 window.y = 361 (fb_info.screen.y - fb_info.terminal.y * boot_fb_font.height) / 2; 362 fb_info.terminal_origin.x = window.x; 363 fb_info.terminal_origin.y = window.y; 364 365#if defined(_BOOT) 366 /* 367 * Being called from dboot, we can have cursor terminal 368 * position passed from boot loader. In such case, fix the 369 * cursor screen coords. 370 */ 371 if (fb_info.cursor.pos.x != 0 || fb_info.cursor.pos.y != 0) { 372 fb_info.cursor.origin.x = window.x + 373 fb_info.cursor.pos.x * boot_fb_font.width; 374 fb_info.cursor.origin.y = window.y + 375 fb_info.cursor.pos.y * boot_fb_font.height; 376 } 377#endif 378 379 /* If the cursor terminal position is 0,0 just reset screen coords */ 380 if (fb_info.cursor.pos.x == 0 && fb_info.cursor.pos.y == 0) { 381 fb_info.cursor.origin.x = window.x; 382 fb_info.cursor.origin.y = window.y; 383 } 384 385 /* 386 * Validate cursor coords with screen/terminal dimensions, 387 * if anything is off, reset to 0,0 388 */ 389 if (fb_info.cursor.pos.x > fb_info.terminal.x || 390 fb_info.cursor.pos.y > fb_info.terminal.y || 391 fb_info.cursor.origin.x > fb_info.screen.x || 392 fb_info.cursor.origin.y > fb_info.screen.y) { 393 394 fb_info.cursor.origin.x = window.x; 395 fb_info.cursor.origin.y = window.y; 396 fb_info.cursor.pos.x = 0; 397 fb_info.cursor.pos.y = 0; 398 } 399 400#if defined(_BOOT) 401 /* clear the screen if cursor is set to 0,0 */
|
366 fb_info.cursor.pos.x = fb_info.cursor.pos.y = 0; 367 if (console == CONS_FRAMEBUFFER && 368 fb_info.cursor.pos.x == 0 && fb_info.cursor.pos.y == 0) { 369 uint32_t fg, bg; 370 int i;
| 402 if (fb_info.cursor.pos.x == 0 && fb_info.cursor.pos.y == 0) { 403 uint32_t fg, bg, toffset; 404 uint16_t y;
|
371 372 boot_get_color(&fg, &bg); 373 bg = boot_color_map(bg); 374
| 405 406 boot_get_color(&fg, &bg); 407 bg = boot_color_map(bg); 408
|
375 for (i = 0; i < fb_info.screen.y; i++) { 376 uint8_t *dest = fb_info.fb + i * fb_info.pitch;
| 409 toffset = 0; 410 for (y = 0; y < fb_info.screen.y; y++) { 411 uint8_t *dest = fb_info.fb + toffset; 412
|
377 boot_fb_fill(dest, bg, fb_info.pitch);
| 413 boot_fb_fill(dest, bg, fb_info.pitch);
|
| 414 toffset += fb_info.pitch;
|
378 } 379 } 380#endif
| 415 } 416 } 417#endif
|
381 /* set up pre-calculated last line */ 382 last_line_size = fb_info.terminal.x * boot_fb_font.width * 383 fb_info.bpp; 384 last_line.x = window.x; 385 last_line.y = window.y + (fb_info.terminal.y - 1) * boot_fb_font.height; 386
| |
387} 388 389/* copy rectangle to framebuffer. */ 390static void 391boot_fb_blit(struct vis_consdisplay *rect) 392{
| 418} 419 420/* copy rectangle to framebuffer. */ 421static void 422boot_fb_blit(struct vis_consdisplay *rect) 423{
|
393 uint32_t size; /* write size per scanline */ 394 uint8_t *fbp, *sfbp; /* fb + calculated offset */
| 424 uint32_t offset, size; /* write size per scanline */ 425 uint8_t *fbp, *sfbp = NULL; /* fb + calculated offset */
|
395 int i; 396 397 /* make sure we will not write past FB */ 398 if (rect->col >= fb_info.screen.x || 399 rect->row >= fb_info.screen.y || 400 rect->col + rect->width >= fb_info.screen.x || 401 rect->row + rect->height >= fb_info.screen.y) 402 return; 403 404 size = rect->width * fb_info.bpp;
| 426 int i; 427 428 /* make sure we will not write past FB */ 429 if (rect->col >= fb_info.screen.x || 430 rect->row >= fb_info.screen.y || 431 rect->col + rect->width >= fb_info.screen.x || 432 rect->row + rect->height >= fb_info.screen.y) 433 return; 434 435 size = rect->width * fb_info.bpp;
|
405 fbp = fb_info.fb + rect->col * fb_info.bpp + 406 rect->row * fb_info.pitch; 407 if (fb_info.shadow_fb != NULL) { 408 sfbp = fb_info.shadow_fb + rect->col * fb_info.bpp + 409 rect->row * fb_info.pitch; 410 } else { 411 sfbp = NULL; 412 }
| 436 offset = rect->col * fb_info.bpp + rect->row * fb_info.pitch; 437 fbp = fb_info.fb + offset; 438 if (fb_info.shadow_fb != NULL) 439 sfbp = fb_info.shadow_fb + offset;
|
413 414 /* write all scanlines in rectangle */ 415 for (i = 0; i < rect->height; i++) { 416 uint8_t *dest = fbp + i * fb_info.pitch; 417 uint8_t *src = rect->data + i * size; 418 boot_fb_cpy(dest, src, size); 419 if (sfbp != NULL) { 420 dest = sfbp + i * fb_info.pitch; 421 boot_fb_cpy(dest, src, size); 422 } 423 } 424} 425 426static void 427bit_to_pix(uchar_t c) 428{ 429 uint32_t fg, bg; 430 431 boot_get_color(&fg, &bg); 432 fg = boot_color_map(fg); 433 bg = boot_color_map(bg); 434 435 switch (fb_info.depth) { 436 case 8: 437 font_bit_to_pix8(&boot_fb_font, (uint8_t *)glyph, c, fg, bg); 438 break; 439 case 15: 440 case 16: 441 font_bit_to_pix16(&boot_fb_font, (uint16_t *)glyph, c, 442 (uint16_t)fg, (uint16_t)bg); 443 break; 444 case 24: 445 font_bit_to_pix24(&boot_fb_font, (uint8_t *)glyph, c, fg, bg); 446 break; 447 case 32: 448 font_bit_to_pix32(&boot_fb_font, (uint32_t *)glyph, c, fg, bg); 449 break; 450 } 451} 452
| 440 441 /* write all scanlines in rectangle */ 442 for (i = 0; i < rect->height; i++) { 443 uint8_t *dest = fbp + i * fb_info.pitch; 444 uint8_t *src = rect->data + i * size; 445 boot_fb_cpy(dest, src, size); 446 if (sfbp != NULL) { 447 dest = sfbp + i * fb_info.pitch; 448 boot_fb_cpy(dest, src, size); 449 } 450 } 451} 452 453static void 454bit_to_pix(uchar_t c) 455{ 456 uint32_t fg, bg; 457 458 boot_get_color(&fg, &bg); 459 fg = boot_color_map(fg); 460 bg = boot_color_map(bg); 461 462 switch (fb_info.depth) { 463 case 8: 464 font_bit_to_pix8(&boot_fb_font, (uint8_t *)glyph, c, fg, bg); 465 break; 466 case 15: 467 case 16: 468 font_bit_to_pix16(&boot_fb_font, (uint16_t *)glyph, c, 469 (uint16_t)fg, (uint16_t)bg); 470 break; 471 case 24: 472 font_bit_to_pix24(&boot_fb_font, (uint8_t *)glyph, c, fg, bg); 473 break; 474 case 32: 475 font_bit_to_pix32(&boot_fb_font, (uint32_t *)glyph, c, fg, bg); 476 break; 477 } 478} 479
|
453/* 454 * move the terminal window lines [1..y] to [0..y-1] and clear last line. 455 */
| |
456static void
| 480static void
|
457boot_fb_scroll(void)
| 481boot_fb_eraseline_impl(uint16_t x, uint16_t y)
|
458{
| 482{
|
459 struct vis_conscopy c_copy; 460 uint32_t soffset, toffset; 461 uint32_t width, height;
| 483 uint32_t toffset, size;
|
462 uint32_t fg, bg;
| 484 uint32_t fg, bg;
|
463 uint8_t *src, *dst, *sdst;
| 485 uint8_t *dst, *sdst;
|
464 int i; 465 466 boot_get_color(&fg, &bg); 467 bg = boot_color_map(bg); 468
| 486 int i; 487 488 boot_get_color(&fg, &bg); 489 bg = boot_color_map(bg); 490
|
469 /* support for scrolling. set up the console copy data and last line */ 470 c_copy.s_row = fb_info.terminal_origin.y + boot_fb_font.height; 471 c_copy.s_col = fb_info.terminal_origin.x; 472 c_copy.e_row = fb_info.screen.y - fb_info.terminal_origin.y; 473 c_copy.e_col = fb_info.screen.x - fb_info.terminal_origin.x; 474 c_copy.t_row = fb_info.terminal_origin.y; 475 c_copy.t_col = fb_info.terminal_origin.x;
| 491 size = fb_info.terminal.x * boot_fb_font.width * fb_info.bpp;
|
476
| 492
|
477 soffset = c_copy.s_col * fb_info.bpp + c_copy.s_row * fb_info.pitch; 478 toffset = c_copy.t_col * fb_info.bpp + c_copy.t_row * fb_info.pitch;
| 493 toffset = x * fb_info.bpp + y * fb_info.pitch; 494 dst = fb_info.fb + toffset; 495 if (fb_info.shadow_fb != NULL) 496 sdst = fb_info.shadow_fb + toffset; 497 498 for (i = 0; i < boot_fb_font.height; i++) { 499 uint8_t *dest = dst + i * fb_info.pitch; 500 if (fb_info.fb + fb_info.fb_size >= dest + size) 501 boot_fb_fill(dest, bg, size); 502 if (fb_info.shadow_fb != NULL) { 503 dest = sdst + i * fb_info.pitch; 504 if (fb_info.shadow_fb + fb_info.fb_size >= 505 dest + size) { 506 boot_fb_fill(dest, bg, size); 507 } 508 } 509 } 510} 511 512static void 513boot_fb_eraseline(void) 514{ 515 boot_fb_eraseline_impl(fb_info.cursor.origin.x, 516 fb_info.cursor.origin.y); 517} 518 519/* 520 * Copy rectangle from console to console. 521 * If shadow buffer is available, use shadow as source. 522 */ 523static void 524boot_fb_conscopy(struct vis_conscopy *c_copy) 525{ 526 uint32_t soffset, toffset; 527 uint32_t width, height, increment; 528 uint8_t *src, *dst, *sdst = NULL; 529 int i; 530 531 soffset = c_copy->s_col * fb_info.bpp + c_copy->s_row * fb_info.pitch; 532 toffset = c_copy->t_col * fb_info.bpp + c_copy->t_row * fb_info.pitch; 533 534 src = fb_info.fb + soffset; 535 dst = fb_info.fb + toffset; 536
|
479 if (fb_info.shadow_fb != NULL) { 480 src = fb_info.shadow_fb + soffset; 481 sdst = fb_info.shadow_fb + toffset;
| 537 if (fb_info.shadow_fb != NULL) { 538 src = fb_info.shadow_fb + soffset; 539 sdst = fb_info.shadow_fb + toffset;
|
482 } else { 483 src = fb_info.fb + soffset; 484 sdst = NULL;
| |
485 }
| 540 }
|
486 dst = fb_info.fb + toffset;
| |
487
| 541
|
488 width = (c_copy.e_col - c_copy.s_col + 1) * fb_info.bpp; 489 height = c_copy.e_row - c_copy.s_row + 1;
| 542 width = (c_copy->e_col - c_copy->s_col + 1) * fb_info.bpp; 543 height = c_copy->e_row - c_copy->s_row + 1; 544
|
490 for (i = 0; i < height; i++) {
| 545 for (i = 0; i < height; i++) {
|
491 uint32_t increment = i * fb_info.pitch;
| 546 increment = i * fb_info.pitch; 547 548 /* Make sure we fit into FB size. */ 549 if (soffset + increment + width >= fb_info.fb_size || 550 toffset + increment + width >= fb_info.fb_size) 551 break; 552
|
492 boot_fb_cpy(dst + increment, src + increment, width);
| 553 boot_fb_cpy(dst + increment, src + increment, width);
|
| 554
|
493 if (sdst != NULL) 494 boot_fb_cpy(sdst + increment, src + increment, width); 495 }
| 555 if (sdst != NULL) 556 boot_fb_cpy(sdst + increment, src + increment, width); 557 }
|
| 558}
|
496
| 559
|
497 /* now clean up the last line */ 498 toffset = last_line.x * fb_info.bpp + last_line.y * fb_info.pitch; 499 dst = fb_info.fb + toffset; 500 if (fb_info.shadow_fb != NULL) 501 sdst = fb_info.shadow_fb + toffset;
| 560/* Shift the line content by chars. */ 561static void 562boot_fb_shiftline(int chars) 563{ 564 struct vis_conscopy c_copy;
|
502
| 565
|
503 for (i = 0; i < boot_fb_font.height; i++) { 504 uint8_t *dest = dst + i * fb_info.pitch; 505 if (fb_info.fb + fb_info.fb_size >= dest + last_line_size) 506 boot_fb_fill(dest, bg, last_line_size); 507 if (sdst != NULL) { 508 dest = sdst + i * fb_info.pitch; 509 if (fb_info.shadow_fb + fb_info.fb_size >= 510 dest + last_line_size) { 511 boot_fb_fill(dest, bg, last_line_size); 512 } 513 } 514 }
| 566 c_copy.s_col = fb_info.cursor.origin.x; 567 c_copy.s_row = fb_info.cursor.origin.y; 568 569 c_copy.e_col = (fb_info.terminal.x - chars) * boot_fb_font.width; 570 c_copy.e_col += fb_info.terminal_origin.x; 571 c_copy.e_row = c_copy.s_row + boot_fb_font.height; 572 573 c_copy.t_col = fb_info.cursor.origin.x + chars * boot_fb_font.width; 574 c_copy.t_row = fb_info.cursor.origin.y; 575 576 boot_fb_conscopy(&c_copy);
|
515} 516 517/*
| 577} 578 579/*
|
| 580 * move the terminal window lines [1..y] to [0..y-1] and clear last line. 581 */ 582static void 583boot_fb_scroll(void) 584{ 585 struct vis_conscopy c_copy; 586 587 /* support for scrolling. set up the console copy data and last line */ 588 c_copy.s_row = fb_info.terminal_origin.y + boot_fb_font.height; 589 c_copy.s_col = fb_info.terminal_origin.x; 590 c_copy.e_row = fb_info.screen.y - fb_info.terminal_origin.y; 591 c_copy.e_col = fb_info.screen.x - fb_info.terminal_origin.x; 592 c_copy.t_row = fb_info.terminal_origin.y; 593 c_copy.t_col = fb_info.terminal_origin.x; 594 595 boot_fb_conscopy(&c_copy); 596 597 /* now clean up the last line */ 598 boot_fb_eraseline_impl(fb_info.terminal_origin.x, 599 fb_info.terminal_origin.y + 600 (fb_info.terminal.y - 1) * boot_fb_font.height); 601} 602 603/*
|
518 * Very simple block cursor. Save space below the cursor and restore 519 * when cursor is invisible. 520 */ 521void 522boot_fb_cursor(boolean_t visible) 523{ 524 uint32_t offset, size; 525 uint32_t *fb32, *sfb32 = NULL; 526 uint32_t fg, bg; 527 uint16_t *fb16, *sfb16 = NULL; 528 uint8_t *fb8, *sfb8 = NULL; 529 int i, pitch; 530 531 if (fb_info.cursor.visible == visible) 532 return; 533 534 boot_get_color(&fg, &bg); 535 fg = boot_color_map(fg); 536 bg = boot_color_map(bg); 537 538 fb_info.cursor.visible = visible; 539 pitch = fb_info.pitch; 540 size = boot_fb_font.width * fb_info.bpp; 541 542 /* 543 * Build cursor image. We are building mirror image of data on 544 * frame buffer by (D xor FG) xor BG. 545 */ 546 offset = fb_info.cursor.origin.x * fb_info.bpp + 547 fb_info.cursor.origin.y * pitch; 548 switch (fb_info.depth) { 549 case 8: 550 for (i = 0; i < boot_fb_font.height; i++) { 551 fb8 = fb_info.fb + offset + i * pitch; 552 if (fb_info.shadow_fb != NULL) 553 sfb8 = fb_info.shadow_fb + offset + i * pitch; 554 for (uint32_t j = 0; j < size; j += 1) { 555 fb8[j] = (fb8[j] ^ (fg & 0xff)) ^ (bg & 0xff); 556 557 if (sfb8 == NULL) 558 continue; 559 560 sfb8[j] = (sfb8[j] ^ (fg & 0xff)) ^ (bg & 0xff); 561 } 562 } 563 break; 564 case 15: 565 case 16: 566 for (i = 0; i < boot_fb_font.height; i++) { 567 fb16 = (uint16_t *)(fb_info.fb + offset + i * pitch); 568 if (fb_info.shadow_fb != NULL) 569 sfb16 = (uint16_t *) 570 (fb_info.shadow_fb + offset + i * pitch); 571 for (int j = 0; j < boot_fb_font.width; j++) { 572 fb16[j] = (fb16[j] ^ (fg & 0xffff)) ^ 573 (bg & 0xffff); 574 575 if (sfb16 == NULL) 576 continue; 577 578 sfb16[j] = (sfb16[j] ^ (fg & 0xffff)) ^ 579 (bg & 0xffff); 580 } 581 } 582 break; 583 case 24: 584 for (i = 0; i < boot_fb_font.height; i++) { 585 fb8 = fb_info.fb + offset + i * pitch; 586 if (fb_info.shadow_fb != NULL) 587 sfb8 = fb_info.shadow_fb + offset + i * pitch; 588 for (uint32_t j = 0; j < size; j += 3) { 589 fb8[j] = (fb8[j] ^ ((fg >> 16) & 0xff)) ^ 590 ((bg >> 16) & 0xff); 591 fb8[j+1] = (fb8[j+1] ^ ((fg >> 8) & 0xff)) ^ 592 ((bg >> 8) & 0xff); 593 fb8[j+2] = (fb8[j+2] ^ (fg & 0xff)) ^ 594 (bg & 0xff); 595 596 if (sfb8 == NULL) 597 continue; 598 599 sfb8[j] = (sfb8[j] ^ ((fg >> 16) & 0xff)) ^ 600 ((bg >> 16) & 0xff); 601 sfb8[j+1] = (sfb8[j+1] ^ ((fg >> 8) & 0xff)) ^ 602 ((bg >> 8) & 0xff); 603 sfb8[j+2] = (sfb8[j+2] ^ (fg & 0xff)) ^ 604 (bg & 0xff); 605 } 606 } 607 break; 608 case 32: 609 for (i = 0; i < boot_fb_font.height; i++) { 610 fb32 = (uint32_t *)(fb_info.fb + offset + i * pitch); 611 if (fb_info.shadow_fb != NULL) { 612 sfb32 = (uint32_t *) 613 (fb_info.shadow_fb + offset + i * pitch); 614 } 615 for (int j = 0; j < boot_fb_font.width; j++) { 616 fb32[j] = (fb32[j] ^ fg) ^ bg; 617 618 if (sfb32 == NULL) 619 continue; 620 621 sfb32[j] = (sfb32[j] ^ fg) ^ bg; 622 } 623 } 624 break; 625 } 626} 627 628static void
| 604 * Very simple block cursor. Save space below the cursor and restore 605 * when cursor is invisible. 606 */ 607void 608boot_fb_cursor(boolean_t visible) 609{ 610 uint32_t offset, size; 611 uint32_t *fb32, *sfb32 = NULL; 612 uint32_t fg, bg; 613 uint16_t *fb16, *sfb16 = NULL; 614 uint8_t *fb8, *sfb8 = NULL; 615 int i, pitch; 616 617 if (fb_info.cursor.visible == visible) 618 return; 619 620 boot_get_color(&fg, &bg); 621 fg = boot_color_map(fg); 622 bg = boot_color_map(bg); 623 624 fb_info.cursor.visible = visible; 625 pitch = fb_info.pitch; 626 size = boot_fb_font.width * fb_info.bpp; 627 628 /* 629 * Build cursor image. We are building mirror image of data on 630 * frame buffer by (D xor FG) xor BG. 631 */ 632 offset = fb_info.cursor.origin.x * fb_info.bpp + 633 fb_info.cursor.origin.y * pitch; 634 switch (fb_info.depth) { 635 case 8: 636 for (i = 0; i < boot_fb_font.height; i++) { 637 fb8 = fb_info.fb + offset + i * pitch; 638 if (fb_info.shadow_fb != NULL) 639 sfb8 = fb_info.shadow_fb + offset + i * pitch; 640 for (uint32_t j = 0; j < size; j += 1) { 641 fb8[j] = (fb8[j] ^ (fg & 0xff)) ^ (bg & 0xff); 642 643 if (sfb8 == NULL) 644 continue; 645 646 sfb8[j] = (sfb8[j] ^ (fg & 0xff)) ^ (bg & 0xff); 647 } 648 } 649 break; 650 case 15: 651 case 16: 652 for (i = 0; i < boot_fb_font.height; i++) { 653 fb16 = (uint16_t *)(fb_info.fb + offset + i * pitch); 654 if (fb_info.shadow_fb != NULL) 655 sfb16 = (uint16_t *) 656 (fb_info.shadow_fb + offset + i * pitch); 657 for (int j = 0; j < boot_fb_font.width; j++) { 658 fb16[j] = (fb16[j] ^ (fg & 0xffff)) ^ 659 (bg & 0xffff); 660 661 if (sfb16 == NULL) 662 continue; 663 664 sfb16[j] = (sfb16[j] ^ (fg & 0xffff)) ^ 665 (bg & 0xffff); 666 } 667 } 668 break; 669 case 24: 670 for (i = 0; i < boot_fb_font.height; i++) { 671 fb8 = fb_info.fb + offset + i * pitch; 672 if (fb_info.shadow_fb != NULL) 673 sfb8 = fb_info.shadow_fb + offset + i * pitch; 674 for (uint32_t j = 0; j < size; j += 3) { 675 fb8[j] = (fb8[j] ^ ((fg >> 16) & 0xff)) ^ 676 ((bg >> 16) & 0xff); 677 fb8[j+1] = (fb8[j+1] ^ ((fg >> 8) & 0xff)) ^ 678 ((bg >> 8) & 0xff); 679 fb8[j+2] = (fb8[j+2] ^ (fg & 0xff)) ^ 680 (bg & 0xff); 681 682 if (sfb8 == NULL) 683 continue; 684 685 sfb8[j] = (sfb8[j] ^ ((fg >> 16) & 0xff)) ^ 686 ((bg >> 16) & 0xff); 687 sfb8[j+1] = (sfb8[j+1] ^ ((fg >> 8) & 0xff)) ^ 688 ((bg >> 8) & 0xff); 689 sfb8[j+2] = (sfb8[j+2] ^ (fg & 0xff)) ^ 690 (bg & 0xff); 691 } 692 } 693 break; 694 case 32: 695 for (i = 0; i < boot_fb_font.height; i++) { 696 fb32 = (uint32_t *)(fb_info.fb + offset + i * pitch); 697 if (fb_info.shadow_fb != NULL) { 698 sfb32 = (uint32_t *) 699 (fb_info.shadow_fb + offset + i * pitch); 700 } 701 for (int j = 0; j < boot_fb_font.width; j++) { 702 fb32[j] = (fb32[j] ^ fg) ^ bg; 703 704 if (sfb32 == NULL) 705 continue; 706 707 sfb32[j] = (sfb32[j] ^ fg) ^ bg; 708 } 709 } 710 break; 711 } 712} 713 714static void
|
629set_cursor_row(void)
| 715boot_fb_setpos(int row, int col)
|
630{
| 716{
|
631 fb_info.cursor.pos.y++; 632 fb_info.cursor.pos.x = 0; 633 fb_info.cursor.origin.x = fb_info.terminal_origin.x;
| 717 if (row < 0) 718 row = 0; 719 if (row >= fb_info.terminal.y) 720 row = fb_info.terminal.y - 1; 721 if (col < 0) 722 col = 0; 723 if (col >= fb_info.terminal.x) 724 col = fb_info.terminal.x - 1;
|
634
| 725
|
635 if (fb_info.cursor.pos.y < fb_info.terminal.y && 636 fb_info.cursor.origin.y + boot_fb_font.height < fb_info.screen.y) { 637 fb_info.cursor.origin.y += boot_fb_font.height; 638 } else { 639 fb_info.cursor.pos.y = fb_info.terminal.y - 1; 640 /* fix the cursor origin y */ 641 fb_info.cursor.origin.y = fb_info.terminal_origin.y + 642 boot_fb_font.height * fb_info.cursor.pos.y; 643 boot_fb_scroll(); 644 }
| 726 fb_info.cursor.pos.x = col; 727 fb_info.cursor.pos.y = row; 728 fb_info.cursor.origin.x = fb_info.terminal_origin.x; 729 fb_info.cursor.origin.x += col * boot_fb_font.width; 730 fb_info.cursor.origin.y = fb_info.terminal_origin.y; 731 fb_info.cursor.origin.y += row * boot_fb_font.height;
|
645} 646 647static void
| 732} 733 734static void
|
648set_cursor_col(void)
| 735boot_fb_putchar(int c)
|
649{
| 736{
|
650 fb_info.cursor.pos.x++; 651 if (fb_info.cursor.pos.x < fb_info.terminal.x && 652 fb_info.cursor.origin.x + boot_fb_font.width < fb_info.screen.x) { 653 fb_info.cursor.origin.x += boot_fb_font.width; 654 } else { 655 fb_info.cursor.pos.x = 0; 656 fb_info.cursor.origin.x = fb_info.terminal_origin.x; 657 set_cursor_row(); 658 } 659} 660 661void 662boot_fb_putchar(uint8_t c) 663{
| |
664 struct vis_consdisplay display;
| 737 struct vis_consdisplay display;
|
665 boolean_t bs = B_FALSE;
| 738 int rows, cols;
|
666
| 739
|
667 /* early tem startup will switch cursor off, if so, keep it off */ 668 boot_fb_cursor(B_FALSE); /* cursor off */ 669 switch (c) { 670 case '\n': 671 set_cursor_row(); 672 boot_fb_cursor(B_TRUE);
| 740 rows = fb_info.cursor.pos.y; 741 cols = fb_info.cursor.pos.x; 742 743 if (c == '\n') { 744 if (rows < fb_info.terminal.y - 1) 745 boot_fb_setpos(rows + 1, cols); 746 else 747 boot_fb_scroll();
|
673 return;
| 748 return;
|
674 case '\r': 675 fb_info.cursor.pos.x = 0; 676 fb_info.cursor.origin.x = fb_info.terminal_origin.x; 677 boot_fb_cursor(B_TRUE); 678 return; 679 case '\b': 680 if (fb_info.cursor.pos.x > 0) { 681 fb_info.cursor.pos.x--; 682 fb_info.cursor.origin.x -= boot_fb_font.width; 683 } 684 c = ' '; 685 bs = B_TRUE; 686 break;
| |
687 } 688 689 bit_to_pix(c); 690 display.col = fb_info.cursor.origin.x; 691 display.row = fb_info.cursor.origin.y; 692 display.width = boot_fb_font.width; 693 display.height = boot_fb_font.height; 694 display.data = glyph; 695 696 boot_fb_blit(&display);
| 749 } 750 751 bit_to_pix(c); 752 display.col = fb_info.cursor.origin.x; 753 display.row = fb_info.cursor.origin.y; 754 display.width = boot_fb_font.width; 755 display.height = boot_fb_font.height; 756 display.data = glyph; 757 758 boot_fb_blit(&display);
|
697 if (bs == B_FALSE) 698 set_cursor_col(); 699 boot_fb_cursor(B_TRUE);
| 759 if (cols < fb_info.terminal.x - 1) 760 boot_fb_setpos(rows, cols + 1); 761 else if (rows < fb_info.terminal.y - 1) 762 boot_fb_setpos(rows + 1, 0); 763 else { 764 boot_fb_setpos(rows, 0); 765 boot_fb_scroll(); 766 }
|
700}
| 767}
|