[SeaBIOS] [PATCH 1/2] vgabios: Support emulating text mode attributes while in graphics mode

Kevin O'Connor kevin at koconnor.net
Fri Oct 31 19:58:00 CET 2014


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 at 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);
-- 
1.9.3




More information about the SeaBIOS mailing list