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

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

This is more convenient since it does not require a video BIOS. Enable it for QEMU.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/cpu/qemu/Kconfig | 2 +- configs/qemu-x86_64_defconfig | 5 +---- configs/qemu-x86_defconfig | 3 --- 3 files changed, 2 insertions(+), 8 deletions(-)
diff --git a/arch/x86/cpu/qemu/Kconfig b/arch/x86/cpu/qemu/Kconfig index f8f2f6473088..aa329b0dab29 100644 --- a/arch/x86/cpu/qemu/Kconfig +++ b/arch/x86/cpu/qemu/Kconfig @@ -12,7 +12,7 @@ config QEMU imply SYS_NS16550 imply USB imply USB_EHCI_HCD - imply VIDEO_VESA + imply VIDEO_BOCHS
if QEMU
diff --git a/configs/qemu-x86_64_defconfig b/configs/qemu-x86_64_defconfig index 79ea35918575..3ebc16d370fe 100644 --- a/configs/qemu-x86_64_defconfig +++ b/configs/qemu-x86_64_defconfig @@ -84,11 +84,8 @@ CONFIG_SPL_DM_RTC=y CONFIG_SYS_NS16550_PORT_MAPPED=y CONFIG_SPI=y CONFIG_USB_KEYBOARD=y -CONFIG_SPL_VIDEO=y -CONFIG_FRAMEBUFFER_SET_VESA_MODE=y -CONFIG_FRAMEBUFFER_VESA_MODE_USER=y -CONFIG_FRAMEBUFFER_VESA_MODE=0x144 CONFIG_CONSOLE_SCROLL_LINES=5 +CONFIG_SPL_VIDEO=y CONFIG_FAT_BLK_XLATE=y # CONFIG_SPL_USE_TINY_PRINTF is not set CONFIG_GENERATE_ACPI_TABLE=y diff --git a/configs/qemu-x86_defconfig b/configs/qemu-x86_defconfig index 9bf29647fe59..fcf429f77115 100644 --- a/configs/qemu-x86_defconfig +++ b/configs/qemu-x86_defconfig @@ -54,9 +54,6 @@ CONFIG_NVME_PCI=y CONFIG_SYS_NS16550_PORT_MAPPED=y CONFIG_SPI=y CONFIG_USB_KEYBOARD=y -CONFIG_FRAMEBUFFER_SET_VESA_MODE=y -CONFIG_FRAMEBUFFER_VESA_MODE_USER=y -CONFIG_FRAMEBUFFER_VESA_MODE=0x144 CONFIG_CONSOLE_SCROLL_LINES=5 CONFIG_GENERATE_ACPI_TABLE=y # CONFIG_GZIP is not set

Am 30. April 2023 04:31:57 MESZ schrieb Simon Glass sjg@chromium.org:
This is more convenient since it does not require a video BIOS. Enable it for QEMU.
Does this require a change in how QEMU is invoked? If so, please add a documentation change.
Best regards
Heinrich
Signed-off-by: Simon Glass sjg@chromium.org
arch/x86/cpu/qemu/Kconfig | 2 +- configs/qemu-x86_64_defconfig | 5 +---- configs/qemu-x86_defconfig | 3 --- 3 files changed, 2 insertions(+), 8 deletions(-)
diff --git a/arch/x86/cpu/qemu/Kconfig b/arch/x86/cpu/qemu/Kconfig index f8f2f6473088..aa329b0dab29 100644 --- a/arch/x86/cpu/qemu/Kconfig +++ b/arch/x86/cpu/qemu/Kconfig @@ -12,7 +12,7 @@ config QEMU imply SYS_NS16550 imply USB imply USB_EHCI_HCD
- imply VIDEO_VESA
- imply VIDEO_BOCHS
if QEMU
diff --git a/configs/qemu-x86_64_defconfig b/configs/qemu-x86_64_defconfig index 79ea35918575..3ebc16d370fe 100644 --- a/configs/qemu-x86_64_defconfig +++ b/configs/qemu-x86_64_defconfig @@ -84,11 +84,8 @@ CONFIG_SPL_DM_RTC=y CONFIG_SYS_NS16550_PORT_MAPPED=y CONFIG_SPI=y CONFIG_USB_KEYBOARD=y -CONFIG_SPL_VIDEO=y -CONFIG_FRAMEBUFFER_SET_VESA_MODE=y -CONFIG_FRAMEBUFFER_VESA_MODE_USER=y -CONFIG_FRAMEBUFFER_VESA_MODE=0x144 CONFIG_CONSOLE_SCROLL_LINES=5 +CONFIG_SPL_VIDEO=y CONFIG_FAT_BLK_XLATE=y # CONFIG_SPL_USE_TINY_PRINTF is not set CONFIG_GENERATE_ACPI_TABLE=y diff --git a/configs/qemu-x86_defconfig b/configs/qemu-x86_defconfig index 9bf29647fe59..fcf429f77115 100644 --- a/configs/qemu-x86_defconfig +++ b/configs/qemu-x86_defconfig @@ -54,9 +54,6 @@ CONFIG_NVME_PCI=y CONFIG_SYS_NS16550_PORT_MAPPED=y CONFIG_SPI=y CONFIG_USB_KEYBOARD=y -CONFIG_FRAMEBUFFER_SET_VESA_MODE=y -CONFIG_FRAMEBUFFER_VESA_MODE_USER=y -CONFIG_FRAMEBUFFER_VESA_MODE=0x144 CONFIG_CONSOLE_SCROLL_LINES=5 CONFIG_GENERATE_ACPI_TABLE=y # CONFIG_GZIP is not set

Hi Heinrich,
On Sat, 29 Apr 2023 at 20:38, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
Am 30. April 2023 04:31:57 MESZ schrieb Simon Glass sjg@chromium.org:
This is more convenient since it does not require a video BIOS. Enable it for QEMU.
Does this require a change in how QEMU is invoked? If so, please add a documentation change.
No, it seems to work fine as is.
Regards, Simon

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

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
participants (3)
-
Bin Meng
-
Heinrich Schuchardt
-
Simon Glass