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@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); }