
Hi Simon,
On Sun, Apr 30, 2023 at 10:32 AM Simon Glass sjg@chromium.org wrote:
Bochs is convenient with QEMU on x86 since it does not require a video BIOS. Add a driver for it.
Signed-off-by: Simon Glass sjg@chromium.org
drivers/video/Kconfig | 30 ++++++++++ drivers/video/Makefile | 2 + drivers/video/bochs.c | 130 +++++++++++++++++++++++++++++++++++++++++ drivers/video/bochs.h | 36 ++++++++++++ 4 files changed, 198 insertions(+) create mode 100644 drivers/video/bochs.c create mode 100644 drivers/video/bochs.h
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 9a95b7a4c792..5fd42807179f 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -278,6 +278,36 @@ config VIDCONSOLE_AS_NAME possible to update the environment, the breakage may be confusing for users. This option will be removed around the end of 2020.
+config VIDEO_BOCHS
bool "Enable Bochs video emulation for QEMU"
depends on X86
help
Enable this to use the Boschs video support provided in the QEMU
emulator. This appears as a PCI device which U-Boot can set up to
provide a frame buffer.
+if VIDEO_BOCHS
+config VIDEO_BOCHS_SIZE_X
int "Width of display (X resolution)"
default 1280
help
Sets the width of the display.
These two options control the size of the display set up by QEMU.
Typical sizes are 1024 x 768 or 1280 x 1024.
+config VIDEO_BOCHS_SIZE_Y
int "High of display (Y resolution)"
default 1024
help
Sets the height of the display.
These two options control the size of the display set up by QEMU.
Typical sizes are 1024 x 768 or 1280 x 1024.
+endif
config VIDEO_COREBOOT bool "Enable coreboot framebuffer driver support" depends on X86 diff --git a/drivers/video/Makefile b/drivers/video/Makefile index a609e35d22e8..11d872ddf41d 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -28,6 +28,8 @@ obj-$(CONFIG_VIDEO_LOGO) += u_boot_logo.o
endif
+obj-$(CONFIG_VIDEO_BOCHS) += bochs.o
obj-${CONFIG_EXYNOS_FB} += exynos/ obj-${CONFIG_VIDEO_ROCKCHIP} += rockchip/ obj-${CONFIG_VIDEO_STM32} += stm32/ diff --git a/drivers/video/bochs.c b/drivers/video/bochs.c new file mode 100644 index 000000000000..7ea29a0ed177 --- /dev/null +++ b/drivers/video/bochs.c @@ -0,0 +1,130 @@ +// SPDX-License-Identifier: GPL-2.0 +/*
- Modified from coreboot bochs.c
- */
+#define LOG_CATEGORY UCLASS_VIDEO
+#include <common.h> +#include <dm.h> +#include <log.h> +#include <pci.h> +#include <video.h> +#include <asm/io.h> +#include <asm/mtrr.h> +#include <linux/sizes.h> +#include "bochs.h"
+static int xsize = CONFIG_VIDEO_BOCHS_SIZE_X; +static int ysize = CONFIG_VIDEO_BOCHS_SIZE_Y;
+static void bochs_write(void *mmio, int index, int val) +{
writew(val, mmio + MMIO_BASE + index * 2);
+}
+static int bochs_read(void *mmio, int index) +{
return readw(mmio + MMIO_BASE + index * 2);
+}
+static void bochs_vga_write(int index, uint8_t val) +{
outb(val, VGA_INDEX);
+}
+static int bochs_init_linear_fb(struct udevice *dev) +{
struct video_uc_plat *plat = dev_get_uclass_plat(dev);
struct video_priv *uc_priv = dev_get_uclass_priv(dev);
ulong fb;
void *mmio;
int id, mem;
log_debug("probing %s at PCI %x\n", dev->name, dm_pci_get_bdf(dev));
fb = dm_pci_read_bar32(dev, 0);
if (!fb)
return log_msg_ret("fb", -EIO);
/* MMIO bar supported since qemu 3.0+ */
mmio = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_2, 0, 0, PCI_REGION_TYPE,
PCI_REGION_MEM);
if (!mmio)
return log_msg_ret("map", -EIO);
log_debug("QEMU VGA: bochs @ %p: %d MiB FB at %lx\n", mmio, mem / SZ_1M,
fb);
mem is uninitialized yet at this point, until (see below)
/* bochs dispi detection */
id = bochs_read(mmio, INDEX_ID);
if ((id & 0xfff0) != ID0) {
log_debug("ID mismatch\n");
return -EPROTONOSUPPORT;
}
mem = bochs_read(mmio, INDEX_VIDEO_MEMORY_64K) * SZ_64K;
it reaches this line
uc_priv->xsize = xsize;
uc_priv->ysize = ysize;
uc_priv->bpix = VIDEO_BPP32;
/* setup video mode */
bochs_write(mmio, INDEX_ENABLE, 0);
bochs_write(mmio, INDEX_BANK, 0);
bochs_write(mmio, INDEX_BPP, VNBITS(uc_priv->bpix));
bochs_write(mmio, INDEX_XRES, xsize);
bochs_write(mmio, INDEX_YRES, ysize);
bochs_write(mmio, INDEX_VIRT_WIDTH, xsize);
bochs_write(mmio, INDEX_VIRT_HEIGHT, ysize);
bochs_write(mmio, INDEX_X_OFFSET, 0);
bochs_write(mmio, INDEX_Y_OFFSET, 0);
bochs_write(mmio, INDEX_ENABLE, ENABLED | LFB_ENABLED);
bochs_vga_write(0, 0x20); /* disable blanking */
plat->base = fb;
return 0;
+}
+static int bochs_video_probe(struct udevice *dev) +{
int ret;
ret = bochs_init_linear_fb(dev);
if (ret)
return log_ret(ret);
return 0;
+}
+static int bochs_video_bind(struct udevice *dev) +{
struct video_uc_plat *uc_plat = dev_get_uclass_plat(dev);
/* Set the maximum supported resolution */
uc_plat->size = 2560 * 1600 * 4;
log_debug("%s: Frame buffer size %x\n", __func__, uc_plat->size);
return 0;
+}
+static const struct udevice_id bochs_video_ids[] = {
{ .compatible = "bochs-fb" },
{ }
+};
+U_BOOT_DRIVER(bochs_video) = {
.name = "bochs_video",
.id = UCLASS_VIDEO,
.of_match = bochs_video_ids,
.bind = bochs_video_bind,
.probe = bochs_video_probe,
+};
+static struct pci_device_id bochs_video_supported[] = {
{ PCI_DEVICE(0x1234, 0x1111) },
{ },
+};
+U_BOOT_PCI_DEVICE(bochs_video, bochs_video_supported); diff --git a/drivers/video/bochs.h b/drivers/video/bochs.h new file mode 100644 index 000000000000..4c8ec83a550e --- /dev/null +++ b/drivers/video/bochs.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/*
- Modified from coreboot bochs.c
- */
+#ifndef __BOCHS_H +#define __BOCHS_H
+#define VGA_INDEX 0x3c0
+#define IOPORT_INDEX 0x01ce +#define IOPORT_DATA 0x01cf
+enum {
INDEX_ID,
INDEX_XRES,
INDEX_YRES,
INDEX_BPP,
INDEX_ENABLE,
INDEX_BANK,
INDEX_VIRT_WIDTH,
INDEX_VIRT_HEIGHT,
INDEX_X_OFFSET,
INDEX_Y_OFFSET,
INDEX_VIDEO_MEMORY_64K
+};
+#define ID0 0xb0c0
+#define ENABLED BIT(0) +#define LFB_ENABLED BIT(6) +#define NOCLEARMEM BIT(7)
+#define MMIO_BASE 0x500
+#endif
Regards, Bin