summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile11
-rw-r--r--cirrus.c142
-rw-r--r--cirrus.h51
-rw-r--r--cve-2017-2615.c243
-rw-r--r--pci.c75
-rw-r--r--pci.h9
6 files changed, 289 insertions, 242 deletions
diff --git a/Makefile b/Makefile
index 05b84cd..af9d16c 100644
--- a/Makefile
+++ b/Makefile
@@ -3,14 +3,17 @@ CC ?= gcc
CFLAGS ?= -Os -g
CFLAGS += -Wall
-SOURCES := $(wildcard *.c)
-TARGETS := $(patsubst %.c,%,$(SOURCES))
+CVETEST := cve-2016-3712
+PCITEST := cve-2017-2615
+TARGETS := $(CVETEST) $(PCITEST)
-cve-2017-2615 : CFLAGS += $(shell pkg-config --cflags libpci)
-cve-2017-2615 : LDLIBS += $(shell pkg-config --libs libpci)
+$(PCITEST) : CFLAGS += $(shell pkg-config --cflags libpci)
+$(PCITEST) : LDLIBS += $(shell pkg-config --libs libpci)
all: $(TARGETS)
clean:
rm -f $(TARGETS)
rm -f *~ *.o
+
+cve-2017-2615: cve-2017-2615.o pci.o cirrus.o
diff --git a/cirrus.c b/cirrus.c
new file mode 100644
index 0000000..7e4015c
--- /dev/null
+++ b/cirrus.c
@@ -0,0 +1,142 @@
+/*
+
+mode setting sequence done by cirrus drm driver
+
+--- set mode ( 1024 x 768 @ 24 bpp ) ---
+vga_cirrus_write_io addr 0x3d4, val 0x11
+vga_cirrus_write_io addr 0x3d5, val 0x20
+vga_cirrus_write_io addr 0x3d4, val 0x0
+vga_cirrus_write_io addr 0x3d5, val 0xa3
+vga_cirrus_write_io addr 0x3d4, val 0x1
+vga_cirrus_write_io addr 0x3d5, val 0x7f
+vga_cirrus_write_io addr 0x3d4, val 0x4
+vga_cirrus_write_io addr 0x3d5, val 0x84
+vga_cirrus_write_io addr 0x3d4, val 0x5
+vga_cirrus_write_io addr 0x3d5, val 0x95
+vga_cirrus_write_io addr 0x3d4, val 0x6
+vga_cirrus_write_io addr 0x3d5, val 0x24
+vga_cirrus_write_io addr 0x3d4, val 0x12
+vga_cirrus_write_io addr 0x3d5, val 0xff
+vga_cirrus_write_io addr 0x3d4, val 0x9
+vga_cirrus_write_io addr 0x3d5, val 0x60
+vga_cirrus_write_io addr 0x3d4, val 0x7
+vga_cirrus_write_io addr 0x3d5, val 0x79
+vga_cirrus_write_io addr 0x3d4, val 0x1a
+vga_cirrus_write_io addr 0x3d5, val 0xe0
+vga_cirrus_write_io addr 0x3d4, val 0x17
+vga_cirrus_write_io addr 0x3d5, val 0x3
+
+vga_cirrus_write_io addr 0x3c4, val 0x7
+vga_cirrus_read_io addr 0x3c5, val 0x0
+vga_cirrus_write_io addr 0x3c4, val 0x7
+vga_cirrus_write_io addr 0x3c5, val 0x15
+
+vga_cirrus_write_io addr 0x3d4, val 0x13
+vga_cirrus_write_io addr 0x3d5, val 0x80
+vga_cirrus_write_io addr 0x3d4, val 0x1b
+vga_cirrus_write_io addr 0x3d5, val 0x32
+vga_cirrus_write_io addr 0x3ce, val 0x5
+vga_cirrus_write_io addr 0x3cf, val 0x40
+vga_cirrus_write_io addr 0x3ce, val 0x6
+vga_cirrus_write_io addr 0x3cf, val 0x1
+
+vga_cirrus_read_io addr 0x3c6, val 0xff
+vga_cirrus_read_io addr 0x3c6, val 0xff
+vga_cirrus_read_io addr 0x3c6, val 0xff
+vga_cirrus_read_io addr 0x3c6, val 0xff
+vga_cirrus_write_io addr 0x3c6, val 0xc5
+
+--- set base address ( 0 ) ---
+vga_cirrus_write_io addr 0x3d4, val 0xc
+vga_cirrus_write_io addr 0x3d5, val 0x0
+vga_cirrus_write_io addr 0x3d4, val 0xd
+vga_cirrus_write_io addr 0x3d5, val 0x0
+
+vga_cirrus_write_io addr 0x3d4, val 0x1b
+vga_cirrus_read_io addr 0x3d5, val 0x32
+vga_cirrus_write_io addr 0x3d4, val 0x1b
+vga_cirrus_write_io addr 0x3d5, val 0x32
+
+vga_cirrus_write_io addr 0x3d4, val 0x1d
+vga_cirrus_read_io addr 0x3d5, val 0x0
+vga_cirrus_write_io addr 0x3d4, val 0x1d
+vga_cirrus_write_io addr 0x3d5, val 0x0
+
+-- unblank --
+vga_cirrus_write_io addr 0x3c0, val 0x20
+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+
+#include "cirrus.h"
+
+void cirrus_setmode(volatile uint8_t *mmio)
+{
+ fprintf(stderr, "setting mode (1024x768 @ 24bpp)\n");
+ /* mode */
+ mmio[0x3d4 + VGA_OFFSET] = 0x11;
+ mmio[0x3d5 + VGA_OFFSET] = 0x20;
+ mmio[0x3d4 + VGA_OFFSET] = 0x0;
+ mmio[0x3d5 + VGA_OFFSET] = 0xa3;
+ mmio[0x3d4 + VGA_OFFSET] = 0x1;
+ mmio[0x3d5 + VGA_OFFSET] = 0x7f;
+ mmio[0x3d4 + VGA_OFFSET] = 0x4;
+ mmio[0x3d5 + VGA_OFFSET] = 0x84;
+ mmio[0x3d4 + VGA_OFFSET] = 0x5;
+ mmio[0x3d5 + VGA_OFFSET] = 0x95;
+ mmio[0x3d4 + VGA_OFFSET] = 0x6;
+ mmio[0x3d5 + VGA_OFFSET] = 0x24;
+ mmio[0x3d4 + VGA_OFFSET] = 0x12;
+ mmio[0x3d5 + VGA_OFFSET] = 0xff;
+ mmio[0x3d4 + VGA_OFFSET] = 0x9;
+ mmio[0x3d5 + VGA_OFFSET] = 0x60;
+ mmio[0x3d4 + VGA_OFFSET] = 0x7;
+ mmio[0x3d5 + VGA_OFFSET] = 0x79;
+ mmio[0x3d4 + VGA_OFFSET] = 0x1a;
+ mmio[0x3d5 + VGA_OFFSET] = 0xe0;
+ mmio[0x3d4 + VGA_OFFSET] = 0x17;
+ mmio[0x3d5 + VGA_OFFSET] = 0x3;
+ mmio[0x3c4 + VGA_OFFSET] = 0x7;
+ mmio[0x3c5 + VGA_OFFSET] = 0x15;
+ mmio[0x3d4 + VGA_OFFSET] = 0x13;
+ mmio[0x3d5 + VGA_OFFSET] = 0x80;
+ mmio[0x3d4 + VGA_OFFSET] = 0x1b;
+ mmio[0x3d5 + VGA_OFFSET] = 0x32;
+ mmio[0x3ce + VGA_OFFSET] = 0x5;
+ mmio[0x3cf + VGA_OFFSET] = 0x40;
+ mmio[0x3ce + VGA_OFFSET] = 0x6;
+ mmio[0x3cf + VGA_OFFSET] = 0x1;
+#if 0
+ mmio[0x3c6 + VGA_OFFSET];
+ mmio[0x3c6 + VGA_OFFSET];
+ mmio[0x3c6 + VGA_OFFSET];
+ mmio[0x3c6 + VGA_OFFSET];
+ mmio[0x3c6 + VGA_OFFSET] = 0xc5;
+#endif
+
+ /* base */
+ mmio[0x3d4 + VGA_OFFSET] = 0xc;
+ mmio[0x3d5 + VGA_OFFSET] = 0x0;
+ mmio[0x3d4 + VGA_OFFSET] = 0xd;
+ mmio[0x3d5 + VGA_OFFSET] = 0x0;
+ mmio[0x3d4 + VGA_OFFSET] = 0x1b;
+ mmio[0x3d5 + VGA_OFFSET] = 0x32;
+ mmio[0x3d4 + VGA_OFFSET] = 0x1d;
+ mmio[0x3d5 + VGA_OFFSET] = 0x0;
+
+ /* dpms */
+ mmio[0x3d4 + VGA_OFFSET] = 0x1;
+ mmio[0x3d5 + VGA_OFFSET] = 0x0;
+ mmio[0x3ce + VGA_OFFSET] = 0xe;
+ mmio[0x3cf + VGA_OFFSET] = 0x1;
+
+ /* unblank */
+ mmio[0x3c0 + VGA_OFFSET] = 0x20;
+
+ fprintf(stderr, "mode done\n");
+ sleep(1);
+}
diff --git a/cirrus.h b/cirrus.h
new file mode 100644
index 0000000..bda4dc4
--- /dev/null
+++ b/cirrus.h
@@ -0,0 +1,51 @@
+#define VGA_OFFSET (-0x3c0)
+#define BLT_OFFSET (0x100)
+
+#define CIRRUS_MMIO_BLTBGCOLOR 0x00 // dword
+#define CIRRUS_MMIO_BLTFGCOLOR 0x04 // dword
+#define CIRRUS_MMIO_BLTWIDTH 0x08 // word
+#define CIRRUS_MMIO_BLTHEIGHT 0x0a // word
+#define CIRRUS_MMIO_BLTDESTPITCH 0x0c // word
+#define CIRRUS_MMIO_BLTSRCPITCH 0x0e // word
+#define CIRRUS_MMIO_BLTDESTADDR 0x10 // dword
+#define CIRRUS_MMIO_BLTSRCADDR 0x14 // dword
+#define CIRRUS_MMIO_BLTWRITEMASK 0x17 // byte
+#define CIRRUS_MMIO_BLTMODE 0x18 // byte
+#define CIRRUS_MMIO_BLTROP 0x1a // byte
+#define CIRRUS_MMIO_BLTMODEEXT 0x1b // byte
+#define CIRRUS_MMIO_BLTSTATUS 0x40 // byte
+
+#define CIRRUS_BLT_BUSY 0x01
+#define CIRRUS_BLT_START 0x02
+#define CIRRUS_BLT_RESET 0x04
+
+#define CIRRUS_BLTMODE_BACKWARDS 0x01
+#define CIRRUS_BLTMODE_MEMSYSDEST 0x02
+#define CIRRUS_BLTMODE_MEMSYSSRC 0x04
+#define CIRRUS_BLTMODE_TRANSPARENTCOMP 0x08
+#define CIRRUS_BLTMODE_PATTERNCOPY 0x40
+#define CIRRUS_BLTMODE_COLOREXPAND 0x80
+#define CIRRUS_BLTMODE_PIXELWIDTHMASK 0x30
+#define CIRRUS_BLTMODE_PIXELWIDTH8 0x00
+#define CIRRUS_BLTMODE_PIXELWIDTH16 0x10
+#define CIRRUS_BLTMODE_PIXELWIDTH24 0x20
+#define CIRRUS_BLTMODE_PIXELWIDTH32 0x30
+
+#define CIRRUS_ROP_0 0x00
+#define CIRRUS_ROP_SRC_AND_DST 0x05
+#define CIRRUS_ROP_NOP 0x06
+#define CIRRUS_ROP_SRC_AND_NOTDST 0x09
+#define CIRRUS_ROP_NOTDST 0x0b
+#define CIRRUS_ROP_SRC 0x0d
+#define CIRRUS_ROP_1 0x0e
+#define CIRRUS_ROP_NOTSRC_AND_DST 0x50
+#define CIRRUS_ROP_SRC_XOR_DST 0x59
+#define CIRRUS_ROP_SRC_OR_DST 0x6d
+#define CIRRUS_ROP_NOTSRC_OR_NOTDST 0x90
+#define CIRRUS_ROP_SRC_NOTXOR_DST 0x95
+#define CIRRUS_ROP_SRC_OR_NOTDST 0xad
+#define CIRRUS_ROP_NOTSRC 0xd0
+#define CIRRUS_ROP_NOTSRC_OR_DST 0xd6
+#define CIRRUS_ROP_NOTSRC_AND_NOTDST 0xda
+
+void cirrus_setmode(volatile uint8_t *mmio);
diff --git a/cve-2017-2615.c b/cve-2017-2615.c
index b953634..2b66f6b 100644
--- a/cve-2017-2615.c
+++ b/cve-2017-2615.c
@@ -1,72 +1,3 @@
-/*
-
-mode setting sequence done by cirrus drm driver
-
---- set mode ( 1024 x 768 @ 24 bpp ) ---
-vga_cirrus_write_io addr 0x3d4, val 0x11
-vga_cirrus_write_io addr 0x3d5, val 0x20
-vga_cirrus_write_io addr 0x3d4, val 0x0
-vga_cirrus_write_io addr 0x3d5, val 0xa3
-vga_cirrus_write_io addr 0x3d4, val 0x1
-vga_cirrus_write_io addr 0x3d5, val 0x7f
-vga_cirrus_write_io addr 0x3d4, val 0x4
-vga_cirrus_write_io addr 0x3d5, val 0x84
-vga_cirrus_write_io addr 0x3d4, val 0x5
-vga_cirrus_write_io addr 0x3d5, val 0x95
-vga_cirrus_write_io addr 0x3d4, val 0x6
-vga_cirrus_write_io addr 0x3d5, val 0x24
-vga_cirrus_write_io addr 0x3d4, val 0x12
-vga_cirrus_write_io addr 0x3d5, val 0xff
-vga_cirrus_write_io addr 0x3d4, val 0x9
-vga_cirrus_write_io addr 0x3d5, val 0x60
-vga_cirrus_write_io addr 0x3d4, val 0x7
-vga_cirrus_write_io addr 0x3d5, val 0x79
-vga_cirrus_write_io addr 0x3d4, val 0x1a
-vga_cirrus_write_io addr 0x3d5, val 0xe0
-vga_cirrus_write_io addr 0x3d4, val 0x17
-vga_cirrus_write_io addr 0x3d5, val 0x3
-
-vga_cirrus_write_io addr 0x3c4, val 0x7
-vga_cirrus_read_io addr 0x3c5, val 0x0
-vga_cirrus_write_io addr 0x3c4, val 0x7
-vga_cirrus_write_io addr 0x3c5, val 0x15
-
-vga_cirrus_write_io addr 0x3d4, val 0x13
-vga_cirrus_write_io addr 0x3d5, val 0x80
-vga_cirrus_write_io addr 0x3d4, val 0x1b
-vga_cirrus_write_io addr 0x3d5, val 0x32
-vga_cirrus_write_io addr 0x3ce, val 0x5
-vga_cirrus_write_io addr 0x3cf, val 0x40
-vga_cirrus_write_io addr 0x3ce, val 0x6
-vga_cirrus_write_io addr 0x3cf, val 0x1
-
-vga_cirrus_read_io addr 0x3c6, val 0xff
-vga_cirrus_read_io addr 0x3c6, val 0xff
-vga_cirrus_read_io addr 0x3c6, val 0xff
-vga_cirrus_read_io addr 0x3c6, val 0xff
-vga_cirrus_write_io addr 0x3c6, val 0xc5
-
---- set base address ( 0 ) ---
-vga_cirrus_write_io addr 0x3d4, val 0xc
-vga_cirrus_write_io addr 0x3d5, val 0x0
-vga_cirrus_write_io addr 0x3d4, val 0xd
-vga_cirrus_write_io addr 0x3d5, val 0x0
-
-vga_cirrus_write_io addr 0x3d4, val 0x1b
-vga_cirrus_read_io addr 0x3d5, val 0x32
-vga_cirrus_write_io addr 0x3d4, val 0x1b
-vga_cirrus_write_io addr 0x3d5, val 0x32
-
-vga_cirrus_write_io addr 0x3d4, val 0x1d
-vga_cirrus_read_io addr 0x3d5, val 0x0
-vga_cirrus_write_io addr 0x3d4, val 0x1d
-vga_cirrus_write_io addr 0x3d5, val 0x0
-
--- unblank --
-vga_cirrus_write_io addr 0x3c0, val 0x20
-
-*/
-
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
@@ -77,183 +8,19 @@ vga_cirrus_write_io addr 0x3c0, val 0x20
#include <sys/io.h>
#include <sys/mman.h>
-#include <pci/pci.h>
-
-struct pci_access *pci;
-struct pci_dev *dev;
-
-static void find_device(unsigned int vendor,
- unsigned int device)
-{
- struct pci_filter filter;
- struct pci_dev *d;
-
- pci_scan_bus(pci);
- pci_filter_init(pci, &filter);
- filter.vendor = vendor;
- filter.device = device;
-
- for (d = pci->devices; d != NULL; d = d->next) {
- if (!pci_filter_match(&filter, d))
- continue;
- dev = d;
- return;
- }
- return;
-}
-
-#define VGA_OFFSET (-0x3c0)
-#define BLT_OFFSET (0x100)
-
-#define CIRRUS_MMIO_BLTBGCOLOR 0x00 // dword
-#define CIRRUS_MMIO_BLTFGCOLOR 0x04 // dword
-#define CIRRUS_MMIO_BLTWIDTH 0x08 // word
-#define CIRRUS_MMIO_BLTHEIGHT 0x0a // word
-#define CIRRUS_MMIO_BLTDESTPITCH 0x0c // word
-#define CIRRUS_MMIO_BLTSRCPITCH 0x0e // word
-#define CIRRUS_MMIO_BLTDESTADDR 0x10 // dword
-#define CIRRUS_MMIO_BLTSRCADDR 0x14 // dword
-#define CIRRUS_MMIO_BLTWRITEMASK 0x17 // byte
-#define CIRRUS_MMIO_BLTMODE 0x18 // byte
-#define CIRRUS_MMIO_BLTROP 0x1a // byte
-#define CIRRUS_MMIO_BLTMODEEXT 0x1b // byte
-#define CIRRUS_MMIO_BLTSTATUS 0x40 // byte
-
-#define CIRRUS_BLT_BUSY 0x01
-#define CIRRUS_BLT_START 0x02
-#define CIRRUS_BLT_RESET 0x04
-
-#define CIRRUS_BLTMODE_BACKWARDS 0x01
-#define CIRRUS_BLTMODE_MEMSYSDEST 0x02
-#define CIRRUS_BLTMODE_MEMSYSSRC 0x04
-#define CIRRUS_BLTMODE_TRANSPARENTCOMP 0x08
-#define CIRRUS_BLTMODE_PATTERNCOPY 0x40
-#define CIRRUS_BLTMODE_COLOREXPAND 0x80
-#define CIRRUS_BLTMODE_PIXELWIDTHMASK 0x30
-#define CIRRUS_BLTMODE_PIXELWIDTH8 0x00
-#define CIRRUS_BLTMODE_PIXELWIDTH16 0x10
-#define CIRRUS_BLTMODE_PIXELWIDTH24 0x20
-#define CIRRUS_BLTMODE_PIXELWIDTH32 0x30
-
-#define CIRRUS_ROP_0 0x00
-#define CIRRUS_ROP_SRC_AND_DST 0x05
-#define CIRRUS_ROP_NOP 0x06
-#define CIRRUS_ROP_SRC_AND_NOTDST 0x09
-#define CIRRUS_ROP_NOTDST 0x0b
-#define CIRRUS_ROP_SRC 0x0d
-#define CIRRUS_ROP_1 0x0e
-#define CIRRUS_ROP_NOTSRC_AND_DST 0x50
-#define CIRRUS_ROP_SRC_XOR_DST 0x59
-#define CIRRUS_ROP_SRC_OR_DST 0x6d
-#define CIRRUS_ROP_NOTSRC_OR_NOTDST 0x90
-#define CIRRUS_ROP_SRC_NOTXOR_DST 0x95
-#define CIRRUS_ROP_SRC_OR_NOTDST 0xad
-#define CIRRUS_ROP_NOTSRC 0xd0
-#define CIRRUS_ROP_NOTSRC_OR_DST 0xd6
-#define CIRRUS_ROP_NOTSRC_AND_NOTDST 0xda
+#include "pci.h"
+#include "cirrus.h"
int main(int argc, char *argv[])
{
- char mmiofile[128];
- int mmiofd;
volatile uint8_t *mmio;
- pci = pci_alloc();
- if (!pci) {
- fprintf(stderr, "libpci alloc failed\n");
- exit(1);
- }
- pci_init(pci);
-
- find_device(0x1013, 0x00b8);
- if (!dev) {
- fprintf(stderr, "cirrus not found\n");
- exit(1);
- }
- fprintf(stderr, "cirrus found at %02x:%02x.%x, mmio @ 0x%08x\n",
- dev->bus, dev->dev, dev->func,
- (uint32_t) dev->base_addr[1]);
-
- snprintf(mmiofile, sizeof(mmiofile),
- "/sys/bus/pci/devices/%04x:%02x:%02x.%x/resource1",
- dev->domain, dev->bus, dev->dev, dev->func);
- mmiofd = open(mmiofile, O_RDWR);
- if (mmiofd < 0) {
- fprintf(stderr, "open %s: %s\n", mmiofile, strerror(errno));
- exit(1);
- }
- mmio = mmap(NULL, 4096, PROT_WRITE | PROT_READ, MAP_SHARED, mmiofd, 0);
- if (mmio == MAP_FAILED) {
- fprintf(stderr, "mmap %s: %s\n", mmiofile, strerror(errno));
- exit(1);
- }
-
+ find_device("cirrus", 0x1013, 0x00b8);
+ mmio = mmap_bar(1);
fprintf(stderr, "init ok\n");
sleep(1);
- fprintf(stderr, "setting mode (1024x768 @ 24bpp)\n");
- /* mode */
- mmio[0x3d4 + VGA_OFFSET] = 0x11;
- mmio[0x3d5 + VGA_OFFSET] = 0x20;
- mmio[0x3d4 + VGA_OFFSET] = 0x0;
- mmio[0x3d5 + VGA_OFFSET] = 0xa3;
- mmio[0x3d4 + VGA_OFFSET] = 0x1;
- mmio[0x3d5 + VGA_OFFSET] = 0x7f;
- mmio[0x3d4 + VGA_OFFSET] = 0x4;
- mmio[0x3d5 + VGA_OFFSET] = 0x84;
- mmio[0x3d4 + VGA_OFFSET] = 0x5;
- mmio[0x3d5 + VGA_OFFSET] = 0x95;
- mmio[0x3d4 + VGA_OFFSET] = 0x6;
- mmio[0x3d5 + VGA_OFFSET] = 0x24;
- mmio[0x3d4 + VGA_OFFSET] = 0x12;
- mmio[0x3d5 + VGA_OFFSET] = 0xff;
- mmio[0x3d4 + VGA_OFFSET] = 0x9;
- mmio[0x3d5 + VGA_OFFSET] = 0x60;
- mmio[0x3d4 + VGA_OFFSET] = 0x7;
- mmio[0x3d5 + VGA_OFFSET] = 0x79;
- mmio[0x3d4 + VGA_OFFSET] = 0x1a;
- mmio[0x3d5 + VGA_OFFSET] = 0xe0;
- mmio[0x3d4 + VGA_OFFSET] = 0x17;
- mmio[0x3d5 + VGA_OFFSET] = 0x3;
- mmio[0x3c4 + VGA_OFFSET] = 0x7;
- mmio[0x3c5 + VGA_OFFSET] = 0x15;
- mmio[0x3d4 + VGA_OFFSET] = 0x13;
- mmio[0x3d5 + VGA_OFFSET] = 0x80;
- mmio[0x3d4 + VGA_OFFSET] = 0x1b;
- mmio[0x3d5 + VGA_OFFSET] = 0x32;
- mmio[0x3ce + VGA_OFFSET] = 0x5;
- mmio[0x3cf + VGA_OFFSET] = 0x40;
- mmio[0x3ce + VGA_OFFSET] = 0x6;
- mmio[0x3cf + VGA_OFFSET] = 0x1;
-#if 0
- mmio[0x3c6 + VGA_OFFSET];
- mmio[0x3c6 + VGA_OFFSET];
- mmio[0x3c6 + VGA_OFFSET];
- mmio[0x3c6 + VGA_OFFSET];
- mmio[0x3c6 + VGA_OFFSET] = 0xc5;
-#endif
-
- /* base */
- mmio[0x3d4 + VGA_OFFSET] = 0xc;
- mmio[0x3d5 + VGA_OFFSET] = 0x0;
- mmio[0x3d4 + VGA_OFFSET] = 0xd;
- mmio[0x3d5 + VGA_OFFSET] = 0x0;
- mmio[0x3d4 + VGA_OFFSET] = 0x1b;
- mmio[0x3d5 + VGA_OFFSET] = 0x32;
- mmio[0x3d4 + VGA_OFFSET] = 0x1d;
- mmio[0x3d5 + VGA_OFFSET] = 0x0;
-
- /* dpms */
- mmio[0x3d4 + VGA_OFFSET] = 0x1;
- mmio[0x3d5 + VGA_OFFSET] = 0x0;
- mmio[0x3ce + VGA_OFFSET] = 0xe;
- mmio[0x3cf + VGA_OFFSET] = 0x1;
-
- /* unblank */
- mmio[0x3c0 + VGA_OFFSET] = 0x20;
-
- fprintf(stderr, "mode done\n");
- sleep(1);
+ cirrus_setmode(mmio);
fprintf(stderr, "trying invalid backwards blit\n");
mmio[BLT_OFFSET + CIRRUS_MMIO_BLTSTATUS] = CIRRUS_BLT_RESET;
diff --git a/pci.c b/pci.c
new file mode 100644
index 0000000..16569ae
--- /dev/null
+++ b/pci.c
@@ -0,0 +1,75 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/mman.h>
+
+#include "pci.h"
+
+struct pci_access *pci;
+struct pci_dev *dev;
+
+void find_device(char *name,
+ unsigned int vendor,
+ unsigned int device)
+{
+ struct pci_filter filter;
+ struct pci_dev *d;
+
+ if (!pci) {
+ pci = pci_alloc();
+ if (!pci) {
+ fprintf(stderr, "libpci alloc failed\n");
+ exit(1);
+ }
+ pci_init(pci);
+ pci_scan_bus(pci);
+ }
+
+ pci_filter_init(pci, &filter);
+ filter.vendor = vendor;
+ filter.device = device;
+
+ for (d = pci->devices; d != NULL; d = d->next) {
+ if (!pci_filter_match(&filter, d))
+ continue;
+ dev = d;
+ fprintf(stderr, "%s found at %02x:%02x.%x\n",
+ name, dev->bus, dev->dev, dev->func);
+ return;
+ }
+ fprintf(stderr, "%s not found\n", name);
+ exit(1);
+}
+
+void *mmap_bar(int nr)
+{
+ char filename[128];
+ size_t size;
+ int fd;
+ void *bar;
+
+ snprintf(filename, sizeof(filename),
+ "/sys/bus/pci/devices/%04x:%02x:%02x.%x/resource%d",
+ dev->domain, dev->bus, dev->dev, dev->func, nr);
+ size = dev->size[nr];
+ fd = open(filename, O_RDWR);
+ if (fd < 0) {
+ fprintf(stderr, "open %s: %s\n", filename, strerror(errno));
+ exit(1);
+ }
+ bar = mmap(NULL, size, PROT_WRITE | PROT_READ, MAP_SHARED, fd, 0);
+ if (bar == MAP_FAILED) {
+ fprintf(stderr, "mmap %s: %s\n", filename, strerror(errno));
+ exit(1);
+ }
+ if (size >= (1 << 20)) {
+ fprintf(stderr, "bar %d mapped (%zd MB)\n", nr, size >> 20);
+ } else {
+ fprintf(stderr, "bar %d mapped (%zd bytes)\n", nr, size);
+ }
+ return bar;
+}
diff --git a/pci.h b/pci.h
new file mode 100644
index 0000000..b28dabe
--- /dev/null
+++ b/pci.h
@@ -0,0 +1,9 @@
+#include <pci/pci.h>
+
+extern struct pci_access *pci;
+extern struct pci_dev *dev;
+
+void find_device(char *name,
+ unsigned int vendor,
+ unsigned int device);
+void *mmap_bar(int nr);