Add support for simple text mode attribute emulation while in graphics mode. This improves text highlighting and background color on some boot-loaders. Enable it only for CBVGA vgabios and only when a text mode is requested.
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- vgasrc/Kconfig | 6 ++++++ vgasrc/cbvga.c | 10 +++++++--- vgasrc/vbe.c | 5 ++--- vgasrc/vgabios.h | 10 +++++++++- vgasrc/vgafb.c | 26 +++++++++++++++++++++++--- 5 files changed, 47 insertions(+), 10 deletions(-)
diff --git a/vgasrc/Kconfig b/vgasrc/Kconfig index 951240c..400e8da 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_TEXT 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_TEXT + bool + help + Support emulating text mode features when only a + framebuffer is available.
config VGA_ALLOCATE_EXTRA_STACK depends on BUILD_VGABIOS diff --git a/vgasrc/cbvga.c b/vgasrc/cbvga.c index a9c6d3a..3acc839 100644 --- a/vgasrc/cbvga.c +++ b/vgasrc/cbvga.c @@ -14,12 +14,15 @@
static int CBmode VAR16; static struct vgamode_s CBmodeinfo VAR16; +static struct vgamode_s CBemulinfo VAR16; static u32 CBlinelength VAR16;
struct vgamode_s *cbvga_find_mode(int mode) { if (mode == GET_GLOBAL(CBmode)) return &CBmodeinfo; + if (mode == 0x03) + return &CBemulinfo; return NULL; }
@@ -92,6 +95,8 @@ cbvga_save_restore(int cmd, u16 seg, void *data) int cbvga_set_mode(struct vgamode_s *vmode_g, int flags) { + MASK_BDA_EXT(flags, BF_EMULATE_TEXT + , (vmode_g == &CBemulinfo) ? BF_EMULATE_TEXT : 0); if (!(flags & MF_NOCLEARMEM)) { if (GET_GLOBAL(CBmodeinfo.memmodel) == MM_TEXT) { memset16_far(SEG_CTEXT, (void*)0, 0x0720, 80*25*2); @@ -181,9 +186,8 @@ cbvga_setup(void) SET_VGA(CBmodeinfo.depth, bpp); SET_VGA(CBmodeinfo.cwidth, 8); SET_VGA(CBmodeinfo.cheight, 16); - - // Setup BDA and clear screen. - vga_set_mode(GET_GLOBAL(CBmode), 0); + memcpy_far(get_global_seg(), &CBemulinfo + , get_global_seg(), &CBmodeinfo, sizeof(CBemulinfo));
return 0; } diff --git a/vgasrc/vbe.c b/vgasrc/vbe.c index e2aeced..af3d0cc 100644 --- a/vgasrc/vbe.c +++ b/vgasrc/vbe.c @@ -381,9 +381,8 @@ vbe_104f10(struct bregs *regs) case 0x00: regs->bx = 0x0f30; break; - case 0x01: ; - u8 flags = GET_BDA_EXT(flags); - SET_BDA_EXT(flags, (flags & ~BF_PM_MASK) | (regs->bh & BF_PM_MASK)); + case 0x01: + MASK_BDA_EXT(flags, BF_PM_MASK, regs->bh & BF_PM_MASK); break; case 0x02: regs->bh = GET_BDA_EXT(flags) & BF_PM_MASK; diff --git a/vgasrc/vgabios.h b/vgasrc/vgabios.h index d06ebb4..344b3d9 100644 --- a/vgasrc/vgabios.h +++ b/vgasrc/vgabios.h @@ -1,6 +1,7 @@ #ifndef __VGABIOS_H #define __VGABIOS_H
+#include "config.h" // CONFIG_VGA_EMULATE_TEXT #include "types.h" // u8 #include "farptr.h" // struct segoff_s #include "std/vga.h" // struct video_param_s @@ -70,12 +71,19 @@ struct vga_bda_s { u16 vgamode_offset; } PACKED;
-#define BF_PM_MASK 0x0f +#define BF_PM_MASK 0x0f +#define BF_EMULATE_TEXT 0x10
#define GET_BDA_EXT(var) \ GET_FARVAR(SEG_BDA, ((struct vga_bda_s *)VGA_CUSTOM_BDA)->var) #define SET_BDA_EXT(var, val) \ SET_FARVAR(SEG_BDA, ((struct vga_bda_s *)VGA_CUSTOM_BDA)->var, (val)) +#define MASK_BDA_EXT(var, off, on) \ + SET_BDA_EXT(var, (GET_BDA_EXT(var) & ~(off)) | (on)) + +static inline int vga_emulate_text(void) { + return CONFIG_VGA_EMULATE_TEXT && GET_BDA_EXT(flags) & BF_EMULATE_TEXT; +}
// Debug settings #define DEBUG_VGA_POST 1 diff --git a/vgasrc/vgafb.c b/vgasrc/vgafb.c index bb27660..e6a4a4c 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 (vga_emulate_text()) + 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 (vga_emulate_text()) { + 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);