~ubuntu-branches/ubuntu/lucid/read-edid/lucid

« back to all changes in this revision

Viewing changes to lrmi.c

  • Committer: Bazaar Package Importer
  • Author(s): LIU Qi
  • Date: 2009-05-11 13:14:40 UTC
  • mfrom: (3.1.2 squeeze)
  • Revision ID: james.westby@ubuntu.com-20090511131440-1l046wvoparqqukn
Tags: 2.0.0-1
* new upstream version and maintainer (Closes: #502125)
  - the new version uses libx86 instead of LRMI (Closes: #495131)
  - libx86 will build on new kernel (Closes: #502126)
* add missing binary-indep in debian/rules (Closes: #395741)
* new version is modified to build on any architecture 
  - fixed the powerpc build problem (Closes: #406736)
  - fixed the rebuild problem (Closes: #433713)
* install the read-edid in usr/sbin directory (Closes: #231307)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
Linux Real Mode Interface - A library of DPMI-like functions for Linux.
3
 
 
4
 
Copyright (C) 1998 by Josh Vanderhoof
5
 
 
6
 
You are free to distribute and modify this file, as long as you
7
 
do not remove this copyright notice and clearly label modified
8
 
versions as being modified.
9
 
 
10
 
This software has NO WARRANTY.  Use it at your own risk.
11
 
*/
12
 
 
13
 
#include <stdio.h>
14
 
#include <string.h>
15
 
#include <asm/vm86.h>
16
 
 
17
 
#ifdef USE_LIBC_VM86
18
 
#include <sys/vm86.h>
19
 
#endif
20
 
 
21
 
#if defined(__linux__)
22
 
#ifndef TF_MASK
23
 
#define TF_MASK X86_EFLAGS_TF
24
 
#endif
25
 
#ifndef IF_MASK
26
 
#define IF_MASK X86_EFLAGS_IF
27
 
#endif
28
 
#ifndef IOPL_MASK
29
 
#define IOPL_MASK X86_EFLAGS_IOPL
30
 
#endif
31
 
#ifndef VIF_MASK
32
 
#define VIF_MASK X86_EFLAGS_VIF
33
 
#endif
34
 
#endif
35
 
 
36
 
#include <sys/types.h>
37
 
#include <sys/stat.h>
38
 
#include <sys/mman.h>
39
 
#include <unistd.h>
40
 
#include <fcntl.h>
41
 
 
42
 
#include "lrmi.h"
43
 
 
44
 
#define REAL_MEM_BASE   ((void *)0x10000)
45
 
#define REAL_MEM_SIZE   0x10000
46
 
#define REAL_MEM_BLOCKS         0x100
47
 
 
48
 
struct mem_block
49
 
        {
50
 
        unsigned int size : 20;
51
 
        unsigned int free : 1;
52
 
        };
53
 
 
54
 
static struct
55
 
        {
56
 
        int ready;
57
 
        int count;
58
 
        struct mem_block blocks[REAL_MEM_BLOCKS];
59
 
        } mem_info = { 0 };
60
 
 
61
 
static int
62
 
real_mem_init(void)
63
 
        {
64
 
        void *m;
65
 
        int fd_zero;
66
 
 
67
 
        if (mem_info.ready)
68
 
                return 1;
69
 
 
70
 
        fd_zero = open("/dev/zero", O_RDONLY);
71
 
        if (fd_zero == -1)
72
 
                {
73
 
                perror("open /dev/zero");
74
 
                return 0;
75
 
                }
76
 
 
77
 
        m = mmap((void *)REAL_MEM_BASE, REAL_MEM_SIZE,
78
 
         PROT_READ | PROT_WRITE | PROT_EXEC,
79
 
         MAP_FIXED | MAP_PRIVATE, fd_zero, 0);
80
 
 
81
 
        if (m == (void *)-1)
82
 
                {
83
 
                perror("mmap /dev/zero");
84
 
                close(fd_zero);
85
 
                return 0;
86
 
                }
87
 
 
88
 
        mem_info.ready = 1;
89
 
        mem_info.count = 1;
90
 
        mem_info.blocks[0].size = REAL_MEM_SIZE;
91
 
        mem_info.blocks[0].free = 1;
92
 
 
93
 
        return 1;
94
 
        }
95
 
 
96
 
 
97
 
static void
98
 
insert_block(int i)
99
 
        {
100
 
        memmove(
101
 
         mem_info.blocks + i + 1,
102
 
         mem_info.blocks + i,
103
 
         (mem_info.count - i) * sizeof(struct mem_block));
104
 
 
105
 
        mem_info.count++;
106
 
        }
107
 
 
108
 
static void
109
 
delete_block(int i)
110
 
        {
111
 
        mem_info.count--;
112
 
 
113
 
        memmove(
114
 
         mem_info.blocks + i,
115
 
         mem_info.blocks + i + 1,
116
 
         (mem_info.count - i) * sizeof(struct mem_block));
117
 
        }
118
 
 
119
 
void *
120
 
LRMI_alloc_real(int size)
121
 
        {
122
 
        int i;
123
 
        char *r = (char *)REAL_MEM_BASE;
124
 
 
125
 
        if (!mem_info.ready)
126
 
                return NULL;
127
 
 
128
 
        if (mem_info.count == REAL_MEM_BLOCKS)
129
 
                return NULL;
130
 
 
131
 
        size = (size + 15) & ~15;
132
 
 
133
 
        for (i = 0; i < mem_info.count; i++)
134
 
                {
135
 
                if (mem_info.blocks[i].free && size < mem_info.blocks[i].size)
136
 
                        {
137
 
                        insert_block(i);
138
 
 
139
 
                        mem_info.blocks[i].size = size;
140
 
                        mem_info.blocks[i].free = 0;
141
 
                        mem_info.blocks[i + 1].size -= size;
142
 
 
143
 
                        return (void *)r;
144
 
                        }
145
 
 
146
 
                r += mem_info.blocks[i].size;
147
 
                }
148
 
 
149
 
        return NULL;
150
 
        }
151
 
 
152
 
 
153
 
void
154
 
LRMI_free_real(void *m)
155
 
        {
156
 
        int i;
157
 
        char *r = (char *)REAL_MEM_BASE;
158
 
 
159
 
        if (!mem_info.ready)
160
 
                return;
161
 
 
162
 
        i = 0;
163
 
        while (m != (void *)r)
164
 
                {
165
 
                r += mem_info.blocks[i].size;
166
 
                i++;
167
 
                if (i == mem_info.count)
168
 
                        return;
169
 
                }
170
 
 
171
 
        mem_info.blocks[i].free = 1;
172
 
 
173
 
        if (i + 1 < mem_info.count && mem_info.blocks[i + 1].free)
174
 
                {
175
 
                mem_info.blocks[i].size += mem_info.blocks[i + 1].size;
176
 
                delete_block(i + 1);
177
 
                }
178
 
 
179
 
        if (i - 1 >= 0 && mem_info.blocks[i - 1].free)
180
 
                {
181
 
                mem_info.blocks[i - 1].size += mem_info.blocks[i].size;
182
 
                delete_block(i);
183
 
                }
184
 
        }
185
 
 
186
 
 
187
 
#define DEFAULT_VM86_FLAGS      (IF_MASK | IOPL_MASK)
188
 
#define DEFAULT_STACK_SIZE      0x1000
189
 
#define RETURN_TO_32_INT        255
190
 
 
191
 
static struct
192
 
        {
193
 
        int ready;
194
 
        unsigned short ret_seg, ret_off;
195
 
        unsigned short stack_seg, stack_off;
196
 
        struct vm86_struct vm;
197
 
        } context = { 0 };
198
 
 
199
 
 
200
 
static inline void
201
 
set_bit(unsigned int bit, void *array)
202
 
        {
203
 
        unsigned char *a = array;
204
 
 
205
 
        a[bit / 8] |= (1 << (bit % 8));
206
 
        }
207
 
 
208
 
 
209
 
static inline unsigned int
210
 
get_int_seg(int i)
211
 
        {
212
 
        return *(unsigned short *)(i * 4 + 2);
213
 
        }
214
 
 
215
 
 
216
 
static inline unsigned int
217
 
get_int_off(int i)
218
 
        {
219
 
        return *(unsigned short *)(i * 4);
220
 
        }
221
 
 
222
 
 
223
 
static inline void
224
 
pushw(unsigned short i)
225
 
        {
226
 
        struct vm86_regs *r = &context.vm.regs;
227
 
        r->esp -= 2;
228
 
        *(unsigned short *)(((unsigned int)r->ss << 4) + r->esp) = i;
229
 
        }
230
 
 
231
 
 
232
 
int
233
 
LRMI_init(void)
234
 
        {
235
 
        void *m;
236
 
        int fd_mem;
237
 
 
238
 
        if (context.ready)
239
 
                return 1;
240
 
 
241
 
        if (!real_mem_init())
242
 
                return 0;
243
 
 
244
 
        /*
245
 
         Map the Interrupt Vectors (0x0 - 0x400) + BIOS data (0x400 - 0x502)
246
 
         and the ROM (0xa0000 - 0x100000)
247
 
        */
248
 
        fd_mem = open("/dev/mem", O_RDWR);
249
 
 
250
 
        if (fd_mem == -1)
251
 
                {
252
 
                perror("open /dev/mem");
253
 
                return 0;
254
 
                }
255
 
 
256
 
        m = mmap((void *)0, 0x502,
257
 
         PROT_READ | PROT_WRITE | PROT_EXEC,
258
 
         MAP_FIXED | MAP_PRIVATE, fd_mem, 0);
259
 
 
260
 
        if (m == (void *)-1)
261
 
                {
262
 
                perror("mmap /dev/mem");
263
 
                return 0;
264
 
                }
265
 
 
266
 
        m = mmap((void *)0xa0000, 0x100000 - 0xa0000,
267
 
         PROT_READ | PROT_WRITE,
268
 
         MAP_FIXED | MAP_SHARED, fd_mem, 0xa0000);
269
 
 
270
 
        if (m == (void *)-1)
271
 
                {
272
 
                perror("mmap /dev/mem");
273
 
                return 0;
274
 
                }
275
 
 
276
 
 
277
 
        /*
278
 
         Allocate a stack
279
 
        */
280
 
        m = LRMI_alloc_real(DEFAULT_STACK_SIZE);
281
 
 
282
 
        context.stack_seg = (unsigned int)m >> 4;
283
 
        context.stack_off = DEFAULT_STACK_SIZE;
284
 
 
285
 
        /*
286
 
         Allocate the return to 32 bit routine
287
 
        */
288
 
        m = LRMI_alloc_real(2);
289
 
 
290
 
        context.ret_seg = (unsigned int)m >> 4;
291
 
        context.ret_off = (unsigned int)m & 0xf;
292
 
 
293
 
        ((unsigned char *)m)[0] = 0xcd;         /* int opcode */
294
 
        ((unsigned char *)m)[1] = RETURN_TO_32_INT;
295
 
 
296
 
        memset(&context.vm, 0, sizeof(context.vm));
297
 
 
298
 
        /*
299
 
         Enable kernel emulation of all ints except RETURN_TO_32_INT
300
 
        */
301
 
        memset(&context.vm.int_revectored, 0, sizeof(context.vm.int_revectored));
302
 
        set_bit(RETURN_TO_32_INT, &context.vm.int_revectored);
303
 
 
304
 
        context.ready = 1;
305
 
 
306
 
        return 1;
307
 
        }
308
 
 
309
 
 
310
 
static void
311
 
set_regs(struct LRMI_regs *r)
312
 
        {
313
 
        context.vm.regs.edi = r->edi;
314
 
        context.vm.regs.esi = r->esi;
315
 
        context.vm.regs.ebp = r->ebp;
316
 
        context.vm.regs.ebx = r->ebx;
317
 
        context.vm.regs.edx = r->edx;
318
 
        context.vm.regs.ecx = r->ecx;
319
 
        context.vm.regs.eax = r->eax;
320
 
        context.vm.regs.eflags = DEFAULT_VM86_FLAGS;
321
 
        context.vm.regs.es = r->es;
322
 
        context.vm.regs.ds = r->ds;
323
 
        context.vm.regs.fs = r->fs;
324
 
        context.vm.regs.gs = r->gs;
325
 
        }
326
 
 
327
 
 
328
 
static void
329
 
get_regs(struct LRMI_regs *r)
330
 
        {
331
 
        r->edi = context.vm.regs.edi;
332
 
        r->esi = context.vm.regs.esi;
333
 
        r->ebp = context.vm.regs.ebp;
334
 
        r->ebx = context.vm.regs.ebx;
335
 
        r->edx = context.vm.regs.edx;
336
 
        r->ecx = context.vm.regs.ecx;
337
 
        r->eax = context.vm.regs.eax;
338
 
        r->flags = context.vm.regs.eflags;
339
 
        r->es = context.vm.regs.es;
340
 
        r->ds = context.vm.regs.ds;
341
 
        r->fs = context.vm.regs.fs;
342
 
        r->gs = context.vm.regs.gs;
343
 
        }
344
 
 
345
 
#define DIRECTION_FLAG  (1 << 10)
346
 
 
347
 
static void
348
 
em_ins(int size)
349
 
        {
350
 
        unsigned int edx, edi;
351
 
 
352
 
        edx = context.vm.regs.edx & 0xffff;
353
 
        edi = context.vm.regs.edi & 0xffff;
354
 
        edi += (unsigned int)context.vm.regs.ds << 4;
355
 
 
356
 
        if (context.vm.regs.eflags & DIRECTION_FLAG)
357
 
                {
358
 
                if (size == 4)
359
 
                        asm volatile ("std; insl; cld"
360
 
                         : "=D" (edi) : "d" (edx), "0" (edi));
361
 
                else if (size == 2)
362
 
                        asm volatile ("std; insw; cld"
363
 
                         : "=D" (edi) : "d" (edx), "0" (edi));
364
 
                else
365
 
                        asm volatile ("std; insb; cld"
366
 
                         : "=D" (edi) : "d" (edx), "0" (edi));
367
 
                }
368
 
        else
369
 
                {
370
 
                if (size == 4)
371
 
                        asm volatile ("cld; insl"
372
 
                         : "=D" (edi) : "d" (edx), "0" (edi));
373
 
                else if (size == 2)
374
 
                        asm volatile ("cld; insw"
375
 
                         : "=D" (edi) : "d" (edx), "0" (edi));
376
 
                else
377
 
                        asm volatile ("cld; insb"
378
 
                         : "=D" (edi) : "d" (edx), "0" (edi));
379
 
                }
380
 
 
381
 
        edi -= (unsigned int)context.vm.regs.ds << 4;
382
 
 
383
 
        context.vm.regs.edi &= 0xffff0000;
384
 
        context.vm.regs.edi |= edi & 0xffff;
385
 
        }
386
 
 
387
 
static void
388
 
em_rep_ins(int size)
389
 
        {
390
 
        unsigned int ecx, edx, edi;
391
 
 
392
 
        ecx = context.vm.regs.ecx & 0xffff;
393
 
        edx = context.vm.regs.edx & 0xffff;
394
 
        edi = context.vm.regs.edi & 0xffff;
395
 
        edi += (unsigned int)context.vm.regs.ds << 4;
396
 
 
397
 
        if (context.vm.regs.eflags & DIRECTION_FLAG)
398
 
                {
399
 
                if (size == 4)
400
 
                        asm volatile ("std; rep; insl; cld"
401
 
                         : "=D" (edi), "=c" (ecx)
402
 
                         : "d" (edx), "0" (edi), "1" (ecx));
403
 
                else if (size == 2)
404
 
                        asm volatile ("std; rep; insw; cld"
405
 
                         : "=D" (edi), "=c" (ecx)
406
 
                         : "d" (edx), "0" (edi), "1" (ecx));
407
 
                else
408
 
                        asm volatile ("std; rep; insb; cld"
409
 
                         : "=D" (edi), "=c" (ecx)
410
 
                         : "d" (edx), "0" (edi), "1" (ecx));
411
 
                }
412
 
        else
413
 
                {
414
 
                if (size == 4)
415
 
                        asm volatile ("cld; rep; insl"
416
 
                         : "=D" (edi), "=c" (ecx)
417
 
                         : "d" (edx), "0" (edi), "1" (ecx));
418
 
                else if (size == 2)
419
 
                        asm volatile ("cld; rep; insw"
420
 
                         : "=D" (edi), "=c" (ecx)
421
 
                         : "d" (edx), "0" (edi), "1" (ecx));
422
 
                else
423
 
                        asm volatile ("cld; rep; insb"
424
 
                         : "=D" (edi), "=c" (ecx)
425
 
                         : "d" (edx), "0" (edi), "1" (ecx));
426
 
                }
427
 
 
428
 
        edi -= (unsigned int)context.vm.regs.ds << 4;
429
 
 
430
 
        context.vm.regs.edi &= 0xffff0000;
431
 
        context.vm.regs.edi |= edi & 0xffff;
432
 
 
433
 
        context.vm.regs.ecx &= 0xffff0000;
434
 
        context.vm.regs.ecx |= ecx & 0xffff;
435
 
        }
436
 
 
437
 
static void
438
 
em_outs(int size)
439
 
        {
440
 
        unsigned int edx, esi;
441
 
 
442
 
        edx = context.vm.regs.edx & 0xffff;
443
 
        esi = context.vm.regs.esi & 0xffff;
444
 
        esi += (unsigned int)context.vm.regs.ds << 4;
445
 
 
446
 
        if (context.vm.regs.eflags & DIRECTION_FLAG)
447
 
                {
448
 
                if (size == 4)
449
 
                        asm volatile ("std; outsl; cld"
450
 
                         : "=S" (esi) : "d" (edx), "0" (esi));
451
 
                else if (size == 2)
452
 
                        asm volatile ("std; outsw; cld"
453
 
                         : "=S" (esi) : "d" (edx), "0" (esi));
454
 
                else
455
 
                        asm volatile ("std; outsb; cld"
456
 
                         : "=S" (esi) : "d" (edx), "0" (esi));
457
 
                }
458
 
        else
459
 
                {
460
 
                if (size == 4)
461
 
                        asm volatile ("cld; outsl"
462
 
                         : "=S" (esi) : "d" (edx), "0" (esi));
463
 
                else if (size == 2)
464
 
                        asm volatile ("cld; outsw"
465
 
                         : "=S" (esi) : "d" (edx), "0" (esi));
466
 
                else
467
 
                        asm volatile ("cld; outsb"
468
 
                         : "=S" (esi) : "d" (edx), "0" (esi));
469
 
                }
470
 
 
471
 
        esi -= (unsigned int)context.vm.regs.ds << 4;
472
 
 
473
 
        context.vm.regs.esi &= 0xffff0000;
474
 
        context.vm.regs.esi |= esi & 0xffff;
475
 
        }
476
 
 
477
 
static void
478
 
em_rep_outs(int size)
479
 
        {
480
 
        unsigned int ecx, edx, esi;
481
 
 
482
 
        ecx = context.vm.regs.ecx & 0xffff;
483
 
        edx = context.vm.regs.edx & 0xffff;
484
 
        esi = context.vm.regs.esi & 0xffff;
485
 
        esi += (unsigned int)context.vm.regs.ds << 4;
486
 
 
487
 
        if (context.vm.regs.eflags & DIRECTION_FLAG)
488
 
                {
489
 
                if (size == 4)
490
 
                        asm volatile ("std; rep; outsl; cld"
491
 
                         : "=S" (esi), "=c" (ecx)
492
 
                         : "d" (edx), "0" (esi), "1" (ecx));
493
 
                else if (size == 2)
494
 
                        asm volatile ("std; rep; outsw; cld"
495
 
                         : "=S" (esi), "=c" (ecx)
496
 
                         : "d" (edx), "0" (esi), "1" (ecx));
497
 
                else
498
 
                        asm volatile ("std; rep; outsb; cld"
499
 
                         : "=S" (esi), "=c" (ecx)
500
 
                         : "d" (edx), "0" (esi), "1" (ecx));
501
 
                }
502
 
        else
503
 
                {
504
 
                if (size == 4)
505
 
                        asm volatile ("cld; rep; outsl"
506
 
                         : "=S" (esi), "=c" (ecx)
507
 
                         : "d" (edx), "0" (esi), "1" (ecx));
508
 
                else if (size == 2)
509
 
                        asm volatile ("cld; rep; outsw"
510
 
                         : "=S" (esi), "=c" (ecx)
511
 
                         : "d" (edx), "0" (esi), "1" (ecx));
512
 
                else
513
 
                        asm volatile ("cld; rep; outsb"
514
 
                         : "=S" (esi), "=c" (ecx)
515
 
                         : "d" (edx), "0" (esi), "1" (ecx));
516
 
                }
517
 
 
518
 
        esi -= (unsigned int)context.vm.regs.ds << 4;
519
 
 
520
 
        context.vm.regs.esi &= 0xffff0000;
521
 
        context.vm.regs.esi |= esi & 0xffff;
522
 
 
523
 
        context.vm.regs.ecx &= 0xffff0000;
524
 
        context.vm.regs.ecx |= ecx & 0xffff;
525
 
        }
526
 
 
527
 
static void
528
 
em_inb(void)
529
 
        {
530
 
        asm volatile ("inb (%w1), %b0"
531
 
         : "=a" (context.vm.regs.eax)
532
 
         : "d" (context.vm.regs.edx), "0" (context.vm.regs.eax));
533
 
        }
534
 
 
535
 
static void
536
 
em_inw(void)
537
 
        {
538
 
        asm volatile ("inw (%w1), %w0"
539
 
         : "=a" (context.vm.regs.eax)
540
 
         : "d" (context.vm.regs.edx), "0" (context.vm.regs.eax));
541
 
        }
542
 
 
543
 
static void
544
 
em_inl(void)
545
 
        {
546
 
        asm volatile ("inl (%w1), %0"
547
 
         : "=a" (context.vm.regs.eax)
548
 
         : "d" (context.vm.regs.edx));
549
 
        }
550
 
 
551
 
static void
552
 
em_outb(void)
553
 
        {
554
 
        asm volatile ("outb %b0, (%w1)"
555
 
         : : "a" (context.vm.regs.eax),
556
 
         "d" (context.vm.regs.edx));
557
 
        }
558
 
 
559
 
static void
560
 
em_outw(void)
561
 
        {
562
 
        asm volatile ("outw %w0, (%w1)"
563
 
         : : "a" (context.vm.regs.eax),
564
 
         "d" (context.vm.regs.edx));
565
 
        }
566
 
 
567
 
static void
568
 
em_outl(void)
569
 
        {
570
 
        asm volatile ("outl %0, (%w1)"
571
 
         : : "a" (context.vm.regs.eax),
572
 
         "d" (context.vm.regs.edx));
573
 
        }
574
 
 
575
 
static int
576
 
emulate(void)
577
 
        {
578
 
        unsigned char *insn;
579
 
        struct
580
 
                {
581
 
                unsigned int size : 1;
582
 
                unsigned int rep : 1;
583
 
                } prefix = { 0, 0 };
584
 
        int i = 0;
585
 
 
586
 
        insn = (unsigned char *)((unsigned int)context.vm.regs.cs << 4);
587
 
        insn += context.vm.regs.eip;
588
 
 
589
 
        while (1)
590
 
                {
591
 
                if (insn[i] == 0x66)
592
 
                        {
593
 
                        prefix.size = 1 - prefix.size;
594
 
                        i++;
595
 
                        }
596
 
                else if (insn[i] == 0xf3)
597
 
                        {
598
 
                        prefix.rep = 1;
599
 
                        i++;
600
 
                        }
601
 
                else if (insn[i] == 0xf0 || insn[i] == 0xf2
602
 
                 || insn[i] == 0x26 || insn[i] == 0x2e
603
 
                 || insn[i] == 0x36 || insn[i] == 0x3e
604
 
                 || insn[i] == 0x64 || insn[i] == 0x65
605
 
                 || insn[i] == 0x67)
606
 
                        {
607
 
                        /* these prefixes are just ignored */
608
 
                        i++;
609
 
                        }
610
 
                else if (insn[i] == 0x6c)
611
 
                        {
612
 
                        if (prefix.rep)
613
 
                                em_rep_ins(1);
614
 
                        else
615
 
                                em_ins(1);
616
 
                        i++;
617
 
                        break;
618
 
                        }
619
 
                else if (insn[i] == 0x6d)
620
 
                        {
621
 
                        if (prefix.rep)
622
 
                                {
623
 
                                if (prefix.size)
624
 
                                        em_rep_ins(4);
625
 
                                else
626
 
                                        em_rep_ins(2);
627
 
                                }
628
 
                        else
629
 
                                {
630
 
                                if (prefix.size)
631
 
                                        em_ins(4);
632
 
                                else
633
 
                                        em_ins(2);
634
 
                                }
635
 
                        i++;
636
 
                        break;
637
 
                        }
638
 
                else if (insn[i] == 0x6e)
639
 
                        {
640
 
                        if (prefix.rep)
641
 
                                em_rep_outs(1);
642
 
                        else
643
 
                                em_outs(1);
644
 
                        i++;
645
 
                        break;
646
 
                        }
647
 
                else if (insn[i] == 0x6f)
648
 
                        {
649
 
                        if (prefix.rep)
650
 
                                {
651
 
                                if (prefix.size)
652
 
                                        em_rep_outs(4);
653
 
                                else
654
 
                                        em_rep_outs(2);
655
 
                                }
656
 
                        else
657
 
                                {
658
 
                                if (prefix.size)
659
 
                                        em_outs(4);
660
 
                                else
661
 
                                        em_outs(2);
662
 
                                }
663
 
                        i++;
664
 
                        break;
665
 
                        }
666
 
                else if (insn[i] == 0xec)
667
 
                        {
668
 
                        em_inb();
669
 
                        i++;
670
 
                        break;
671
 
                        }
672
 
                else if (insn[i] == 0xed)
673
 
                        {
674
 
                        if (prefix.size)
675
 
                                em_inl();
676
 
                        else
677
 
                                em_inw();
678
 
                        i++;
679
 
                        break;
680
 
                        }
681
 
                else if (insn[i] == 0xee)
682
 
                        {
683
 
                        em_outb();
684
 
                        i++;
685
 
                        break;
686
 
                        }
687
 
                else if (insn[i] == 0xef)
688
 
                        {
689
 
                        if (prefix.size)
690
 
                                em_outl();
691
 
                        else
692
 
                                em_outw();
693
 
 
694
 
                        i++;
695
 
                        break;
696
 
                        }
697
 
                else
698
 
                        return 0;
699
 
                }
700
 
 
701
 
        context.vm.regs.eip += i;
702
 
        return 1;
703
 
        }
704
 
 
705
 
 
706
 
/*
707
 
 I don't know how to make sure I get the right vm86() from libc.
708
 
 The one I want is syscall # 113 (vm86old() in libc 5, vm86() in glibc)
709
 
 which should be declared as "int vm86(struct vm86_struct *);" in
710
 
 <sys/vm86.h>.
711
 
 
712
 
 This just does syscall 113 with inline asm, which should work
713
 
 for both libc's (I hope).
714
 
*/
715
 
#if !defined(USE_LIBC_VM86)
716
 
static int
717
 
lrmi_vm86(struct vm86_struct *vm)
718
 
        {
719
 
        int r;
720
 
#ifdef __PIC__
721
 
        asm volatile (
722
 
         "pushl %%ebx\n\t"
723
 
         "movl %2, %%ebx\n\t"
724
 
         "int $0x80\n\t"
725
 
         "popl %%ebx"
726
 
         : "=a" (r)
727
 
         : "0" (113), "r" (vm));
728
 
#else
729
 
        asm volatile (
730
 
         "int $0x80"
731
 
         : "=a" (r)
732
 
         : "0" (113), "b" (vm));
733
 
#endif
734
 
        return r;
735
 
        }
736
 
#else
737
 
#define lrmi_vm86 vm86
738
 
#endif
739
 
 
740
 
 
741
 
static void
742
 
debug_info(int vret)
743
 
        {
744
 
        int i;
745
 
        unsigned char *p;
746
 
 
747
 
        fputs("vm86() failed\n", stderr);
748
 
        fprintf(stderr, "return = 0x%x\n", vret);
749
 
        fprintf(stderr, "eax = 0x%08lx\n", context.vm.regs.eax);
750
 
        fprintf(stderr, "ebx = 0x%08lx\n", context.vm.regs.ebx);
751
 
        fprintf(stderr, "ecx = 0x%08lx\n", context.vm.regs.ecx);
752
 
        fprintf(stderr, "edx = 0x%08lx\n", context.vm.regs.edx);
753
 
        fprintf(stderr, "esi = 0x%08lx\n", context.vm.regs.esi);
754
 
        fprintf(stderr, "edi = 0x%08lx\n", context.vm.regs.edi);
755
 
        fprintf(stderr, "ebp = 0x%08lx\n", context.vm.regs.ebp);
756
 
        fprintf(stderr, "eip = 0x%08lx\n", context.vm.regs.eip);
757
 
        fprintf(stderr, "cs  = 0x%04x\n", context.vm.regs.cs);
758
 
        fprintf(stderr, "esp = 0x%08lx\n", context.vm.regs.esp);
759
 
        fprintf(stderr, "ss  = 0x%04x\n", context.vm.regs.ss);
760
 
        fprintf(stderr, "ds  = 0x%04x\n", context.vm.regs.ds);
761
 
        fprintf(stderr, "es  = 0x%04x\n", context.vm.regs.es);
762
 
        fprintf(stderr, "fs  = 0x%04x\n", context.vm.regs.fs);
763
 
        fprintf(stderr, "gs  = 0x%04x\n", context.vm.regs.gs);
764
 
        fprintf(stderr, "eflags  = 0x%08lx\n", context.vm.regs.eflags);
765
 
 
766
 
        fputs("cs:ip = [ ", stderr);
767
 
 
768
 
        p = (unsigned char *)((context.vm.regs.cs << 4) + (context.vm.regs.eip & 0xffff));
769
 
 
770
 
        for (i = 0; i < 16; ++i)
771
 
                fprintf(stderr, "%02x ", (unsigned int)p[i]);
772
 
 
773
 
        fputs("]\n", stderr);
774
 
        }
775
 
 
776
 
 
777
 
static int
778
 
run_vm86(void)
779
 
        {
780
 
        unsigned int vret;
781
 
 
782
 
        while (1)
783
 
                {
784
 
                vret = lrmi_vm86(&context.vm);
785
 
 
786
 
                if (VM86_TYPE(vret) == VM86_INTx)
787
 
                        {
788
 
                        unsigned int v = VM86_ARG(vret);
789
 
 
790
 
                        if (v == RETURN_TO_32_INT)
791
 
                                return 1;
792
 
 
793
 
                        pushw(context.vm.regs.eflags);
794
 
                        pushw(context.vm.regs.cs);
795
 
                        pushw(context.vm.regs.eip);
796
 
 
797
 
                        context.vm.regs.cs = get_int_seg(v);
798
 
                        context.vm.regs.eip = get_int_off(v);
799
 
                        context.vm.regs.eflags &= ~(VIF_MASK | TF_MASK);
800
 
 
801
 
                        continue;
802
 
                        }
803
 
 
804
 
                if (VM86_TYPE(vret) != VM86_UNKNOWN)
805
 
                        break;
806
 
 
807
 
                if (!emulate())
808
 
                        break;
809
 
                }
810
 
 
811
 
        debug_info(vret);
812
 
 
813
 
        return 0;
814
 
        }
815
 
 
816
 
 
817
 
int
818
 
LRMI_call(struct LRMI_regs *r)
819
 
        {
820
 
        unsigned int vret;
821
 
 
822
 
        memset(&context.vm.regs, 0, sizeof(context.vm.regs));
823
 
 
824
 
        set_regs(r);
825
 
 
826
 
        context.vm.regs.cs = r->cs;
827
 
        context.vm.regs.eip = r->ip;
828
 
 
829
 
        if (r->ss == 0 && r->sp == 0)
830
 
                {
831
 
                context.vm.regs.ss = context.stack_seg;
832
 
                context.vm.regs.esp = context.stack_off;
833
 
                }
834
 
        else
835
 
                {
836
 
                context.vm.regs.ss = r->ss;
837
 
                context.vm.regs.esp = r->sp;
838
 
                }
839
 
 
840
 
        pushw(context.ret_seg);
841
 
        pushw(context.ret_off);
842
 
 
843
 
        vret = run_vm86();
844
 
 
845
 
        get_regs(r);
846
 
 
847
 
        return vret;
848
 
        }
849
 
 
850
 
 
851
 
int
852
 
LRMI_int(int i, struct LRMI_regs *r)
853
 
        {
854
 
        unsigned int vret;
855
 
        unsigned int seg, off;
856
 
 
857
 
        seg = get_int_seg(i);
858
 
        off = get_int_off(i);
859
 
 
860
 
        /*
861
 
         If the interrupt is in regular memory, it's probably
862
 
         still pointing at a dos TSR (which is now gone).
863
 
        */
864
 
        if (seg < 0xa000 || (seg << 4) + off >= 0x100000)
865
 
                {
866
 
                fprintf(stderr, "Int 0x%x is not in rom (%04x:%04x)\n", i, seg, off);
867
 
                return 0;
868
 
                }
869
 
 
870
 
        memset(&context.vm.regs, 0, sizeof(context.vm.regs));
871
 
 
872
 
        set_regs(r);
873
 
 
874
 
        context.vm.regs.cs = seg;
875
 
        context.vm.regs.eip = off;
876
 
 
877
 
        if (r->ss == 0 && r->sp == 0)
878
 
                {
879
 
                context.vm.regs.ss = context.stack_seg;
880
 
                context.vm.regs.esp = context.stack_off;
881
 
                }
882
 
        else
883
 
                {
884
 
                context.vm.regs.ss = r->ss;
885
 
                context.vm.regs.esp = r->sp;
886
 
                }
887
 
 
888
 
        pushw(DEFAULT_VM86_FLAGS);
889
 
        pushw(context.ret_seg);
890
 
        pushw(context.ret_off);
891
 
 
892
 
        vret = run_vm86();
893
 
 
894
 
        get_regs(r);
895
 
 
896
 
        return vret;
897
 
        }
898