summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore14
-rw-r--r--Makefile.am6
-rwxr-xr-xautogen.sh12
-rw-r--r--configure.ac15
-rw-r--r--vbe_edid.c189
5 files changed, 236 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..40d3a4b
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,14 @@
+.deps/
+Makefile
+Makefile.in
+aclocal.m4
+autom4te.cache/
+config.log
+config.status
+configure
+depcomp
+install-sh
+missing
+*.edid
+*.o
+vbe_edid
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..2a7e1bd
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,6 @@
+AUTOMAKE_OPTIONS = foreign
+
+sbin_PROGRAMS = vbe-edid
+
+vbe_edid_SOURCES = vbe_edid.c
+vbe_edid_LDADD = -lx86
diff --git a/autogen.sh b/autogen.sh
new file mode 100755
index 0000000..354f254
--- /dev/null
+++ b/autogen.sh
@@ -0,0 +1,12 @@
+#! /bin/sh
+
+srcdir=`dirname $0`
+test -z "$srcdir" && srcdir=.
+
+ORIGDIR=`pwd`
+cd $srcdir
+
+autoreconf -v --install || exit 1
+cd $ORIGDIR || exit $?
+
+$srcdir/configure "$@"
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..32e671a
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,15 @@
+dnl Process this file with autoconf to produce a configure script.
+
+AC_INIT(vbe-edid, 0.0.1)
+AM_INIT_AUTOMAKE()
+
+dnl Checks for programs
+
+CFLAGS="-g -O0 -Wall"
+
+AC_PROG_CC
+
+AC_CHECK_LIB([x86], [LRMI_init], [], [AC_MSG_ERROR([libx86 not found])])
+AC_CHECK_HEADER([libx86.h], [], [AC_MSG_ERROR([libx86.h not found])])
+
+AC_OUTPUT([Makefile])
diff --git a/vbe_edid.c b/vbe_edid.c
new file mode 100644
index 0000000..0d8e056
--- /dev/null
+++ b/vbe_edid.c
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2010 Luc Verhaegen <libv@skynet.be>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Based on get-edid.c by John Fremlin, but this one is actual C code, and
+ * the content of get-edid.c or this file is not exactly rocket-science.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/io.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <libx86.h>
+
+static int
+vbe_call(struct LRMI_regs *regs, unsigned char al, unsigned char bl)
+{
+ regs->eax = 0x4F00 | al;
+ regs->ebx = bl;
+
+ if (!LRMI_int(0x10, regs)) {
+ fprintf(stderr, "%s: LRMI_int failed!\n", __func__);
+ return -1;
+ }
+
+ if (regs->eax == 0x4F)
+ return 0;
+ else if (regs->eax == 0x014F) {
+ fprintf(stderr, "VBE Call 0x%02X failed!\n", al);
+ return -1;
+ } else {
+ fprintf(stderr, "VBE Call 0x%02X is unsupported!\n", al);
+ return -1;
+ }
+}
+
+static int
+vbe_controller_info(void)
+{
+ struct LRMI_regs regs = { 0 };
+ unsigned char *info;
+ int ret;
+
+ info = LRMI_alloc_real(512);
+ if (!info) {
+ fprintf(stderr, "Error: %s: LRMI_alloc_real failed!\n",
+ __func__);
+ return -1;
+ }
+
+ memcpy(info, "VBE2", 4);
+ regs.es = ((unsigned long) info) >> 4;
+ regs.edi = 0;
+
+ ret = vbe_call(&regs, 0x00, 0x00);
+ if (!ret)
+ printf("Found VBE Version %d.%d.\n", info[5], info[4]);
+
+ LRMI_free_real(info);
+
+ return ret;
+}
+
+static int
+edid_dump(unsigned char *edid, int size)
+{
+ char name[4], filename[14];
+ unsigned short model;
+ int fd;
+
+ if ((size < 128) ||
+ memcmp(edid, "\x00\xFF\xFF\xFF\xFF\xFF\xFF\x00", 8)) {
+ fprintf(stderr, "Error: Invalid EDID header!\n");
+ return -1;
+ }
+
+ name[0] = edid[8] >> 2;
+ name[1] = ((edid[8] & 0x03) << 3) | (edid[9] >> 5);
+ name[2] = edid[9] & 0x1F;
+
+ if ((name[0] && (name[0] < 27)) &&
+ (name[1] && (name[1] < 27)) &&
+ (name[2] && (name[2] < 27))) {
+ name[0] += 0x60;
+ name[1] += 0x60;
+ name[2] += 0x60;
+ } else {
+ name[0] = 'x';
+ name[1] = 'x';
+ name[2] = 'x';
+ }
+ name[3] = 0;
+
+ model = edid[0x0A] | (edid[0x0B] << 8);
+
+ sprintf(filename, "%s-%04x.edid", name, model);
+
+ fd = open(filename, O_WRONLY | O_CREAT | O_EXCL);
+ if (fd < 0) {
+ fprintf(stderr, "Failed to open %s: %s\n",
+ filename, strerror(errno));
+ return -errno;
+ }
+
+ if (write(fd, edid, size) == -1) {
+ fprintf(stderr, "Failed to write to %s: %s\n",
+ filename, strerror(errno));
+ return -errno;
+ }
+
+ printf("Dumped %d bytes to %s\n", size, filename);
+
+ close(fd);
+
+ return 0;
+}
+
+static int
+vbe_edid_read(void)
+{
+ struct LRMI_regs regs = { 0 };
+ unsigned char *edid;
+ int ret = 0;
+
+ edid = LRMI_alloc_real(128);
+ if (!edid) {
+ fprintf(stderr, "Error: %s: LRMI_ALLOC_REAL failed!\n",
+ __func__);
+ return -1;
+ }
+
+ regs.es = ((unsigned long) edid) >> 4;
+ regs.edi = 0;
+ regs.ecx = 0;
+ regs.edx = 1;
+
+ ret = vbe_call(&regs, 0x15, 0x01);
+ if (!ret)
+ edid_dump(edid, 128);
+
+ LRMI_free_real(edid);
+
+ return ret;
+}
+
+int
+main(int argc, char *argv[])
+{
+ int ret;
+
+ if (iopl(3)) {
+ fprintf(stderr, "Error: iopl failed: %s\n", strerror(errno));
+ return -errno;
+ }
+
+ if (!LRMI_init()) {
+ fprintf(stderr, "Error: LRMI_init() failed!\n");
+ return -1;
+ }
+
+ ret = vbe_controller_info();
+ if (!ret)
+ ret = vbe_edid_read();
+
+ return ret;
+}