Deleted Added
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

--- 17 unchanged lines hidden (view full) ---

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
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

--- 14 unchanged lines hidden (view full) ---

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];
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

--- 8 unchanged lines hidden (view full) ---

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
90/*
91 * extract data from MB2 framebuffer tag and set up initial frame buffer.
92 */
93boolean_t
94xbi_fb_init(struct xboot_info *xbi)
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

--- 14 unchanged lines hidden (view full) ---

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
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

--- 49 unchanged lines hidden (view full) ---

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;
190 for (i = 0; i < len; i++) {
191 dst16[i] = (uint16_t)data;
192 }
193 break;
194 case 32:
195 dst32 = (uint32_t *)dst;
196 len /= 4;
197 for (i = 0; i < len; i++) {
198 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;
210 uint32_t i;
211
212 switch (fb_info.depth) {
213 case 24:
214 case 8:
215 for (i = 0; i < len; i++)
216 dst[i] = src[i];
217 break;
218 case 15:
219 case 16:
220 dst16 = (uint16_t *)dst;
221 src16 = (uint16_t *)src;
222 for (i = 0; i < len >> 1; i++) {
223 dst16[i] = src16[i];
224 }
225 break;
226 case 32:
227 dst32 = (uint32_t *)dst;
228 src32 = (uint32_t *)src;
229 for (i = 0; i < len >> 2; i++) {
230 dst32[i] = src32[i];
231 }
232 break;
233 }
234}
235
236/*
237 * Allocate shadow frame buffer, called from fakebop.c when early boot
238 * allocator is ready.

--- 12 unchanged lines hidden (view full) ---

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 */
259static void
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 {

--- 90 unchanged lines hidden (view full) ---

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 */
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;
371
372 boot_get_color(&fg, &bg);
373 bg = boot_color_map(bg);
374
375 for (i = 0; i < fb_info.screen.y; i++) {
376 uint8_t *dest = fb_info.fb + i * fb_info.pitch;
377 boot_fb_fill(dest, bg, fb_info.pitch);
378 }
379 }
380#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{
393 uint32_t size; /* write size per scanline */
394 uint8_t *fbp, *sfbp; /* 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;
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 }
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;

--- 24 unchanged lines hidden (view full) ---

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
453/*
454 * move the terminal window lines [1..y] to [0..y-1] and clear last line.
455 */
456static void
457boot_fb_scroll(void)
458{
459 struct vis_conscopy c_copy;
460 uint32_t soffset, toffset;
461 uint32_t width, height;
462 uint32_t fg, bg;
463 uint8_t *src, *dst, *sdst;
464 int i;
465
466 boot_get_color(&fg, &bg);
467 bg = boot_color_map(bg);
468
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;
476
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;
479 if (fb_info.shadow_fb != NULL) {
480 src = fb_info.shadow_fb + soffset;
481 sdst = fb_info.shadow_fb + toffset;
482 } else {
483 src = fb_info.fb + soffset;
484 sdst = NULL;
485 }
486 dst = fb_info.fb + toffset;
487
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;
490 for (i = 0; i < height; i++) {
491 uint32_t increment = i * fb_info.pitch;
492 boot_fb_cpy(dst + increment, src + increment, width);
493 if (sdst != NULL)
494 boot_fb_cpy(sdst + increment, src + increment, width);
495 }
496
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;
502
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 }
515}
516
517/*
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;

--- 95 unchanged lines hidden (view full) ---

621 sfb32[j] = (sfb32[j] ^ fg) ^ bg;
622 }
623 }
624 break;
625 }
626}
627
628static void
629set_cursor_row(void)
630{
631 fb_info.cursor.pos.y++;
632 fb_info.cursor.pos.x = 0;
633 fb_info.cursor.origin.x = fb_info.terminal_origin.x;
634
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 }
645}
646
647static void
648set_cursor_col(void)
649{
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;
665 boolean_t bs = B_FALSE;
666
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);
673 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);
697 if (bs == B_FALSE)
698 set_cursor_col();
699 boot_fb_cursor(B_TRUE);
700}