Annotation of qemu/tests/runcom.c, revision 1.1.1.4

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: }

unix.superglobalmegacorp.com