[PATCH 1/2] x86: video: Add a driver for QEMU bochs emulation
Bin Meng
bmeng.cn at gmail.com
Thu May 11 08:14:52 CEST 2023
Hi Simon,
On Sun, Apr 30, 2023 at 10:32 AM Simon Glass <sjg at 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 at 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
More information about the U-Boot
mailing list