qemu: add bochs-display support

Use coreboot text mode emulation to also support the qemu bochs-display
device.  This is a new display device supporting simple linear
framebuffers, using the bochs register interface.  No support for legacy
vga (text modes, planar modes, cga modes, 8bpp palette modes all
dropped).  The bochs interface is compatible with the qemu stdvga.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
This commit is contained in:
Gerd Hoffmann 2017-11-15 14:43:10 +01:00
parent 4d70b24b86
commit 77404b450d
5 changed files with 95 additions and 14 deletions

View File

@ -213,7 +213,7 @@ SRCVGA=src/output.c src/string.c src/hw/pci.c src/hw/serialio.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 \
src/fw/coreboot.c vgasrc/cbvga.c
src/fw/coreboot.c vgasrc/cbvga.c vgasrc/bochsdisplay.c
ifeq "$(CONFIG_VGA_FIXUP_ASM)" "y"
$(OUT)vgaccode16.raw.s: $(OUT)autoconf.h $(patsubst %.c, $(OUT)%.o,$(SRCVGA)) ; $(call whole-compile, $(filter-out -fomit-frame-pointer,$(CFLAGS16)) -fno-omit-frame-pointer -S -Isrc, $(SRCVGA),$@)

View File

@ -55,6 +55,21 @@ menu "VGA ROM"
Build support for a vgabios wrapper around video
devices initialized using coreboot native vga init.
config DISPLAY_BOCHS
depends on QEMU
bool "qemu bochs-display support"
select VGA_EMULATE_TEXT
help
Build support for the qemu bochs-display device, which
is basically qemu stdvga without the legacy vga
emulation, supporting only 16+32 bpp VESA video modes
in a linear framebuffer. So this uses cbvga text mode
emulation.
The bochs-display device is available in qemu
v3.0+. The vgabios works with the qemu stdvga too (use
"qemu -device VGA,romfile=/path/to/vgabios.bin")".
endchoice
choice
@ -166,6 +181,7 @@ menu "VGA ROM"
default 0x1af4 if VGA_BOCHS_VIRTIO
default 0x100b if VGA_GEODEGX2
default 0x1022 if VGA_GEODELX
default 0x1234 if DISPLAY_BOCHS
default 0x0000
help
Vendor ID for the PCI ROM
@ -181,6 +197,7 @@ menu "VGA ROM"
default 0x1050 if VGA_BOCHS_VIRTIO
default 0x0030 if VGA_GEODEGX2
default 0x2081 if VGA_GEODELX
default 0x1111 if DISPLAY_BOCHS
default 0x0000
help
Device ID for the PCI ROM

59
vgasrc/bochsdisplay.c Normal file
View File

@ -0,0 +1,59 @@
#include "biosvar.h" // GET_BDA
#include "output.h" // dprintf
#include "string.h" // memset16_far
#include "bochsvga.h" // VBE_BOCHS_*
#include "hw/pci.h" // pci_config_readl
#include "hw/pci_regs.h" // PCI_BASE_ADDRESS_0
#include "vgautil.h" // VBE_total_memory
#define FRAMEBUFFER_WIDTH 1024
#define FRAMEBUFFER_HEIGHT 768
#define FRAMEBUFFER_BPP 4
#define FRAMEBUFFER_STRIDE (FRAMEBUFFER_BPP * FRAMEBUFFER_WIDTH)
#define FRAMEBUFFER_SIZE (FRAMEBUFFER_STRIDE * FRAMEBUFFER_HEIGHT)
int
bochs_display_setup(void)
{
dprintf(1, "bochs-display: setup called\n");
if (GET_GLOBAL(HaveRunInit))
return 0;
int bdf = GET_GLOBAL(VgaBDF);
if (bdf == 0)
return 0;
u32 bar = pci_config_readl(bdf, PCI_BASE_ADDRESS_0);
u32 lfb_addr = bar & PCI_BASE_ADDRESS_MEM_MASK;
bar = pci_config_readl(bdf, PCI_BASE_ADDRESS_2);
u32 io_addr = bar & PCI_BASE_ADDRESS_IO_MASK;
dprintf(1, "bochs-display: bdf %02x:%02x.%x, bar 0 at 0x%x, bar 1 at 0x%x\n"
, pci_bdf_to_bus(bdf) , pci_bdf_to_dev(bdf), pci_bdf_to_fn(bdf),
lfb_addr, io_addr);
u16 *dispi = (void*)(io_addr + 0x500);
u8 *vga = (void*)(io_addr + 0x400);
u16 id = readw(dispi + VBE_DISPI_INDEX_ID);
dprintf(1, "bochs-display: id is 0x%x, %s\n", id
, id == VBE_DISPI_ID5 ? "good" : "FAIL");
if (id != VBE_DISPI_ID5)
return 0;
dprintf(1, "bochs-display: using %dx%d, %d bpp (%d stride)\n"
, FRAMEBUFFER_WIDTH, FRAMEBUFFER_HEIGHT
, FRAMEBUFFER_BPP * 8, FRAMEBUFFER_STRIDE);
cbvga_setup_modes(lfb_addr, FRAMEBUFFER_BPP * 8,
FRAMEBUFFER_WIDTH, FRAMEBUFFER_HEIGHT,
FRAMEBUFFER_STRIDE);
writew(dispi + VBE_DISPI_INDEX_XRES, FRAMEBUFFER_WIDTH);
writew(dispi + VBE_DISPI_INDEX_YRES, FRAMEBUFFER_HEIGHT);
writew(dispi + VBE_DISPI_INDEX_BPP, FRAMEBUFFER_BPP * 8);
writew(dispi + VBE_DISPI_INDEX_ENABLE, VBE_DISPI_ENABLED);
writeb(vga, 0x20); /* unblank (for qemu -device VGA) */
return 0;
}

View File

@ -14,7 +14,7 @@ static inline struct vgamode_s *vgahw_find_mode(int mode) {
return clext_find_mode(mode);
if (CONFIG_VGA_BOCHS)
return bochsvga_find_mode(mode);
if (CONFIG_VGA_COREBOOT)
if (CONFIG_VGA_COREBOOT || CONFIG_DISPLAY_BOCHS)
return cbvga_find_mode(mode);
return stdvga_find_mode(mode);
}
@ -24,7 +24,7 @@ static inline int vgahw_set_mode(struct vgamode_s *vmode_g, int flags) {
return clext_set_mode(vmode_g, flags);
if (CONFIG_VGA_BOCHS)
return bochsvga_set_mode(vmode_g, flags);
if (CONFIG_VGA_COREBOOT)
if (CONFIG_VGA_COREBOOT || CONFIG_DISPLAY_BOCHS)
return cbvga_set_mode(vmode_g, flags);
return stdvga_set_mode(vmode_g, flags);
}
@ -34,7 +34,7 @@ static inline void vgahw_list_modes(u16 seg, u16 *dest, u16 *last) {
clext_list_modes(seg, dest, last);
else if (CONFIG_VGA_BOCHS)
bochsvga_list_modes(seg, dest, last);
else if (CONFIG_VGA_COREBOOT)
else if (CONFIG_VGA_COREBOOT || CONFIG_DISPLAY_BOCHS)
cbvga_list_modes(seg, dest, last);
else
stdvga_list_modes(seg, dest, last);
@ -49,6 +49,8 @@ static inline int vgahw_setup(void) {
return geodevga_setup();
if (CONFIG_VGA_COREBOOT)
return cbvga_setup();
if (CONFIG_DISPLAY_BOCHS)
return bochs_display_setup();
return stdvga_setup();
}
@ -57,7 +59,7 @@ static inline int vgahw_get_window(struct vgamode_s *vmode_g, int window) {
return clext_get_window(vmode_g, window);
if (CONFIG_VGA_BOCHS)
return bochsvga_get_window(vmode_g, window);
if (CONFIG_VGA_COREBOOT)
if (CONFIG_VGA_COREBOOT || CONFIG_DISPLAY_BOCHS)
return cbvga_get_window(vmode_g, window);
return stdvga_get_window(vmode_g, window);
}
@ -68,7 +70,7 @@ static inline int vgahw_set_window(struct vgamode_s *vmode_g, int window
return clext_set_window(vmode_g, window, val);
if (CONFIG_VGA_BOCHS)
return bochsvga_set_window(vmode_g, window, val);
if (CONFIG_VGA_COREBOOT)
if (CONFIG_VGA_COREBOOT || CONFIG_DISPLAY_BOCHS)
return cbvga_set_window(vmode_g, window, val);
return stdvga_set_window(vmode_g, window, val);
}
@ -78,7 +80,7 @@ static inline int vgahw_get_linelength(struct vgamode_s *vmode_g) {
return clext_get_linelength(vmode_g);
if (CONFIG_VGA_BOCHS)
return bochsvga_get_linelength(vmode_g);
if (CONFIG_VGA_COREBOOT)
if (CONFIG_VGA_COREBOOT || CONFIG_DISPLAY_BOCHS)
return cbvga_get_linelength(vmode_g);
return stdvga_get_linelength(vmode_g);
}
@ -88,7 +90,7 @@ static inline int vgahw_set_linelength(struct vgamode_s *vmode_g, int val) {
return clext_set_linelength(vmode_g, val);
if (CONFIG_VGA_BOCHS)
return bochsvga_set_linelength(vmode_g, val);
if (CONFIG_VGA_COREBOOT)
if (CONFIG_VGA_COREBOOT || CONFIG_DISPLAY_BOCHS)
return cbvga_set_linelength(vmode_g, val);
return stdvga_set_linelength(vmode_g, val);
}
@ -98,7 +100,7 @@ static inline int vgahw_get_displaystart(struct vgamode_s *vmode_g) {
return clext_get_displaystart(vmode_g);
if (CONFIG_VGA_BOCHS)
return bochsvga_get_displaystart(vmode_g);
if (CONFIG_VGA_COREBOOT)
if (CONFIG_VGA_COREBOOT || CONFIG_DISPLAY_BOCHS)
return cbvga_get_displaystart(vmode_g);
return stdvga_get_displaystart(vmode_g);
}
@ -108,7 +110,7 @@ static inline int vgahw_set_displaystart(struct vgamode_s *vmode_g, int val) {
return clext_set_displaystart(vmode_g, val);
if (CONFIG_VGA_BOCHS)
return bochsvga_set_displaystart(vmode_g, val);
if (CONFIG_VGA_COREBOOT)
if (CONFIG_VGA_COREBOOT || CONFIG_DISPLAY_BOCHS)
return cbvga_set_displaystart(vmode_g, val);
return stdvga_set_displaystart(vmode_g, val);
}
@ -116,7 +118,7 @@ static inline int vgahw_set_displaystart(struct vgamode_s *vmode_g, int val) {
static inline int vgahw_get_dacformat(struct vgamode_s *vmode_g) {
if (CONFIG_VGA_BOCHS)
return bochsvga_get_dacformat(vmode_g);
if (CONFIG_VGA_COREBOOT)
if (CONFIG_VGA_COREBOOT || CONFIG_DISPLAY_BOCHS)
return cbvga_get_dacformat(vmode_g);
return stdvga_get_dacformat(vmode_g);
}
@ -124,7 +126,7 @@ static inline int vgahw_get_dacformat(struct vgamode_s *vmode_g) {
static inline int vgahw_set_dacformat(struct vgamode_s *vmode_g, int val) {
if (CONFIG_VGA_BOCHS)
return bochsvga_set_dacformat(vmode_g, val);
if (CONFIG_VGA_COREBOOT)
if (CONFIG_VGA_COREBOOT || CONFIG_DISPLAY_BOCHS)
return cbvga_set_dacformat(vmode_g, val);
return stdvga_set_dacformat(vmode_g, val);
}
@ -134,13 +136,13 @@ static inline int vgahw_save_restore(int cmd, u16 seg, void *data) {
return clext_save_restore(cmd, seg, data);
if (CONFIG_VGA_BOCHS)
return bochsvga_save_restore(cmd, seg, data);
if (CONFIG_VGA_COREBOOT)
if (CONFIG_VGA_COREBOOT || CONFIG_DISPLAY_BOCHS)
return cbvga_save_restore(cmd, seg, data);
return stdvga_save_restore(cmd, seg, data);
}
static inline int vgahw_get_linesize(struct vgamode_s *vmode_g) {
if (CONFIG_VGA_COREBOOT)
if (CONFIG_VGA_COREBOOT || CONFIG_DISPLAY_BOCHS)
return cbvga_get_linesize(vmode_g);
return stdvga_get_linesize(vmode_g);
}

View File

@ -21,6 +21,9 @@ int cbvga_get_linesize(struct vgamode_s *vmode_g);
void cbvga_setup_modes(u64 addr, u8 bpp, u32 xlines, u32 ylines, u32 linelength);
int cbvga_setup(void);
// bochsdisplay.c
int bochs_display_setup(void);
// clext.c
struct vgamode_s *clext_find_mode(int mode);
void clext_list_modes(u16 seg, u16 *dest, u16 *last);