coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
bochs.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <stdint.h>
4 #include <arch/io.h>
5 #include <arch/mmio.h>
6 #include <console/console.h>
7 #include <device/device.h>
8 #include <device/pci.h>
9 #include <device/pci_ops.h>
10 #include <device/pci_ids.h>
11 #include <pc80/vga.h>
12 #include <pc80/vga_io.h>
13 #include <framebuffer_info.h>
14 
15 /* VGA init. We use the Bochs VESA VBE extensions */
16 #define VBE_DISPI_IOPORT_INDEX 0x01CE
17 #define VBE_DISPI_IOPORT_DATA 0x01CF
18 
19 #define VBE_DISPI_INDEX_ID 0x0
20 #define VBE_DISPI_INDEX_XRES 0x1
21 #define VBE_DISPI_INDEX_YRES 0x2
22 #define VBE_DISPI_INDEX_BPP 0x3
23 #define VBE_DISPI_INDEX_ENABLE 0x4
24 #define VBE_DISPI_INDEX_BANK 0x5
25 #define VBE_DISPI_INDEX_VIRT_WIDTH 0x6
26 #define VBE_DISPI_INDEX_VIRT_HEIGHT 0x7
27 #define VBE_DISPI_INDEX_X_OFFSET 0x8
28 #define VBE_DISPI_INDEX_Y_OFFSET 0x9
29 #define VBE_DISPI_INDEX_VIDEO_MEMORY_64K 0xa
30 
31 #define VBE_DISPI_ID0 0xB0C0
32 #define VBE_DISPI_ID1 0xB0C1
33 #define VBE_DISPI_ID2 0xB0C2
34 #define VBE_DISPI_ID4 0xB0C4
35 #define VBE_DISPI_ID5 0xB0C5
36 
37 #define VBE_DISPI_DISABLED 0x00
38 #define VBE_DISPI_ENABLED 0x01
39 #define VBE_DISPI_LFB_ENABLED 0x40
40 #define VBE_DISPI_NOCLEARMEM 0x80
41 
42 static int width = CONFIG_DRIVERS_EMULATION_QEMU_BOCHS_XRES;
43 static int height = CONFIG_DRIVERS_EMULATION_QEMU_BOCHS_YRES;
44 
45 static void bochs_write(struct resource *res, int index, int val)
46 {
47  if (res->flags & IORESOURCE_IO) {
48  outw(index, res->base);
49  outw(val, res->base + 1);
50  } else {
51  write16(res2mmio(res, 0x500 + index * 2, 0), val);
52  }
53 }
54 
55 static int bochs_read(struct resource *res, int index)
56 {
57  if (res->flags & IORESOURCE_IO) {
58  outw(index, res->base);
59  return inw(res->base + 1);
60  } else {
61  return read16(res2mmio(res, 0x500 + index * 2, 0));
62  }
63 }
64 
65 static void bochs_vga_write(struct resource *res, int index, uint8_t val)
66 {
67  if (res->flags & IORESOURCE_IO)
68  outb(val, index + 0x3c0);
69  else
70  write8(res2mmio(res, (0x400 - 0x3c0) + index, 0), val);
71 }
72 
73 static struct resource res_legacy = {
77  NULL,
79  0,
80  1,
81  1
82 };
83 
84 static void bochs_init_linear_fb(struct device *dev)
85 {
86  struct resource *res_fb, *res_io;
87  int id, mem, bar;
88 
89  res_fb = probe_resource(dev, PCI_BASE_ADDRESS_0);
90  if (res_fb && res_fb->flags & IORESOURCE_MEM) {
91  /* qemu -vga {std,qxl} */
92  bar = 0;
93  } else {
94  res_fb = probe_resource(dev, PCI_BASE_ADDRESS_1);
95  if (res_fb && res_fb->flags & IORESOURCE_MEM) {
96  /* qemu -vga vmware */
97  bar = 1;
98  } else {
99  printk(BIOS_ERR, "%s: Not bochs compatible\n", dev_name(dev));
100  return;
101  }
102  }
103 
104  /* MMIO bar supported since qemu 3.0+ */
105  res_io = probe_resource(dev, PCI_BASE_ADDRESS_2);
106  if (((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA) ||
107  !res_io || !(res_io->flags & IORESOURCE_MEM)) {
108  printk(BIOS_DEBUG, "QEMU VGA: Using legacy VGA\n");
109  res_io = &res_legacy;
110  } else {
111  printk(BIOS_DEBUG, "QEMU VGA: Using I/O bar at %llx\n", res_io->base);
112  }
113 
114  /* bochs dispi detection */
115  id = bochs_read(res_io, VBE_DISPI_INDEX_ID);
116  if ((id & 0xfff0) != VBE_DISPI_ID0) {
117  printk(BIOS_DEBUG, "QEMU VGA: bochs dispi: ID mismatch.\n");
118  return;
119  }
120  mem = bochs_read(res_io, VBE_DISPI_INDEX_VIDEO_MEMORY_64K) * 64 * 1024;
121 
122  printk(BIOS_DEBUG, "QEMU VGA: bochs dispi interface found, "
123  "%d MiB video memory\n", mem / (1024 * 1024));
124  printk(BIOS_DEBUG, "QEMU VGA: framebuffer @ %llx (pci bar %d)\n",
125  res_fb->base, bar);
126 
127  /* setup video mode */
129  bochs_write(res_io, VBE_DISPI_INDEX_BANK, 0);
130  bochs_write(res_io, VBE_DISPI_INDEX_BPP, 32);
139 
140  bochs_vga_write(res_io, 0, 0x20); /* disable blanking */
141 
142  /* Advertise new mode */
143  fb_add_framebuffer_info(res_fb->base, width, height, 4 * width, 32);
144 }
145 
146 static void bochs_init_text_mode(struct device *dev)
147 {
148  vga_misc_write(0x1);
150 }
151 
152 static void bochs_init(struct device *dev)
153 {
154  if (CONFIG(LINEAR_FRAMEBUFFER))
156  else if (CONFIG(VGA_TEXT_FRAMEBUFFER))
158 }
159 
160 static struct device_operations qemu_graph_ops = {
162  .set_resources = pci_dev_set_resources,
163  .enable_resources = pci_dev_enable_resources,
164  .init = bochs_init,
165 };
166 
167 static const struct pci_driver qemu_stdvga_driver __pci_driver = {
168  .ops = &qemu_graph_ops,
169  .vendor = 0x1234,
170  .device = 0x1111,
171 };
172 
173 static const struct pci_driver qemu_vmware_driver __pci_driver = {
174  .ops = &qemu_graph_ops,
175  .vendor = 0x15ad,
176  .device = 0x0405,
177 };
178 static const struct pci_driver qemu_qxl_driver __pci_driver = {
179  .ops = &qemu_graph_ops,
180  .vendor = 0x1b36,
181  .device = 0x0100,
182 };
static void write8(void *addr, uint8_t val)
Definition: mmio.h:30
static uint16_t read16(const void *addr)
Definition: mmio.h:17
static void write16(void *addr, uint16_t val)
Definition: mmio.h:35
#define VBE_DISPI_INDEX_BPP
Definition: bochs.c:22
static void bochs_write(struct resource *res, int index, int val)
Definition: bochs.c:45
#define VBE_DISPI_IOPORT_INDEX
Definition: bochs.c:16
#define VBE_DISPI_ENABLED
Definition: bochs.c:38
#define VBE_DISPI_INDEX_ID
Definition: bochs.c:19
#define VBE_DISPI_INDEX_X_OFFSET
Definition: bochs.c:27
static struct resource res_legacy
Definition: bochs.c:73
static int bochs_read(struct resource *res, int index)
Definition: bochs.c:55
static int width
Definition: bochs.c:42
#define VBE_DISPI_IOPORT_DATA
Definition: bochs.c:17
static void bochs_vga_write(struct resource *res, int index, uint8_t val)
Definition: bochs.c:65
#define VBE_DISPI_INDEX_XRES
Definition: bochs.c:20
#define VBE_DISPI_INDEX_VIRT_WIDTH
Definition: bochs.c:25
#define VBE_DISPI_INDEX_Y_OFFSET
Definition: bochs.c:28
static struct device_operations qemu_graph_ops
Definition: bochs.c:160
static const struct pci_driver qemu_stdvga_driver __pci_driver
Definition: bochs.c:167
#define VBE_DISPI_ID0
Definition: bochs.c:31
#define VBE_DISPI_INDEX_BANK
Definition: bochs.c:24
static void bochs_init_linear_fb(struct device *dev)
Definition: bochs.c:84
#define VBE_DISPI_INDEX_VIRT_HEIGHT
Definition: bochs.c:26
#define VBE_DISPI_INDEX_YRES
Definition: bochs.c:21
#define VBE_DISPI_INDEX_ENABLE
Definition: bochs.c:23
static int height
Definition: bochs.c:43
#define VBE_DISPI_INDEX_VIDEO_MEMORY_64K
Definition: bochs.c:29
static void bochs_init(struct device *dev)
Definition: bochs.c:152
static void bochs_init_text_mode(struct device *dev)
Definition: bochs.c:146
#define VBE_DISPI_LFB_ENABLED
Definition: bochs.c:39
#define printk(level,...)
Definition: stdlib.h:16
void outb(u8 val, u16 port)
u16 inw(u16 port)
void outw(u16 val, u16 port)
struct resource * probe_resource(const struct device *dev, unsigned int index)
See if a resource structure already exists for a given index.
Definition: device_util.c:323
@ CONFIG
Definition: dsi_common.h:201
struct fb_info * fb_add_framebuffer_info(uintptr_t fb_addr, uint32_t x_resolution, uint32_t y_resolution, uint32_t bytes_per_line, uint8_t bits_per_pixel)
Definition: edid_fill_fb.c:89
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
Definition: loglevel.h:128
#define BIOS_ERR
BIOS_ERR - System in incomplete state.
Definition: loglevel.h:72
const char * dev_name
#define PCI_BASE_ADDRESS_2
Definition: pci_def.h:65
#define PCI_BASE_ADDRESS_0
Definition: pci_def.h:63
#define PCI_BASE_ADDRESS_1
Definition: pci_def.h:64
void pci_dev_enable_resources(struct device *dev)
Definition: pci_device.c:721
void pci_dev_read_resources(struct device *dev)
Definition: pci_device.c:534
void pci_dev_set_resources(struct device *dev)
Definition: pci_device.c:691
#define PCI_CLASS_DISPLAY_VGA
Definition: pci_ids.h:35
#define IORESOURCE_MEM
Definition: resource.h:10
#define IORESOURCE_IO
Definition: resource.h:9
static void * res2mmio(const struct resource *res, unsigned long offset, unsigned long mask)
Definition: resource.h:87
#define NULL
Definition: stddef.h:19
unsigned char uint8_t
Definition: stdint.h:8
void(* read_resources)(struct device *dev)
Definition: device.h:39
Definition: device.h:107
unsigned int class
Definition: device.h:120
unsigned long flags
Definition: resource.h:49
resource_t base
Definition: resource.h:45
u8 val
Definition: sys.c:300
void vga_textmode_init(void)
Definition: vga.c:280
void vga_misc_write(unsigned char value)
Definition: vga_io.c:70