[SeaBIOS] [PATCH 2/4] vgabios: Add support for writing text to framebuffers in high memory.
Kevin O'Connor
kevin at koconnor.net
Wed Feb 12 18:31:41 CET 2014
Add code for manipulating "direct" style linear RGB framebuffers that
may be in high memory. This adds simple font writing and scrolling
support.
Signed-off-by: Kevin O'Connor <kevin at koconnor.net>
---
Makefile | 2 +-
vgasrc/Kconfig | 2 +
vgasrc/vgabios.h | 7 +++
vgasrc/vgafb.c | 14 +++--
vgasrc/vgahighfb.c | 154 +++++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 173 insertions(+), 6 deletions(-)
create mode 100644 vgasrc/vgahighfb.c
diff --git a/Makefile b/Makefile
index 488bd04..ffe0650 100644
--- a/Makefile
+++ b/Makefile
@@ -201,7 +201,7 @@ $(OUT)bios.bin.elf: $(OUT)rom.o $(OUT)bios.bin.prep
# VGA src files
SRCVGA=src/output.c src/string.c src/hw/pci.c src/hw/serialio.c \
- vgasrc/vgainit.c vgasrc/vgabios.c vgasrc/vgafb.c \
+ vgasrc/vgainit.c vgasrc/vgabios.c vgasrc/vgafb.c vgasrc/vgahighfb.c \
vgasrc/vgafonts.c vgasrc/vbe.c \
vgasrc/stdvga.c vgasrc/stdvgamodes.c vgasrc/stdvgaio.c \
vgasrc/clext.c vgasrc/bochsvga.c vgasrc/geodevga.c
diff --git a/vgasrc/Kconfig b/vgasrc/Kconfig
index a058a86..bdb8f5b 100644
--- a/vgasrc/Kconfig
+++ b/vgasrc/Kconfig
@@ -82,6 +82,8 @@ menu "VGA ROM"
bool
config VGA_STDVGA_FRAMEBUFFER
bool
+ config VGA_HIGH_FRAMEBUFFER
+ bool
config VGA_ALLOCATE_EXTRA_STACK
depends on BUILD_VGABIOS
diff --git a/vgasrc/vgabios.h b/vgasrc/vgabios.h
index 6949560..1e3b0b2 100644
--- a/vgasrc/vgabios.h
+++ b/vgasrc/vgabios.h
@@ -89,11 +89,18 @@ int vga_set_mode(int mode, int flags);
// vgafb.c
void vgafb_scroll(int nblines, int attr
, struct cursorpos ul, struct cursorpos lr);
+struct segoff_s get_font_data(u8 c);
void vgafb_write_char(struct cursorpos cp, struct carattr ca);
struct carattr vgafb_read_char(struct cursorpos cp);
void vgafb_write_pixel(u8 color, u16 x, u16 y);
u8 vgafb_read_pixel(u16 x, u16 y);
+// vgahighfb.c
+void scroll_direct(struct vgamode_s *vmode_g, int nblines, int attr
+ , struct cursorpos ul, struct cursorpos lr);
+void write_gfx_char_direct(struct vgamode_s *vmode_g
+ , struct cursorpos cp, struct carattr ca);
+
// vbe.c
extern u32 VBE_total_memory;
extern u32 VBE_capabilities;
diff --git a/vgasrc/vgafb.c b/vgasrc/vgafb.c
index a31db46..5da11d2 100644
--- a/vgasrc/vgafb.c
+++ b/vgasrc/vgafb.c
@@ -200,10 +200,12 @@ vgafb_scroll(int nblines, int attr, struct cursorpos ul, struct cursorpos lr)
case MM_CGA:
scroll_cga(vmode_g, nblines, attr, ul, lr);
break;
- case MM_DIRECT:
case MM_PACKED:
scroll_lin(vmode_g, nblines, attr, ul, lr);
break;
+ case MM_DIRECT:
+ scroll_direct(vmode_g, nblines, attr, ul, lr);
+ break;
default:
break;
}
@@ -214,7 +216,7 @@ vgafb_scroll(int nblines, int attr, struct cursorpos ul, struct cursorpos lr)
* Read/write characters to screen
****************************************************************/
-static struct segoff_s
+struct segoff_s
get_font_data(u8 c)
{
int char_height = GET_BDA(char_height);
@@ -369,10 +371,12 @@ vgafb_write_char(struct cursorpos cp, struct carattr ca)
case MM_CGA:
write_gfx_char_cga(vmode_g, cp, ca);
break;
- case MM_DIRECT:
case MM_PACKED:
write_gfx_char_lin(vmode_g, cp, ca);
break;
+ case MM_DIRECT:
+ write_gfx_char_direct(vmode_g, cp, ca);
+ break;
default:
break;
}
@@ -464,12 +468,12 @@ vgafb_write_pixel(u8 color, u16 x, u16 y)
}
SET_FARVAR(SEG_CTEXT, *addr_far, data);
break;
- case MM_DIRECT:
case MM_PACKED:
addr_far = (void*)(x + y * (GET_BDA(video_cols) * 8));
SET_FARVAR(SEG_GRAPH, *addr_far, color);
break;
default:
+ case MM_DIRECT:
case MM_TEXT:
return;
}
@@ -511,12 +515,12 @@ vgafb_read_pixel(u16 x, u16 y)
else
attr = (data >> (7 - (x & 0x07))) & 0x01;
break;
- case MM_DIRECT:
case MM_PACKED:
addr_far = (void*)(x + y * (GET_BDA(video_cols) * 8));
attr = GET_FARVAR(SEG_GRAPH, *addr_far);
break;
default:
+ case MM_DIRECT:
case MM_TEXT:
return 0;
}
diff --git a/vgasrc/vgahighfb.c b/vgasrc/vgahighfb.c
new file mode 100644
index 0000000..0498b16
--- /dev/null
+++ b/vgasrc/vgahighfb.c
@@ -0,0 +1,154 @@
+// Code for manipulating VGA framebuffer in high memory.
+//
+// Copyright (C) 2014 Kevin O'Connor <kevin at koconnor.net>
+//
+// This file may be distributed under the terms of the GNU LGPLv3 license.
+
+#include "biosvar.h" // GET_BDA
+#include "vgabios.h" // scroll_direct
+#include "vgahw.h" // vgahw_get_displaystart
+
+// Color mapping for various pixel depth modes.
+u16 DepthMap15[16] VAR16 = {
+ 0x0000, 0x0015, 0x02a0, 0x02b5, 0x5400, 0x5415, 0x5550, 0x56b5,
+ 0x294a, 0x295f, 0x2bea, 0x2bff, 0x7d4a, 0x7d5f, 0x7fea, 0x7fff,
+};
+u16 DepthMap16[16] VAR16 = {
+ 0x0000, 0x0015, 0x0540, 0x0555, 0xa800, 0xa815, 0xaaa0, 0xad55,
+ 0x52aa, 0x52bf, 0x57ea, 0x57ff, 0xfaaa, 0xfabf, 0xffea, 0xffff,
+};
+u32 DepthMap32[16] VAR16 = {
+ 0x000000, 0x0000aa, 0x00aa00, 0x00aaaa,
+ 0xaa0000, 0xaa00aa, 0xaa5500, 0xaaaaaa,
+ 0x555555, 0x5555ff, 0x55ff55, 0x55ffff,
+ 0xff5555, 0xff55ff, 0xffff55, 0xffffff,
+};
+
+static int
+fill_pixels(struct vgamode_s *vmode_g, void *pixels, u32 attr, u8 mask)
+{
+ int i;
+ switch (GET_GLOBAL(vmode_g->depth)) {
+ case 15:
+ for (i=0; i<8; i++)
+ *(u16*)(pixels+i*2) = GET_GLOBAL(
+ DepthMap15[mask & (0x80>>i) ? attr & 0x0f : attr >> 4]);
+ return 16;
+ case 16:
+ for (i=0; i<8; i++)
+ *(u16*)(pixels+i*2) = GET_GLOBAL(
+ DepthMap16[mask & (0x80>>i) ? attr & 0x0f : attr >> 4]);
+ return 16;
+ case 24:
+ for (i=0; i<8; i++)
+ *(u32*)(pixels+i*3) = GET_GLOBAL(
+ DepthMap32[mask & (0x80>>i) ? attr & 0x0f : attr >> 4]);
+ return 24;
+ default:
+ case 32:
+ for (i=0; i<8; i++)
+ *(u32*)(pixels+i*4) = GET_GLOBAL(
+ DepthMap32[mask & (0x80>>i) ? attr & 0x0f : attr >> 4]);
+ return 32;
+ }
+}
+
+// Use int 1587 call to copy memory to/from the framebuffer.
+static void
+memcpy_high(struct vgamode_s *vmode_g, void *dest, void *src, u32 len)
+{
+ u64 gdt[6];
+ gdt[2] = GDT_DATA | GDT_LIMIT(0xfffff) | GDT_BASE((u32)src);
+ gdt[3] = GDT_DATA | GDT_LIMIT(0xfffff) | GDT_BASE((u32)dest);
+
+ // Call int 1587 to copy data.
+ len/=2;
+ u32 flags;
+ u32 eax = 0x8700;
+ u32 si = (u32)&gdt;
+ SET_SEG(ES, GET_SEG(SS));
+ asm volatile(
+ "stc\n"
+ "int $0x15\n"
+ "cli\n"
+ "cld\n"
+ "pushfl\n"
+ "popl %0\n"
+ : "=r" (flags), "+a" (eax), "+S" (si), "+c" (len)
+ : : "cc", "memory");
+}
+
+static void
+memset_high(struct vgamode_s *vmode_g, void *dest, u32 attr, u32 len)
+{
+ u32 pixels[8];
+ u32 bpp = fill_pixels(vmode_g, pixels, attr, 0x00);
+ memcpy_high(vmode_g, dest, MAKE_FLATPTR(GET_SEG(SS), pixels), bpp);
+ memcpy_high(vmode_g, dest + bpp, dest, len - bpp);
+}
+
+// Scroll the screen.
+void
+scroll_direct(struct vgamode_s *vmode_g, int nblines, int attr
+ , struct cursorpos ul, struct cursorpos lr)
+{
+ if (!CONFIG_VGA_HIGH_FRAMEBUFFER)
+ return;
+ int cheight = GET_BDA(char_height);
+ int cwidth = vga_bpp(vmode_g);
+ int stride = vgahw_get_linelength(vmode_g);
+ nblines *= cheight;
+ void *dest_far = (void*)GET_GLOBAL(VBE_framebuffer)
+ + vgahw_get_displaystart(vmode_g);
+ u32 src_delta = nblines * stride;
+ if (nblines >= 0) {
+ dest_far += ul.y * cheight * stride + ul.x * cwidth;
+ } else {
+ // Scroll down
+ dest_far += lr.y * cheight * stride + ul.x * cwidth;
+ nblines = -nblines;
+ stride = -stride;
+ }
+ if (attr < 0)
+ attr = 0x07;
+ int cols = (lr.x - ul.x + 1) * cwidth;
+ int rows = (lr.y - ul.y + 1) * cheight;
+ int copylines = rows - nblines;
+ while (copylines--) {
+ memcpy_high(vmode_g, dest_far, dest_far + src_delta, cols);
+ dest_far += stride;
+ }
+ while (nblines--) {
+ memset_high(vmode_g, dest_far, attr, cols);
+ dest_far += stride;
+ }
+}
+
+// Write a character to the screen.
+void
+write_gfx_char_direct(struct vgamode_s *vmode_g
+ , struct cursorpos cp, struct carattr ca)
+{
+ if (!CONFIG_VGA_HIGH_FRAMEBUFFER)
+ return;
+ u16 nbcols = GET_BDA(video_cols);
+ if (cp.x >= nbcols)
+ return;
+
+ struct segoff_s font = get_font_data(ca.car);
+ int cheight = GET_BDA(char_height);
+ int cwidth = vga_bpp(vmode_g);
+ int stride = vgahw_get_linelength(vmode_g);
+ int addr = cp.y * cheight * stride + cp.x * cwidth;
+ void *dest_far = (void*)GET_GLOBAL(VBE_framebuffer)
+ + vgahw_get_displaystart(vmode_g) + addr;
+ u8 attr = ca.use_attr ? ca.attr : 0x07;
+ int i;
+ for (i = 0; i < cheight; i++) {
+ u8 fontline = GET_FARVAR(font.seg, *(u8*)(font.offset+i));
+ u32 pixels[8];
+ u32 bpp = fill_pixels(vmode_g, pixels, attr, fontline);
+ memcpy_high(vmode_g, dest_far, MAKE_FLATPTR(GET_SEG(SS), pixels), bpp);
+ dest_far += stride;
+ }
+}
--
1.8.5.3
More information about the SeaBIOS
mailing list