Add support for qemu ramfb. This is a simple boot framebuffer device,
with normal ram being used to back the framebuffer and fw_cfg being used
to configure the device.
Use case (on x86): boot display for vgpu devices (which neither emulate
vga nor have a vgabios).
Sharing fw_cfg code with seabios turned out to be difficuilt due to
various dependencies the code has on infrastructure which only seabios
has. So include a copy of the code here, with those dependencies
removed and also stripped down because we don't need a non-dma fallback
here.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
Makefile | 2 +-
vgasrc/vgahw.h | 28 +++++-----
vgasrc/vgautil.h | 3 +
vgasrc/ramfb.c | 163 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
vgasrc/Kconfig | 7 +++
5 files changed, 189 insertions(+), 14 deletions(-)
create mode 100644 vgasrc/ramfb.c
diff --git a/Makefile b/Makefile
index de2a145c39..d2d11dbef8 100644
--- a/Makefile
+++ b/Makefile
@@ -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 vgasrc/bochsdisplay.c
+ src/fw/coreboot.c vgasrc/cbvga.c vgasrc/bochsdisplay.c vgasrc/ramfb.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),$@)
diff --git a/vgasrc/vgahw.h b/vgasrc/vgahw.h
index 6d6ff1aa7b..51777458da 100644
--- a/vgasrc/vgahw.h
+++ b/vgasrc/vgahw.h
@@ -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 || CONFIG_DISPLAY_BOCHS)
+ if (CONFIG_VGA_EMULATE_TEXT)
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 || CONFIG_DISPLAY_BOCHS)
+ if (CONFIG_VGA_EMULATE_TEXT)
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 || CONFIG_DISPLAY_BOCHS)
+ else if (CONFIG_VGA_EMULATE_TEXT)
cbvga_list_modes(seg, dest, last);
else
stdvga_list_modes(seg, dest, last);
@@ -51,6 +51,8 @@ static inline int vgahw_setup(void) {
return cbvga_setup();
if (CONFIG_DISPLAY_BOCHS)
return bochs_display_setup();
+ if (CONFIG_VGA_RAMFB)
+ return ramfb_setup();
return stdvga_setup();
}
@@ -59,7 +61,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 || CONFIG_DISPLAY_BOCHS)
+ if (CONFIG_VGA_EMULATE_TEXT)
return cbvga_get_window(vmode_g, window);
return stdvga_get_window(vmode_g, window);
}
@@ -70,7 +72,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 || CONFIG_DISPLAY_BOCHS)
+ if (CONFIG_VGA_EMULATE_TEXT)
return cbvga_set_window(vmode_g, window, val);
return stdvga_set_window(vmode_g, window, val);
}
@@ -80,7 +82,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 || CONFIG_DISPLAY_BOCHS)
+ if (CONFIG_VGA_EMULATE_TEXT)
return cbvga_get_linelength(vmode_g);
return stdvga_get_linelength(vmode_g);
}
@@ -90,7 +92,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 || CONFIG_DISPLAY_BOCHS)
+ if (CONFIG_VGA_EMULATE_TEXT)
return cbvga_set_linelength(vmode_g, val);
return stdvga_set_linelength(vmode_g, val);
}
@@ -100,7 +102,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 || CONFIG_DISPLAY_BOCHS)
+ if (CONFIG_VGA_EMULATE_TEXT)
return cbvga_get_displaystart(vmode_g);
return stdvga_get_displaystart(vmode_g);
}
@@ -110,7 +112,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 || CONFIG_DISPLAY_BOCHS)
+ if (CONFIG_VGA_EMULATE_TEXT)
return cbvga_set_displaystart(vmode_g, val);
return stdvga_set_displaystart(vmode_g, val);
}
@@ -118,7 +120,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 || CONFIG_DISPLAY_BOCHS)
+ if (CONFIG_VGA_EMULATE_TEXT)
return cbvga_get_dacformat(vmode_g);
return stdvga_get_dacformat(vmode_g);
}
@@ -126,7 +128,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 || CONFIG_DISPLAY_BOCHS)
+ if (CONFIG_VGA_EMULATE_TEXT)
return cbvga_set_dacformat(vmode_g, val);
return stdvga_set_dacformat(vmode_g, val);
}
@@ -136,13 +138,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 || CONFIG_DISPLAY_BOCHS)
+ if (CONFIG_VGA_EMULATE_TEXT)
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 || CONFIG_DISPLAY_BOCHS)
+ if (CONFIG_VGA_EMULATE_TEXT)
return cbvga_get_linesize(vmode_g);
return stdvga_get_linesize(vmode_g);
}
diff --git a/vgasrc/vgautil.h b/vgasrc/vgautil.h
index 0f2dba4c2a..4f37bf947c 100644
--- a/vgasrc/vgautil.h
+++ b/vgasrc/vgautil.h
@@ -24,6 +24,9 @@ int cbvga_setup(void);
// bochsdisplay.c
int bochs_display_setup(void);
+// ramfb.c
+int ramfb_setup(void);
+
// clext.c
struct vgamode_s *clext_find_mode(int mode);
void clext_list_modes(u16 seg, u16 *dest, u16 *last);
diff --git a/vgasrc/ramfb.c b/vgasrc/ramfb.c
new file mode 100644
index 0000000000..8f8e2ef331
--- /dev/null
+++ b/vgasrc/ramfb.c
@@ -0,0 +1,163 @@
+#include "biosvar.h" // GET_BDA
+#include "output.h" // dprintf
+#include "string.h" // memset16_far
+#include "vgautil.h" // VBE_total_memory
+#include "std/pmm.h" // struct pmmheader
+#include "byteorder.h"
+#include "fw/paravirt.h"
+
+/* ---------------------------------------------------------------------- */
+/* minimal qemu fc_cfg support bits, requires dma support */
+
+#define QEMU_CFG_FILE_DIR 0x19
+
+struct QemuCfgFile {
+ u32 size; /* file size */
+ u16 select; /* write this to 0x510 to read it */
+ u16 reserved;
+ char name[56];
+};
+
+static void
+qemu_cfg_dma_transfer(void *address, u32 length, u32 control)
+{
+ QemuCfgDmaAccess access;
+
+ if (length == 0) {
+ return;
+ }
+
+ access.address = cpu_to_be64((u64)(u32)address);
+ access.length = cpu_to_be32(length);
+ access.control = cpu_to_be32(control);
+
+ barrier();
+
+ outl(cpu_to_be32((u32)&access), PORT_QEMU_CFG_DMA_ADDR_LOW);
+
+ while(be32_to_cpu(access.control) & ~QEMU_CFG_DMA_CTL_ERROR)
+ /* wait */;
+}
+
+static void
+qemu_cfg_read(void *buf, int len)
+{
+ qemu_cfg_dma_transfer(buf, len, QEMU_CFG_DMA_CTL_READ);
+}
+
+static void
+qemu_cfg_read_entry(void *buf, int e, int len)
+{
+ u32 control = (e << 16) | QEMU_CFG_DMA_CTL_SELECT
+ | QEMU_CFG_DMA_CTL_READ;
+ qemu_cfg_dma_transfer(buf, len, control);
+}
+
+static void
+qemu_cfg_write_entry(void *buf, int e, int len)
+{
+ u32 control = (e << 16) | QEMU_CFG_DMA_CTL_SELECT
+ | QEMU_CFG_DMA_CTL_WRITE;
+ qemu_cfg_dma_transfer(buf, len, control);
+}
+
+static int
+qemu_cfg_find_file(const char *filename)
+{
+ u32 count, e, select;
+
+ qemu_cfg_read_entry(&count, QEMU_CFG_FILE_DIR, sizeof(count));
+ count = be32_to_cpu(count);
+ for (select = 0, e = 0; e < count; e++) {
+ struct QemuCfgFile qfile;
+ qemu_cfg_read(&qfile, sizeof(qfile));
+ if (memcmp_far(GET_SEG(SS), qfile.name,
+ GET_SEG(CS), filename, 10) == 0)
+ select = be16_to_cpu(qfile.select);
+ }
+ return select;
+}
+
+/* ---------------------------------------------------------------------- */
+
+#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)
+
+struct QemuRAMFBCfg {
+ u64 addr;
+ u32 fourcc;
+ u32 flags;
+ u32 width;
+ u32 height;
+ u32 stride;
+};
+
+#define fourcc_code(a, b, c, d) ((u32)(a) | ((u32)(b) << 8) | \
+ ((u32)(c) << 16) | ((u32)(d) << 24))
+
+#define DRM_FORMAT_RGB565 fourcc_code('R', 'G', '1', '6') /* [15:0] R:G:B 5:6:5 little endian */
+#define DRM_FORMAT_RGB888 fourcc_code('R', 'G', '2', '4') /* [23:0] R:G:B little endian */
+#define DRM_FORMAT_XRGB8888 fourcc_code('X', 'R', '2', '4') /* [31:0] x:R:G:B 8:8:8:8 little endian */
+
+static u32
+allocate_framebuffer(void)
+{
+ u32 res = allocate_pmm(FRAMEBUFFER_SIZE, 1, 1);
+ if (!res)
+ return 0;
+ dprintf(1, "ramfb: framebuffer allocated at %x\n", res);
+ return res;
+}
+
+int
+ramfb_setup(void)
+{
+ dprintf(1, "ramfb: init\n");
+
+ if (GET_GLOBAL(HaveRunInit))
+ return 0;
+
+ u32 select = qemu_cfg_find_file("etc/ramfb");
+ if (select == 0) {
+ dprintf(1, "ramfb: fw_cfg (etc/ramfb) file not found\n");
+ return -1;
+ }
+
+ dprintf(1, "ramfb: fw_cfg (etc/ramfb) file at slot 0x%x\n", select);
+ u32 fb = allocate_framebuffer();
+ if (!fb) {
+ dprintf(1, "ramfb: allocating framebuffer failed\n");
+ return -1;
+ }
+
+ u64 addr = fb;
+ u8 bpp = FRAMEBUFFER_BPP * 8;
+ u32 xlines = FRAMEBUFFER_WIDTH;
+ u32 ylines = FRAMEBUFFER_HEIGHT;
+ u32 linelength = FRAMEBUFFER_STRIDE;
+ dprintf(1, "Found FB @ %llx %dx%d with %d bpp (%d stride)\n"
+ , addr, xlines, ylines, bpp, linelength);
+
+ if (!addr || addr > 0xffffffff
+ || (bpp != 15 && bpp != 16 && bpp != 24 && bpp != 32)) {
+ dprintf(1, "Unable to use FB\n");
+ return -1;
+ }
+
+ cbvga_setup_modes(addr, bpp, xlines, ylines, linelength);
+
+ struct QemuRAMFBCfg cfg = {
+ .addr = cpu_to_be64(fb),
+ .fourcc = cpu_to_be32(DRM_FORMAT_XRGB8888),
+ .flags = cpu_to_be32(0),
+ .width = cpu_to_be32(FRAMEBUFFER_WIDTH),
+ .height = cpu_to_be32(FRAMEBUFFER_HEIGHT),
+ .stride = cpu_to_be32(FRAMEBUFFER_STRIDE),
+ };
+ qemu_cfg_write_entry(&cfg, select, sizeof(cfg));
+
+ return 0;
+}
diff --git a/vgasrc/Kconfig b/vgasrc/Kconfig
index 4443c0b37a..1933b0e23f 100644
--- a/vgasrc/Kconfig
+++ b/vgasrc/Kconfig
@@ -70,6 +70,13 @@ menu "VGA ROM"
v3.0+. The vgabios works with the qemu stdvga too (use
"qemu -device VGA,romfile=/path/to/vgabios.bin")".
+ config VGA_RAMFB
+ depends on QEMU
+ bool "qemu ram framebuffer (experimental)"
+ select VGA_EMULATE_TEXT
+ help
+ qemu ram framebuffer (experimental)
+
endchoice
choice
--
2.9.3
_______________________________________________
SeaBIOS mailing list
SeaBIOS@seabios.org
https://mail.coreboot.org/mailman/listinfo/seabios
On Fri, Jun 15, 2018 at 02:57:37PM +0200, Gerd Hoffmann wrote: > Add support for qemu ramfb. This is a simple boot framebuffer device, > with normal ram being used to back the framebuffer and fw_cfg being used > to configure the device. > > Use case (on x86): boot display for vgpu devices (which neither emulate > vga nor have a vgabios). > > Sharing fw_cfg code with seabios turned out to be difficuilt due to > various dependencies the code has on infrastructure which only seabios > has. So include a copy of the code here, with those dependencies > removed and also stripped down because we don't need a non-dma fallback > here. > > Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> > --- > Makefile | 2 +- > vgasrc/vgahw.h | 28 +++++----- > vgasrc/vgautil.h | 3 + > vgasrc/ramfb.c | 163 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ > vgasrc/Kconfig | 7 +++ > 5 files changed, 189 insertions(+), 14 deletions(-) > create mode 100644 vgasrc/ramfb.c > > diff --git a/Makefile b/Makefile > index de2a145c39..d2d11dbef8 100644 > --- a/Makefile > +++ b/Makefile > @@ -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 vgasrc/bochsdisplay.c > + src/fw/coreboot.c vgasrc/cbvga.c vgasrc/bochsdisplay.c vgasrc/ramfb.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),$@) > diff --git a/vgasrc/vgahw.h b/vgasrc/vgahw.h > index 6d6ff1aa7b..51777458da 100644 > --- a/vgasrc/vgahw.h > +++ b/vgasrc/vgahw.h > @@ -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 || CONFIG_DISPLAY_BOCHS) > + if (CONFIG_VGA_EMULATE_TEXT) > 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 || CONFIG_DISPLAY_BOCHS) > + if (CONFIG_VGA_EMULATE_TEXT) > 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 || CONFIG_DISPLAY_BOCHS) > + else if (CONFIG_VGA_EMULATE_TEXT) > cbvga_list_modes(seg, dest, last); > else > stdvga_list_modes(seg, dest, last); > @@ -51,6 +51,8 @@ static inline int vgahw_setup(void) { > return cbvga_setup(); > if (CONFIG_DISPLAY_BOCHS) > return bochs_display_setup(); > + if (CONFIG_VGA_RAMFB) > + return ramfb_setup(); > return stdvga_setup(); > } > > @@ -59,7 +61,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 || CONFIG_DISPLAY_BOCHS) > + if (CONFIG_VGA_EMULATE_TEXT) > return cbvga_get_window(vmode_g, window); > return stdvga_get_window(vmode_g, window); > } > @@ -70,7 +72,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 || CONFIG_DISPLAY_BOCHS) > + if (CONFIG_VGA_EMULATE_TEXT) > return cbvga_set_window(vmode_g, window, val); > return stdvga_set_window(vmode_g, window, val); > } > @@ -80,7 +82,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 || CONFIG_DISPLAY_BOCHS) > + if (CONFIG_VGA_EMULATE_TEXT) > return cbvga_get_linelength(vmode_g); > return stdvga_get_linelength(vmode_g); > } > @@ -90,7 +92,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 || CONFIG_DISPLAY_BOCHS) > + if (CONFIG_VGA_EMULATE_TEXT) > return cbvga_set_linelength(vmode_g, val); > return stdvga_set_linelength(vmode_g, val); > } > @@ -100,7 +102,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 || CONFIG_DISPLAY_BOCHS) > + if (CONFIG_VGA_EMULATE_TEXT) > return cbvga_get_displaystart(vmode_g); > return stdvga_get_displaystart(vmode_g); > } > @@ -110,7 +112,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 || CONFIG_DISPLAY_BOCHS) > + if (CONFIG_VGA_EMULATE_TEXT) > return cbvga_set_displaystart(vmode_g, val); > return stdvga_set_displaystart(vmode_g, val); > } > @@ -118,7 +120,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 || CONFIG_DISPLAY_BOCHS) > + if (CONFIG_VGA_EMULATE_TEXT) > return cbvga_get_dacformat(vmode_g); > return stdvga_get_dacformat(vmode_g); > } > @@ -126,7 +128,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 || CONFIG_DISPLAY_BOCHS) > + if (CONFIG_VGA_EMULATE_TEXT) > return cbvga_set_dacformat(vmode_g, val); > return stdvga_set_dacformat(vmode_g, val); > } > @@ -136,13 +138,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 || CONFIG_DISPLAY_BOCHS) > + if (CONFIG_VGA_EMULATE_TEXT) > 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 || CONFIG_DISPLAY_BOCHS) > + if (CONFIG_VGA_EMULATE_TEXT) > return cbvga_get_linesize(vmode_g); > return stdvga_get_linesize(vmode_g); > } > diff --git a/vgasrc/vgautil.h b/vgasrc/vgautil.h > index 0f2dba4c2a..4f37bf947c 100644 > --- a/vgasrc/vgautil.h > +++ b/vgasrc/vgautil.h > @@ -24,6 +24,9 @@ int cbvga_setup(void); > // bochsdisplay.c > int bochs_display_setup(void); > > +// ramfb.c > +int ramfb_setup(void); > + > // clext.c > struct vgamode_s *clext_find_mode(int mode); > void clext_list_modes(u16 seg, u16 *dest, u16 *last); > diff --git a/vgasrc/ramfb.c b/vgasrc/ramfb.c > new file mode 100644 > index 0000000000..8f8e2ef331 > --- /dev/null > +++ b/vgasrc/ramfb.c > @@ -0,0 +1,163 @@ > +#include "biosvar.h" // GET_BDA > +#include "output.h" // dprintf > +#include "string.h" // memset16_far > +#include "vgautil.h" // VBE_total_memory > +#include "std/pmm.h" // struct pmmheader > +#include "byteorder.h" > +#include "fw/paravirt.h" > + > +/* ---------------------------------------------------------------------- */ > +/* minimal qemu fc_cfg support bits, requires dma support */ > + > +#define QEMU_CFG_FILE_DIR 0x19 > + > +struct QemuCfgFile { > + u32 size; /* file size */ > + u16 select; /* write this to 0x510 to read it */ > + u16 reserved; > + char name[56]; > +}; > + > +static void > +qemu_cfg_dma_transfer(void *address, u32 length, u32 control) > +{ > + QemuCfgDmaAccess access; > + > + if (length == 0) { > + return; > + } > + > + access.address = cpu_to_be64((u64)(u32)address); > + access.length = cpu_to_be32(length); > + access.control = cpu_to_be32(control); > + > + barrier(); > + > + outl(cpu_to_be32((u32)&access), PORT_QEMU_CFG_DMA_ADDR_LOW); > + > + while(be32_to_cpu(access.control) & ~QEMU_CFG_DMA_CTL_ERROR) > + /* wait */; > +} > + > +static void > +qemu_cfg_read(void *buf, int len) > +{ > + qemu_cfg_dma_transfer(buf, len, QEMU_CFG_DMA_CTL_READ); > +} > + > +static void > +qemu_cfg_read_entry(void *buf, int e, int len) > +{ > + u32 control = (e << 16) | QEMU_CFG_DMA_CTL_SELECT > + | QEMU_CFG_DMA_CTL_READ; > + qemu_cfg_dma_transfer(buf, len, control); > +} > + > +static void > +qemu_cfg_write_entry(void *buf, int e, int len) > +{ > + u32 control = (e << 16) | QEMU_CFG_DMA_CTL_SELECT > + | QEMU_CFG_DMA_CTL_WRITE; > + qemu_cfg_dma_transfer(buf, len, control); > +} > + > +static int > +qemu_cfg_find_file(const char *filename) > +{ > + u32 count, e, select; > + > + qemu_cfg_read_entry(&count, QEMU_CFG_FILE_DIR, sizeof(count)); > + count = be32_to_cpu(count); > + for (select = 0, e = 0; e < count; e++) { > + struct QemuCfgFile qfile; > + qemu_cfg_read(&qfile, sizeof(qfile)); > + if (memcmp_far(GET_SEG(SS), qfile.name, > + GET_SEG(CS), filename, 10) == 0) > + select = be16_to_cpu(qfile.select); > + } > + return select; > +} > + > +/* ---------------------------------------------------------------------- */ > + > +#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) > + > +struct QemuRAMFBCfg { > + u64 addr; > + u32 fourcc; > + u32 flags; > + u32 width; > + u32 height; > + u32 stride; > +}; > + > +#define fourcc_code(a, b, c, d) ((u32)(a) | ((u32)(b) << 8) | \ > + ((u32)(c) << 16) | ((u32)(d) << 24)) > + > +#define DRM_FORMAT_RGB565 fourcc_code('R', 'G', '1', '6') /* [15:0] R:G:B 5:6:5 little endian */ > +#define DRM_FORMAT_RGB888 fourcc_code('R', 'G', '2', '4') /* [23:0] R:G:B little endian */ > +#define DRM_FORMAT_XRGB8888 fourcc_code('X', 'R', '2', '4') /* [31:0] x:R:G:B 8:8:8:8 little endian */ > + > +static u32 > +allocate_framebuffer(void) > +{ > + u32 res = allocate_pmm(FRAMEBUFFER_SIZE, 1, 1); > + if (!res) > + return 0; > + dprintf(1, "ramfb: framebuffer allocated at %x\n", res); > + return res; > +} > + > +int > +ramfb_setup(void) > +{ > + dprintf(1, "ramfb: init\n"); > + > + if (GET_GLOBAL(HaveRunInit)) > + return 0; > + > + u32 select = qemu_cfg_find_file("etc/ramfb"); > + if (select == 0) { > + dprintf(1, "ramfb: fw_cfg (etc/ramfb) file not found\n"); > + return -1; > + } > + > + dprintf(1, "ramfb: fw_cfg (etc/ramfb) file at slot 0x%x\n", select); > + u32 fb = allocate_framebuffer(); > + if (!fb) { > + dprintf(1, "ramfb: allocating framebuffer failed\n"); > + return -1; > + } > + > + u64 addr = fb; > + u8 bpp = FRAMEBUFFER_BPP * 8; > + u32 xlines = FRAMEBUFFER_WIDTH; > + u32 ylines = FRAMEBUFFER_HEIGHT; > + u32 linelength = FRAMEBUFFER_STRIDE; > + dprintf(1, "Found FB @ %llx %dx%d with %d bpp (%d stride)\n" > + , addr, xlines, ylines, bpp, linelength); > + > + if (!addr || addr > 0xffffffff > + || (bpp != 15 && bpp != 16 && bpp != 24 && bpp != 32)) { > + dprintf(1, "Unable to use FB\n"); > + return -1; > + } > + > + cbvga_setup_modes(addr, bpp, xlines, ylines, linelength); > + > + struct QemuRAMFBCfg cfg = { > + .addr = cpu_to_be64(fb), > + .fourcc = cpu_to_be32(DRM_FORMAT_XRGB8888), > + .flags = cpu_to_be32(0), > + .width = cpu_to_be32(FRAMEBUFFER_WIDTH), > + .height = cpu_to_be32(FRAMEBUFFER_HEIGHT), > + .stride = cpu_to_be32(FRAMEBUFFER_STRIDE), > + }; > + qemu_cfg_write_entry(&cfg, select, sizeof(cfg)); > + > + return 0; > +} > diff --git a/vgasrc/Kconfig b/vgasrc/Kconfig > index 4443c0b37a..1933b0e23f 100644 > --- a/vgasrc/Kconfig > +++ b/vgasrc/Kconfig > @@ -70,6 +70,13 @@ menu "VGA ROM" > v3.0+. The vgabios works with the qemu stdvga too (use > "qemu -device VGA,romfile=/path/to/vgabios.bin")". > > + config VGA_RAMFB > + depends on QEMU > + bool "qemu ram framebuffer (experimental)" > + select VGA_EMULATE_TEXT > + help > + qemu ram framebuffer (experimental) > + > endchoice > > choice Thanks. Series looks good to me. -Kevin _______________________________________________ SeaBIOS mailing list SeaBIOS@seabios.org https://mail.coreboot.org/mailman/listinfo/seabios
Hi, > Thanks. Series looks good to me. qemu patches have been merged, so I pushed these now. cheers, Gerd _______________________________________________ SeaBIOS mailing list SeaBIOS@seabios.org https://mail.coreboot.org/mailman/listinfo/seabios
© 2016 - 2025 Red Hat, Inc.