|
|
1.1 root 1: /*
2: * Simple example of use of vm86: launch a basic .com DOS executable
3: */
4: #include <stdlib.h>
5: #include <stdio.h>
6: #include <string.h>
7: #include <inttypes.h>
8: #include <unistd.h>
9: #include <fcntl.h>
10: #include <sys/mman.h>
11: #include <signal.h>
12:
13: #include <linux/unistd.h>
14: #include <asm/vm86.h>
15:
1.1.1.4 ! root 16: extern int vm86 (unsigned long int subfunction,
! 17: struct vm86plus_struct *info);
1.1 root 18:
1.1.1.4 ! root 19: #define VIF_MASK 0x00080000
1.1 root 20:
1.1.1.4 ! root 21: //#define SIGTEST
1.1 root 22:
23: #define COM_BASE_ADDR 0x10100
24:
1.1.1.3 root 25: static void usage(void)
1.1 root 26: {
27: printf("runcom version 0.1 (c) 2003 Fabrice Bellard\n"
28: "usage: runcom file.com\n"
29: "VM86 Run simple .com DOS executables (linux vm86 test mode)\n");
30: exit(1);
31: }
32:
33: static inline void set_bit(uint8_t *a, unsigned int bit)
34: {
35: a[bit / 8] |= (1 << (bit % 8));
36: }
37:
38: static inline uint8_t *seg_to_linear(unsigned int seg, unsigned int reg)
39: {
40: return (uint8_t *)((seg << 4) + (reg & 0xffff));
41: }
42:
43: static inline void pushw(struct vm86_regs *r, int val)
44: {
45: r->esp = (r->esp & ~0xffff) | ((r->esp - 2) & 0xffff);
46: *(uint16_t *)seg_to_linear(r->ss, r->esp) = val;
47: }
48:
49: void dump_regs(struct vm86_regs *r)
50: {
1.1.1.2 root 51: fprintf(stderr,
1.1 root 52: "EAX=%08lx EBX=%08lx ECX=%08lx EDX=%08lx\n"
53: "ESI=%08lx EDI=%08lx EBP=%08lx ESP=%08lx\n"
54: "EIP=%08lx EFL=%08lx\n"
55: "CS=%04x DS=%04x ES=%04x SS=%04x FS=%04x GS=%04x\n",
56: r->eax, r->ebx, r->ecx, r->edx, r->esi, r->edi, r->ebp, r->esp,
57: r->eip, r->eflags,
58: r->cs, r->ds, r->es, r->ss, r->fs, r->gs);
59: }
60:
61: #ifdef SIGTEST
62: void alarm_handler(int sig)
63: {
64: fprintf(stderr, "alarm signal=%d\n", sig);
65: alarm(1);
66: }
67: #endif
68:
69: int main(int argc, char **argv)
70: {
71: uint8_t *vm86_mem;
72: const char *filename;
73: int fd, ret, seg;
74: struct vm86plus_struct ctx;
75: struct vm86_regs *r;
76:
77: if (argc != 2)
78: usage();
79: filename = argv[1];
1.1.1.2 root 80:
81: vm86_mem = mmap((void *)0x00000000, 0x110000,
82: PROT_WRITE | PROT_READ | PROT_EXEC,
1.1 root 83: MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0);
84: if (vm86_mem == MAP_FAILED) {
85: perror("mmap");
86: exit(1);
87: }
88: #ifdef SIGTEST
89: {
90: struct sigaction act;
91:
92: act.sa_handler = alarm_handler;
93: sigemptyset(&act.sa_mask);
94: act.sa_flags = 0;
95: sigaction(SIGALRM, &act, NULL);
96: alarm(1);
97: }
98: #endif
99:
100: /* load the MSDOS .com executable */
101: fd = open(filename, O_RDONLY);
102: if (fd < 0) {
103: perror(filename);
104: exit(1);
105: }
106: ret = read(fd, vm86_mem + COM_BASE_ADDR, 65536 - 256);
107: if (ret < 0) {
108: perror("read");
109: exit(1);
110: }
111: close(fd);
112:
113: memset(&ctx, 0, sizeof(ctx));
114: /* init basic registers */
115: r = &ctx.regs;
116: r->eip = 0x100;
117: r->esp = 0xfffe;
118: seg = (COM_BASE_ADDR - 0x100) >> 4;
119: r->cs = seg;
120: r->ss = seg;
121: r->ds = seg;
122: r->es = seg;
123: r->fs = seg;
124: r->gs = seg;
125: r->eflags = VIF_MASK;
126:
127: /* put return code */
128: set_bit((uint8_t *)&ctx.int_revectored, 0x21);
129: *seg_to_linear(r->cs, 0) = 0xb4; /* mov ah, $0 */
130: *seg_to_linear(r->cs, 1) = 0x00;
131: *seg_to_linear(r->cs, 2) = 0xcd; /* int $0x21 */
132: *seg_to_linear(r->cs, 3) = 0x21;
133: pushw(&ctx.regs, 0x0000);
134:
135: /* the value of these registers seem to be assumed by pi_10.com */
136: r->esi = 0x100;
137: r->ecx = 0xff;
138: r->ebp = 0x0900;
139: r->edi = 0xfffe;
140:
141: for(;;) {
142: ret = vm86(VM86_ENTER, &ctx);
143: switch(VM86_TYPE(ret)) {
144: case VM86_INTx:
145: {
146: int int_num, ah;
1.1.1.2 root 147:
1.1 root 148: int_num = VM86_ARG(ret);
149: if (int_num != 0x21)
150: goto unknown_int;
151: ah = (r->eax >> 8) & 0xff;
152: switch(ah) {
153: case 0x00: /* exit */
154: exit(0);
155: case 0x02: /* write char */
156: {
157: uint8_t c = r->edx;
158: write(1, &c, 1);
159: }
160: break;
161: case 0x09: /* write string */
162: {
163: uint8_t c;
164: for(;;) {
165: c = *seg_to_linear(r->ds, r->edx);
166: if (c == '$')
167: break;
168: write(1, &c, 1);
169: }
170: r->eax = (r->eax & ~0xff) | '$';
171: }
172: break;
173: default:
174: unknown_int:
175: fprintf(stderr, "unsupported int 0x%02x\n", int_num);
176: dump_regs(&ctx.regs);
177: // exit(1);
178: }
179: }
180: break;
181: case VM86_SIGNAL:
182: /* a signal came, we just ignore that */
183: break;
184: case VM86_STI:
185: break;
186: default:
187: fprintf(stderr, "unhandled vm86 return code (0x%x)\n", ret);
188: dump_regs(&ctx.regs);
189: exit(1);
190: }
191: }
192: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.