summaryrefslogtreecommitdiff
path: root/vbtracetool.c
diff options
context:
space:
mode:
authorStuart Bennett <sb476@cam.ac.uk>2007-11-16 00:13:50 +0000
committerStuart Bennett <sb476@cam.ac.uk>2007-11-16 01:45:58 +0000
commit5154c73df7017a6a04a497b00c29c7edb5d12c96 (patch)
treec13108b3f32de9a8f6f34ce39eba2679356e6a48 /vbtracetool.c
parent0cbb7dd01ad08b150e7cd0d4e7dfadd0c7375598 (diff)
inttool is dead, long live vbtracetool
Diffstat (limited to 'vbtracetool.c')
-rw-r--r--vbtracetool.c156
1 files changed, 156 insertions, 0 deletions
diff --git a/vbtracetool.c b/vbtracetool.c
new file mode 100644
index 0000000..94d9248
--- /dev/null
+++ b/vbtracetool.c
@@ -0,0 +1,156 @@
+/*
+ * vbtracetool, an execution tracing tool for video biosen
+ *
+ * Copyright 2007 Stuart Bennett <sb476@cam.ac.uk>
+ *
+ * Based on vbetool.c, Copyright Matthew Garrett <mjg59@srcf.ucam.org>
+ *
+ * This program is released under the terms of the GNU General Public License,
+ * version 2
+ */
+
+#include <pci/pci.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/io.h>
+
+#include "lrmi.h"
+#include "x86emu.h"
+
+int do_set_mode(unsigned mode)
+{
+ struct LRMI_regs r;
+ memset(&r, 0, sizeof(r));
+
+ r.eax = 0x4f02;
+ r.ebx = (mode & 0xffff) | 0x8000;
+ r.ecx = 0;
+ r.edx = 0;
+
+ if (!LRMI_int(0x10, &r)) {
+ fprintf(stderr, "Error: something went wrong performing real mode call\n");
+ return 1;
+ }
+ printf("ax: 0x%04x, bx: 0x%04x\n", r.eax & 0xffff, r.ebx & 0xffff);
+
+ return 0;
+}
+
+int do_get_mode(void)
+{
+ struct LRMI_regs r;
+ memset(&r, 0, sizeof(r));
+
+ r.eax = 0x4f03;
+ r.ebx = 0;
+ r.ecx = 0;
+ r.edx = 0;
+
+ if (!LRMI_int(0x10, &r)) {
+ fprintf(stderr, "Error: something went wrong performing real mode call\n");
+ return 1;
+ }
+ printf("ax: 0x%04x, bx: 0x%04x, mode: 0x%04x (%d)\n", r.eax & 0xffff, r.ebx & 0xffff, r.ebx & 0x3fff, r.ebx & 0x3fff);
+
+ return 0;
+}
+
+int do_post_int(unsigned pci_device)
+{
+ struct LRMI_regs r;
+ memset(&r, 0, sizeof(r));
+
+ /* Several machines seem to want the device that they're POSTing in
+ here */
+ r.eax = pci_device;
+
+ /* 0xc000 is the video option ROM. The init code for each
+ option ROM is at 0x0003 - so jump to c000:0003 and start running */
+ r.cs = 0xc000;
+ r.ip = 0x0003;
+
+ /* This is all heavily cargo culted but seems to work */
+ r.edx = 0x80;
+ r.ds = 0x0040;
+
+ if (!LRMI_call(&r)) {
+ fprintf(stderr, "Error: something went wrong performing real mode call\n");
+ return 1;
+ }
+
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ static struct pci_access *pacc;
+ struct pci_dev *p;
+ unsigned int c;
+ unsigned int pci_id;
+ int opt, debug = 0, mode, op = 0, opset = 0;
+
+ while ((opt = getopt(argc, argv, "dgps:")) != -1) {
+ switch (opt) {
+ case 'd':
+ debug = 1;
+ break;
+ case 'g':
+ opset++;
+ break;
+ case 'p':
+ op = 2;
+ opset++;
+ break;
+ case 's':
+ op = 1;
+ opset++;
+ mode = atoi(optarg);
+ break;
+ default:
+ opset = 2;
+ }
+ }
+
+ if (optind < argc || opset > 1) {
+ printf("eh?\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if (!LRMI_init()) {
+ fprintf(stderr, "Failed to initialise LRMI (Linux Real-Mode Interface).\n");
+ exit(EXIT_FAILURE);
+ }
+
+ ioperm(0, 1024, 1);
+ iopl(3);
+
+ if (debug)
+ M.x86.debug = DEBUG_TRACE_F | DEBUG_DECODE_F; /* x86emu debug flags */
+ else
+ M.x86.debug = 0;
+
+ switch (op) {
+ case 0:
+ return (do_get_mode());
+ case 1:
+ return (do_set_mode(mode));
+ case 2:
+ pacc = pci_alloc();
+ pacc->numeric_ids = 1;
+ pci_init(pacc);
+
+ pci_scan_bus(pacc);
+
+ for (p = pacc->devices; p; p = p->next) {
+ c = pci_read_word(p, PCI_CLASS_DEVICE);
+ if (c == 0x300) {
+ pci_id = (p->bus << 8) + (p->dev << 3) + (p->func & 0x7);
+ return (do_post_int(pci_id));
+ }
+ }
+ }
+
+ return 0;
+}