diff mbox series

[1/2] x86: video: Add a driver for QEMU bochs emulation

Message ID 20230430023157.1051841-1-sjg@chromium.org
State Superseded
Delegated to: Bin Meng
Headers show
Series [1/2] x86: video: Add a driver for QEMU bochs emulation | expand

Commit Message

Simon Glass April 30, 2023, 2:31 a.m. UTC
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

Comments

Bin Meng May 11, 2023, 6:14 a.m. UTC | #1
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

typo: Bochs

> +         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);

Could we use mmio access like bochs_read/write ?

> +}
> +
> +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);
> +
> +       /* 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;
> +
> +       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" },
> +       { }
> +};

This compatible string is not used anywhere ?

> +
> +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
Bin Meng May 11, 2023, 11:23 a.m. UTC | #2
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
diff mbox series

Patch

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);
+
+	/* 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;
+
+	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