summaryrefslogtreecommitdiff
path: root/src/bios_reader/bios_reader.c
diff options
context:
space:
mode:
authorEric Anholt <anholt@FreeBSD.org>2006-04-16 13:05:35 -0500
committerEric Anholt <anholt@FreeBSD.org>2006-04-16 13:05:35 -0500
commit786ee3df1726f08953167d05f7fa1930452703bb (patch)
tree1498851b99a532c7b1927f81576a1cba22e95944 /src/bios_reader/bios_reader.c
parent62652127cd12f5a0fc9364285b81d2661372148a (diff)
Add a standalone program for parsing VBT.
Diffstat (limited to 'src/bios_reader/bios_reader.c')
-rw-r--r--src/bios_reader/bios_reader.c163
1 files changed, 163 insertions, 0 deletions
diff --git a/src/bios_reader/bios_reader.c b/src/bios_reader/bios_reader.c
new file mode 100644
index 00000000..a52bcc72
--- /dev/null
+++ b/src/bios_reader/bios_reader.c
@@ -0,0 +1,163 @@
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * 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, sublicense,
+ * 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 NONINFRINGEMENT. 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.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#define _PARSE_EDID_
+#include "edid.h"
+
+/* Define some types so we can reuse i830_bios.h */
+typedef void *ScrnInfoPtr;
+typedef int Bool;
+#define TRUE 1
+#define FALSE 0
+#include "../i830_bios.h"
+
+
+/* Make a fake pI830 so we can easily pull i830_bios.c code in here. */
+struct _fake_i830 {
+ CARD8 *VBIOS;
+};
+struct _fake_i830 I830;
+struct _fake_i830 *pI830 = &I830;
+
+#define INTEL_BIOS_8(_addr) (pI830->VBIOS[_addr])
+#define INTEL_BIOS_16(_addr) (pI830->VBIOS[_addr] | \
+ (pI830->VBIOS[_addr + 1] << 8))
+#define INTEL_BIOS_32(_addr) (pI830->VBIOS[_addr] | \
+ (pI830->VBIOS[_addr + 1] << 8) \
+ (pI830->VBIOS[_addr + 2] << 16) \
+ (pI830->VBIOS[_addr + 3] << 24))
+
+int main(int argc, char **argv)
+{
+ FILE *f;
+ int bios_size = 65536;
+ struct vbt_header *vbt;
+ struct bdb_header *bdb;
+ int vbt_off, bdb_off, bdb_block_off, block_size;
+ int panel_type = -1, i;
+ char *filename = "bios";
+
+ if (argc == 2)
+ filename = argv[1];
+
+ f = fopen(filename, "r");
+ if (!f) {
+ printf("Couldn't open %s\n", filename);
+ return 1;
+ }
+
+ pI830->VBIOS = calloc(1, bios_size);
+ if (fread(pI830->VBIOS, 1, bios_size, f) != bios_size)
+ return 1;
+
+ vbt_off = INTEL_BIOS_16(0x1a);
+ printf("VBT offset: %08x\n", vbt_off);
+ vbt = (struct vbt_header *)(pI830->VBIOS + vbt_off);
+ printf("VBT sig: %20s\n", vbt->signature);
+ printf("VBT vers: %d.%d\n", vbt->version / 100, vbt->version % 100);
+
+ bdb_off = vbt_off + vbt->bdb_offset;
+ bdb = (struct bdb_header *)(pI830->VBIOS + bdb_off);
+ printf("BDB sig: %16s\n", bdb->signature);
+ printf("BDB vers: %d.%d\n", bdb->version / 100, bdb->version % 100);
+ for (bdb_block_off = bdb->header_size; bdb_block_off < bdb->bdb_size;
+ bdb_block_off += block_size)
+ {
+ int start = bdb_off + bdb_block_off;
+ int id;
+ struct lvds_bdb_1 *lvds1;
+ struct lvds_bdb_2 *lvds2;
+ struct lvds_bdb_2_fp_params *fpparam;
+ struct lvds_bdb_2_fp_edid_dtd *fptiming;
+ CARD8 *timing_ptr;
+
+ id = INTEL_BIOS_8(start);
+ block_size = INTEL_BIOS_16(start + 1) + 3;
+ printf("BDB block type %03d size %d\n", id, block_size);
+ switch (id) {
+ case 40:
+ lvds1 = (struct lvds_bdb_1 *)(pI830->VBIOS + start);
+ panel_type = lvds1->panel_type;
+ printf("Panel type: %d, caps %04x\n", panel_type, lvds1->caps);
+ break;
+ case 41:
+ if (panel_type == -1) {
+ printf("Found panel block with no panel type\n");
+ break;
+ }
+
+ lvds2 = (struct lvds_bdb_2 *)(pI830->VBIOS + start);
+
+ printf("Entries per table: %d\n", lvds2->table_size);
+ for (i = 0; i < 16; i++) {
+ char marker;
+ fpparam = (struct lvds_bdb_2_fp_params *)(pI830->VBIOS +
+ bdb_off + lvds2->panels[i].fp_params_offset);
+ fptiming = (struct lvds_bdb_2_fp_edid_dtd *)(pI830->VBIOS +
+ bdb_off + lvds2->panels[i].fp_edid_dtd_offset);
+ timing_ptr = pI830->VBIOS + bdb_off +
+ lvds2->panels[i].fp_edid_dtd_offset;
+ if (fpparam->terminator != 0xffff) {
+ /* Apparently the offsets are wrong for some BIOSes, so we
+ * try the other offsets if we find a bad terminator.
+ */
+ fpparam = (struct lvds_bdb_2_fp_params *)(pI830->VBIOS +
+ bdb_off + lvds2->panels[i].fp_params_offset + 8);
+ fptiming = (struct lvds_bdb_2_fp_edid_dtd *)(pI830->VBIOS +
+ bdb_off + lvds2->panels[i].fp_edid_dtd_offset + 8);
+ timing_ptr = pI830->VBIOS + bdb_off +
+ lvds2->panels[i].fp_edid_dtd_offset + 8;
+
+ if (fpparam->terminator != 0xffff)
+ continue;
+ }
+ if (i == panel_type)
+ marker = '*';
+ else
+ marker = ' ';
+ printf("%c Panel index %02i xres %d yres %d clock %d\n", marker,
+ i, fpparam->x_res, fpparam->y_res,
+ _PIXEL_CLOCK(timing_ptr));
+ printf(" %d %d %d %d %d %d %d %d\n",
+ _H_ACTIVE(timing_ptr), _H_BLANK(timing_ptr),
+ _H_SYNC_OFF(timing_ptr), _H_SYNC_WIDTH(timing_ptr),
+ _V_ACTIVE(timing_ptr), _V_BLANK(timing_ptr),
+ _V_SYNC_OFF(timing_ptr), _V_SYNC_WIDTH(timing_ptr));
+ }
+
+ printf("Panel of size %dx%d\n", fpparam->x_res, fpparam->y_res);
+ break;
+ }
+ }
+
+ return 0;
+}