These two patches enable better support for text highlighting and colors when using the "coreboot native vga" seavgabios option rom. It is a bit of a hack, but seems to improve things in a couple of boot loaders I tested.
This is also at (along with the previous usb series): https://github.com/KevinOConnor/seabios/tree/testing
-Kevin
Kevin O'Connor (2): vgabios: Add support for reading framebuffer in "direct" mode vgabios: Add support handling text mode attributes while in graphics mode
vgasrc/Kconfig | 6 ++++++ vgasrc/vgafb.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 61 insertions(+), 8 deletions(-)
Support reading high memory "direct" framebuffers and translating the results to 8 bit attribute values.
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- vgasrc/vgafb.c | 37 ++++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-)
diff --git a/vgasrc/vgafb.c b/vgasrc/vgafb.c index fdc525d..e67244f 100644 --- a/vgasrc/vgafb.c +++ b/vgasrc/vgafb.c @@ -236,9 +236,31 @@ get_color(int depth, u8 attr) int r = (attr&4) ? 2 : 0, g = (attr&2) ? 2 : 0, b = (attr&1) ? 2 : 0; if ((attr & 0xf) == 6) g = 1; - return ((((((1<<rbits) - 1) * (r + h) + 1) / 3) << (gbits+bbits)) - + (((((1<<gbits) - 1) * (g + h) + 1) / 3) << bbits) - + ((((1<<bbits) - 1) * (b + h) + 1) / 3)); + int rv = DIV_ROUND_CLOSEST(((1<<rbits) - 1) * (r + h), 3); + int gv = DIV_ROUND_CLOSEST(((1<<gbits) - 1) * (g + h), 3); + int bv = DIV_ROUND_CLOSEST(((1<<bbits) - 1) * (b + h), 3); + return (rv << (gbits+bbits)) + (gv << bbits) + bv; +} + +// Find the closest attribute for a given framebuffer color +static u8 +reverse_color(int depth, u32 color) +{ + int rbits, gbits, bbits; + switch (depth) { + case 15: rbits=5; gbits=5; bbits=5; break; + case 16: rbits=5; gbits=6; bbits=5; break; + default: + case 24: rbits=8; gbits=8; bbits=8; break; + } + int rv = (color >> (gbits+bbits)) & ((1<<rbits)-1); + int gv = (color >> bbits) & ((1<<gbits)-1); + int bv = color & ((1<<bbits)-1); + int r = DIV_ROUND_CLOSEST(rv * 3, (1<<rbits) - 1); + int g = DIV_ROUND_CLOSEST(gv * 3, (1<<gbits) - 1); + int b = DIV_ROUND_CLOSEST(bv * 3, (1<<bbits) - 1); + int h = r && g && b && (r != 2 || g != 2 || b != 2); + return (h ? 8 : 0) | ((r-h) ? 4 : 0) | ((g-h) ? 2 : 0) | ((b-h) ? 1 : 0); }
static void @@ -253,9 +275,14 @@ gfx_direct(struct gfx_op *op) + op->x * bypp); switch (op->op) { default: - case GO_READ8: - // XXX - not implemented. + case GO_READ8: { + u8 data[64]; + memcpy_high(MAKE_FLATPTR(GET_SEG(SS), data), dest_far, bypp * 8); + int i; + for (i=0; i<8; i++) + op->pixels[i] = reverse_color(depth, *(u32*)&data[i*bypp]); break; + } case GO_WRITE8: { u8 data[64]; int i;
Add support for simple text mode attribute emulation while in graphics mode. This seems to help with text highlighting and colors with a few boot-loaders. Turn it on only for CBVGA vgabios.
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- vgasrc/Kconfig | 6 ++++++ vgasrc/vgafb.c | 26 +++++++++++++++++++++++--- 2 files changed, 29 insertions(+), 3 deletions(-)
diff --git a/vgasrc/Kconfig b/vgasrc/Kconfig index 951240c..6474c22 100644 --- a/vgasrc/Kconfig +++ b/vgasrc/Kconfig @@ -50,6 +50,7 @@ menu "VGA ROM" config VGA_COREBOOT depends on COREBOOT bool "coreboot linear framebuffer" + select VGA_EMULATE_TEXTATTR help Build support for a vgabios wrapper around video devices initialized using coreboot native vga init. @@ -83,6 +84,11 @@ menu "VGA ROM"
config VGA_STDVGA_PORTS bool + config VGA_EMULATE_TEXTATTR + bool + help + Try to emulate text mode attributes when writing text in + graphics mode.
config VGA_ALLOCATE_EXTRA_STACK depends on BUILD_VGABIOS diff --git a/vgasrc/vgafb.c b/vgasrc/vgafb.c index e67244f..74ddc53 100644 --- a/vgasrc/vgafb.c +++ b/vgasrc/vgafb.c @@ -380,6 +380,8 @@ gfx_clear_chars(struct vgamode_s *vmode_g, struct cursorpos dest op.y = dest.y * cheight; op.ylen = clearsize.y * cheight; op.pixels[0] = ca.attr; + if (CONFIG_VGA_EMULATE_TEXTATTR) + op.pixels[0] = ca.attr >> 4; op.op = GO_MEMSET; handle_gfx_op(&op); } @@ -414,7 +416,25 @@ gfx_write_char(struct vgamode_s *vmode_g op.x = cp.x * 8; int cheight = GET_BDA(char_height); op.y = cp.y * cheight; - int usexor = ca.attr & 0x80 && GET_GLOBAL(vmode_g->depth) < 8; + u8 fgattr = ca.attr, bgattr = 0x00; + int usexor = 0; + if (CONFIG_VGA_EMULATE_TEXTATTR) { + if (ca.use_attr) { + bgattr = fgattr >> 4; + fgattr = fgattr & 0x0f; + } else { + // Read bottom right pixel of the cell to guess bg color + op.op = GO_READ8; + op.y += cheight-1; + handle_gfx_op(&op); + op.y -= cheight-1; + bgattr = op.pixels[7]; + fgattr = bgattr ^ 0x7; + } + } else if (fgattr & 0x80 && GET_GLOBAL(vmode_g->depth) < 8) { + usexor = 1; + fgattr &= 0x7f; + } int i; for (i = 0; i < cheight; i++, op.y++) { u8 fontline = GET_FARVAR(font.seg, *(u8*)(font.offset+i)); @@ -423,11 +443,11 @@ gfx_write_char(struct vgamode_s *vmode_g handle_gfx_op(&op); int j; for (j = 0; j < 8; j++) - op.pixels[j] ^= (fontline & (0x80>>j)) ? (ca.attr & 0x7f) : 0x00; + op.pixels[j] ^= (fontline & (0x80>>j)) ? fgattr : 0x00; } else { int j; for (j = 0; j < 8; j++) - op.pixels[j] = (fontline & (0x80>>j)) ? ca.attr : 0x00; + op.pixels[j] = (fontline & (0x80>>j)) ? fgattr : bgattr; } op.op = GO_WRITE8; handle_gfx_op(&op);