[SeaBIOS] [PATCH 2/2] vgabios: Add software cursor capability

Kevin O'Connor kevin at koconnor.net
Sat Oct 18 20:56:25 CEST 2014


Add mechanism for drawing a cursor to the framebuffer to implement a
cursor in software.  This can be useful for "coreboot native vga".

Signed-off-by: Kevin O'Connor <kevin at koconnor.net>
---
 vgasrc/Kconfig   |  5 +++++
 vgasrc/vgabios.c |  2 +-
 vgasrc/vgabios.h |  1 +
 vgasrc/vgafb.c   | 44 ++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 51 insertions(+), 1 deletion(-)

diff --git a/vgasrc/Kconfig b/vgasrc/Kconfig
index 6474c22..5f3cc9d 100644
--- a/vgasrc/Kconfig
+++ b/vgasrc/Kconfig
@@ -51,6 +51,7 @@ menu "VGA ROM"
             depends on COREBOOT
             bool "coreboot linear framebuffer"
             select VGA_EMULATE_TEXTATTR
+            select VGA_SOFTWARE_CURSOR
             help
                 Build support for a vgabios wrapper around video
                 devices initialized using coreboot native vga init.
@@ -89,6 +90,10 @@ menu "VGA ROM"
         help
             Try to emulate text mode attributes when writing text in
             graphics mode.
+    config VGA_SOFTWARE_CURSOR
+        bool
+        help
+            Emulate a cursor by modifying the framebuffer.
 
     config VGA_ALLOCATE_EXTRA_STACK
         depends on BUILD_VGABIOS
diff --git a/vgasrc/vgabios.c b/vgasrc/vgabios.c
index 85a060e..ab9f4a0 100644
--- a/vgasrc/vgabios.c
+++ b/vgasrc/vgabios.c
@@ -111,7 +111,7 @@ set_cursor_pos(struct cursorpos cp)
     stdvga_set_cursor_pos((int)text_address(cp));
 }
 
-static struct cursorpos
+struct cursorpos
 get_cursor_pos(u8 page)
 {
     if (page == 0xff)
diff --git a/vgasrc/vgabios.h b/vgasrc/vgabios.h
index e07309a..5abbe4e 100644
--- a/vgasrc/vgabios.h
+++ b/vgasrc/vgabios.h
@@ -115,6 +115,7 @@ struct cursorpos {
 };
 int vga_bpp(struct vgamode_s *vmode_g);
 u16 calc_page_size(u8 memmodel, u16 width, u16 height);
+struct cursorpos get_cursor_pos(u8 page);
 int bda_save_restore(int cmd, u16 seg, void *data);
 struct vgamode_s *get_current_mode(void);
 int vga_set_mode(int mode, int flags);
diff --git a/vgasrc/vgafb.c b/vgasrc/vgafb.c
index f179584..85ff184 100644
--- a/vgasrc/vgafb.c
+++ b/vgasrc/vgafb.c
@@ -454,6 +454,32 @@ gfx_write_char(struct vgamode_s *vmode_g
     }
 }
 
+// Draw/undraw a cursor on the framebuffer by xor'ing the cursor cell
+void
+gfx_set_swcursor(struct vgamode_s *vmode_g, int enable)
+{
+    struct cursorpos cp = get_cursor_pos(0xff);
+    if (cp.x >= GET_BDA(video_cols))
+        return;
+
+    struct gfx_op op;
+    init_gfx_op(&op, vmode_g);
+    op.x = cp.x * 8;
+    int cheight = GET_BDA(char_height);
+    op.y = cp.y * cheight;
+
+    int i;
+    for (i = 0; i < cheight; i++, op.y++) {
+        op.op = GO_READ8;
+        handle_gfx_op(&op);
+        int j;
+        for (j = 0; j < 8; j++)
+            op.pixels[j] ^= 0x07;
+        op.op = GO_WRITE8;
+        handle_gfx_op(&op);
+    }
+}
+
 // Set the pixel at the given position.
 void
 vgafb_write_pixel(u8 color, u16 x, u16 y)
@@ -599,4 +625,22 @@ fail: ;
 void
 vgafb_set_swcursor(int enable)
 {
+    if (!CONFIG_VGA_SOFTWARE_CURSOR)
+        return;
+
+    struct vgamode_s *vmode_g = get_current_mode();
+    if (!vmode_g)
+        return;
+
+    if (GET_GLOBAL(vmode_g->memmodel) != MM_TEXT) {
+        gfx_set_swcursor(vmode_g, enable);
+        return;
+    }
+
+    // In text mode, swap foreground and background attributes for cursor
+    struct cursorpos cp = get_cursor_pos(0xff);
+    void *dest_far = text_address(cp) + 1;
+    u8 attr = GET_FARVAR(GET_GLOBAL(vmode_g->sstart), *(u8*)dest_far);
+    attr = (attr >> 4) | (attr << 4);
+    SET_FARVAR(GET_GLOBAL(vmode_g->sstart), *(u8*)dest_far, attr);
 }
-- 
1.9.3




More information about the SeaBIOS mailing list