Release 980913
[wine] / loader / dos / dosmod.c
1 /*
2  * DOS Virtual Machine
3  *
4  * Copyright 1998 Ove Kåven
5  */
6
7 #ifdef linux
8
9 /* apparently ELF images are usually loaded high anyway */
10 #ifndef __ELF__
11 /* if not, force dosmod at high addresses */
12 asm(".org 0x110000");
13 #endif __ELF__
14
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <errno.h>
19 #include <unistd.h>
20 #include <fcntl.h>
21 #include <signal.h>
22 #include <sys/stat.h>
23 #include <sys/mman.h>
24 #include <sys/vm86.h>
25 #include <sys/types.h>
26 #include <sys/ptrace.h>
27 #include <sys/wait.h>
28
29  /* FIXME: hack because libc vm86 may be the old syscall version */
30
31 #define SYS_vm86   166
32
33 static __inline__ int vm86plus( int func, struct vm86plus_struct *ptr )
34 {
35     int res;
36 #ifdef __PIC__
37     __asm__ __volatile__( "pushl %%ebx\n\t"
38                           "movl %2,%%ebx\n\t"
39                           "int $0x80\n\t"
40                           "popl %%ebx"
41                           : "=a" (res)
42                           : "0" (SYS_vm86),
43                             "g" (func),
44                             "c" (ptr) );
45 #else
46     __asm__ __volatile__("int $0x80"
47                          : "=a" (res)
48                          : "0" (SYS_vm86),
49                            "b" (func),
50                            "c" (ptr) );
51 #endif  /* __PIC__ */
52     if (res >= 0) return res;
53     errno = -res;
54     return -1;
55 }
56
57 int main(int argc,char**argv)
58 {
59  int mfd=open(argv[0],O_RDWR);
60  void*img;
61  struct vm86plus_struct VM86;
62  int func,ret;
63  off_t fofs=0;
64  pid_t ppid=getppid();
65  
66 /* fprintf(stderr,"main is at %08lx, file is %s, fd=%d\n",(unsigned long)&main,argv[0],mfd); */
67  if (mfd<0) return 1;
68 /* Map in our DOS image at the start of the process address space */
69  if (argv[1]) {
70   /* Ulrich Weigand suggested mapping in the DOS image directly from the Wine
71      address space */
72   fofs=atol(argv[1]);
73   /* linux currently only allows mapping a process memory if it's being ptraced */
74   /* Linus doesn't like it, so this probably won't work in the future */
75   /* it doesn't even work for me right now */
76   ptrace(PTRACE_ATTACH,ppid,0,0);
77   kill(ppid,SIGSTOP);
78   waitpid(ppid,NULL,0);
79  }
80  img=mmap(NULL,0x110000,PROT_EXEC|PROT_READ|PROT_WRITE,MAP_FIXED|MAP_SHARED,mfd,fofs);
81  if (argv[1]) {
82   ptrace(PTRACE_DETACH,ppid,0,0);
83   kill(ppid,SIGCONT);
84  }
85  if (img==(void*)-1) {
86   fprintf(stderr,"DOS memory map failed, error=%s\n",strerror(errno));
87   fprintf(stderr,"in attempt to map %s, offset %08lX, length 110000, to offset 0\n",argv[0],fofs);
88   return 1;
89  }
90 /* fprintf(stderr,"Successfully mapped DOS memory, entering vm86 loop\n"); */
91 /* report back to the main program that we're ready */
92  ret=0;
93  write(1,&ret,sizeof(ret));
94 /* context exchange loop */
95  do {
96   if (read(0,&func,sizeof(func))!=sizeof(func)) return 1;
97   if (read(0,&VM86,sizeof(VM86))!=sizeof(VM86)) return 1;
98   if (func<0) break;
99   ret=vm86plus(func,&VM86);
100   if (write(1,&ret,sizeof(ret))!=sizeof(ret)) return 1;
101   if (write(1,&VM86,sizeof(VM86))!=sizeof(VM86)) return 1;
102  } while (1);
103  return 0;
104 }
105
106 #else /* !linux */
107 int main(void) {return 1;}
108 #endif