few fixes
[grml-scripts.git] / compile / vmware-detect.c
1 #include "string.h"
2 #include "unistd.h"
3 #include "stdio.h"
4 #include "stdlib.h"
5
6 #define WRITE(x) write(1, x, strlen(x))
7 #define DWRITE(x) do{ \
8     if(debug) { \
9         WRITE(x); \
10     } \
11 } while(0);
12 #define FALSE 0
13 #define TRUE !FALSE
14
15 // from libowfat {{{
16 static inline char tohex(char c) {
17   return c>=10?c-10+'a':c+'0';
18 }
19
20 unsigned int fmt_xlong(char *dest,unsigned long i) {
21   register unsigned long len,tmp;
22   /* first count the number of bytes needed */
23   for (len=1, tmp=i; tmp>15; ++len) tmp>>=4;
24   if (dest)
25     for (tmp=i, dest+=len; ; ) {
26       *--dest = tohex(tmp&15);
27       if (!(tmp>>=4)) break;
28     }
29   return len;
30 }
31 // }}}
32
33 void printIdtr(const unsigned char* idtr, unsigned size)
34 {
35     unsigned i;
36     for(i=0; i<=size; ++i) {
37         char out[4] = {0};
38         fmt_xlong(out, idtr[i]);
39         WRITE(out);
40     }
41     WRITE("\n");
42 }
43
44 // i386 {{{
45 #if defined (__i386__)
46 int checkVmware(const int debug)
47 {
48     unsigned char idtr[6] = {0};
49     asm("sidt %0" : "=m" (idtr));
50     if(debug)
51         printIdtr(idtr, 6);
52     return (0xff==idtr[5]) ? 1 : 0;
53 }
54 int checkVmwareIO()
55 {
56     unsigned int vmaj, vmin, magic, dout = 11;
57     __asm__ __volatile__(
58             "mov $0x564D5868, %%eax; /* magic number */"
59             "mov $0x3c6cf712, %%ebx; /* random number */"
60             "mov $0x0000000A, %%ecx; /* specifies command */"
61             "mov $0x5658, %%edx; /* VMware I/O port */"
62             "in %%dx, %%eax;"
63             "mov %%eax, %0;"
64             "mov %%ebx, %1;"
65             "mov %%ecx, %2;"
66             "mov %%edx, %3;"
67         : "=r"(vmaj), "=r"(magic), "=r"(vmin), "=r"(dout));
68 #ifdef DEBUG
69     fprintf(stderr, "version: major=%x, minor=%x, magic=%x, dout=%x\n",
70             vmaj, vmin, magic, dout);
71 #endif
72     return (0x564D5868 == magic) ? 1 : 0;
73 }
74 // }}}
75
76 // x86-64 {{{
77 #elif defined (__x86_64__)
78 // only guessed, possible need to check against 0xffff?
79 int checkVmware(const int debug)
80 {
81     unsigned char idtr[10];
82     asm("sidt %0" : "=m" (idtr));
83     if(debug)
84         printIdtr(idtr, 10);
85     return (0xff==idtr[9]) ? 1 : 0;
86 }
87 int checkVmwareIO() { return 0; }
88 // }}}
89
90 // others {{{
91 #else
92 // vmware runs only on the archs above
93 int checkVmware(const int) { return 0; }
94 int checkVmwareIO() { return 0; }
95 #endif
96 // }}}
97
98 // returns 0 if running inside vmware, 1 otherwise
99 int main(int argc, char* argv[]) {
100     int debug = FALSE;
101     if(argc == 2 && !strcmp(argv[1], "--debug"))
102         debug = TRUE;
103
104     int a, b;
105     // known to be false positives
106     a = checkVmware(debug);
107     DWRITE("idt-check: ")
108     if(!a) {
109         DWRITE("false\n");
110         if(!debug)
111             return EXIT_FAILURE;
112     } else
113         DWRITE("true\n");
114
115     // never returns if not running under vmware
116     void dummy() { DWRITE("false\n"); exit(1); }
117     signal(SIGSEGV, dummy);
118     DWRITE("ioport-check: ");
119     b = checkVmwareIO();
120     if(b) {
121         DWRITE("true\n");
122         return EXIT_SUCCESS;
123     }
124     // never reached
125     WRITE("Error: IO check hasn't killed the program but no vmware found either!\n");
126     return EXIT_FAILURE;
127 }
128 // vim: foldmethod=marker