QemuVGADriver: add support for QEMU EDID data

Versions of QEMU >= 3.1 support passing of display information from host to guest
via an EDID blob accessible from the stdvga PCI MMIO BAR.

Whilst this feature is still in development, we can start by using the EDID data
to generate the list of supported guest resolutions as suggested by the host. As
EDID blob generation is currently disabled by default, it must be explicitly
enabled on the QEMU command line using "-device VGA,edid=on".

In the cases where the EDID data blob is not present, we fall back to using the
previous hard-coded set of guest resolutions.

Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
diff --git a/QemuVGADriver/QemuVGADriver.mcp.xml b/QemuVGADriver/QemuVGADriver.mcp.xml
index f4f930e..fda99e8 100644
--- a/QemuVGADriver/QemuVGADriver.mcp.xml
+++ b/QemuVGADriver/QemuVGADriver.mcp.xml
Binary files differ
diff --git a/QemuVGADriver/src/QemuEdid.c b/QemuVGADriver/src/QemuEdid.c
new file mode 100644
index 0000000..57de244
--- /dev/null
+++ b/QemuVGADriver/src/QemuEdid.c
Binary files differ
diff --git a/QemuVGADriver/src/QemuVga.c b/QemuVGADriver/src/QemuVga.c
index 4584242..7b6dd23 100644
--- a/QemuVGADriver/src/QemuVga.c
+++ b/QemuVGADriver/src/QemuVga.c
@@ -4,13 +4,8 @@
 #include "QemuVga.h"
 #include <Timer.h>
 
-/* List of supported modes */
-struct vMode {
-	UInt32	width;
-	UInt32	height;
-};
-
-static struct vMode vModes[] =  {
+/*
+static struct _vMode defaultVModes[] =  {
 	{ 640, 480 },
 	{ 800, 600 },
 	{ 1024, 768 },
@@ -18,9 +13,9 @@
 	{ 1600, 1200 },
 	{ 1920, 1080 },
 	{ 1920, 1200 },
-	{ 0,0 }
+	{ 0, 0 }
 };
-
+*/
 static void VgaWriteB(UInt16 port, UInt8 val)
 {
 	UInt8 *ptr;
@@ -152,6 +147,8 @@
 {
 	UInt16 id, i;
 	UInt32 mem, width, height, depth;
+	Boolean modeFound = false;
+	struct vMode *v;
 
 	lprintf("First MMIO read...\n");
 	id = DispiReadW(VBE_DISPI_INDEX_ID);
@@ -174,16 +171,23 @@
 	lprintf("Current setting: %dx%dx%d\n", width, height, depth);
 
 	GLOBAL.depth = GLOBAL.bootDepth = depth;
-	for (i = 0; vModes[i].width; i++) {
-		if (width == vModes[i].width && height == vModes[i].height)
+	GLOBAL.numModes = QemuVga_ReadEdidModes();
+	lprintf("Number of modes: %d\n", GLOBAL.numModes);
+
+	for (i = 0, v = vModes; v != NULL; v = v->next, i++) {
+		if (width == v->mode->width && height == v->mode->height) {
+		    modeFound = true;
 			break;
+		}
 	}
-	if (!vModes[i].width) {
+
+	if (!modeFound) {
 		lprintf("Not found in list ! using default.\n");
 		i = 0;
+	} else {
+	    lprintf("Using mode: %d\n", i);
 	}
 	GLOBAL.bootMode = i;
-	GLOBAL.numModes = sizeof(vModes) / sizeof(struct vMode) - 1;
 
 	QemuVga_SetMode(GLOBAL.bootMode, depth, 0);
 
@@ -305,9 +309,9 @@
 	if (index >= GLOBAL.numModes)
 		return paramErr;
 	if (width)
-		*width = vModes[index].width;
+		*width = getVMode(index)->width;
 	if (height)
-		*height = vModes[index].height;
+		*height = getVMode(index)->height;
 	return noErr;
 }
 
@@ -318,8 +322,8 @@
 
 	if (index >= GLOBAL.numModes)
 		return paramErr;
-	width = vModes[index].width;
-	height = vModes[index].height;
+	width = getVMode(index)->width;
+	height = getVMode(index)->height;
 	pBytes = width * ((depth + 7) / 8) * height;
 	if (pageSize)
 		*pageSize = pBytes;
@@ -340,8 +344,8 @@
 	if (mode >= GLOBAL.numModes)
 		return paramErr;
 	
-	width = vModes[mode].width;
-	height = vModes[mode].height;
+	width = getVMode(mode)->width;
+	height = getVMode(mode)->height;
 	QemuVga_GetModePages(mode, depth, &pageSize, &numPages);
 	lprintf("Set Mode: %dx%dx%d has %d pages\n", width, height, depth, numPages);
 	if (page >= numPages)
diff --git a/QemuVGADriver/src/QemuVga.h b/QemuVGADriver/src/QemuVga.h
index 69e80fa..f070bb7 100644
--- a/QemuVGADriver/src/QemuVga.h
+++ b/QemuVGADriver/src/QemuVga.h
@@ -45,6 +45,22 @@
 #define VBE_DISPI_LFB_ENABLED            0x40
 #define VBE_DISPI_NOCLEARMEM             0x80
 
+/* --- VModes */
+
+struct _vMode {
+    UInt32 width;
+    UInt32 height;
+};
+
+struct vMode {
+    struct vMode *next;
+    struct _vMode *mode;
+};
+
+extern struct vMode *vModes;
+extern struct _vMode defaultVModes[];
+extern struct _vMode *getVMode(UInt16 idx);
+
 /* --- Internal APIs */
 
 extern OSStatus	QemuVga_Init();
@@ -56,6 +72,8 @@
 extern void QemuVga_EnableInterrupts(void);
 extern void QemuVga_DisableInterrupts(void);
 
+extern UInt16 QemuVga_ReadEdidModes(void);
+
 extern OSStatus	QemuVga_SetDepth(UInt32 bpp);
 
 extern OSStatus	QemuVga_SetColorEntry(UInt32 index, RGBColor *color);
diff --git a/builds/qemu_vga.ndrv b/builds/qemu_vga.ndrv
index 6e02f74..4197767 100644
--- a/builds/qemu_vga.ndrv
+++ b/builds/qemu_vga.ndrv
Binary files differ
diff --git a/builds/qemu_vga_debugosi.ndrv b/builds/qemu_vga_debugosi.ndrv
index 639a0c5..b4036c0 100644
--- a/builds/qemu_vga_debugosi.ndrv
+++ b/builds/qemu_vga_debugosi.ndrv
Binary files differ