~ubuntu-branches/ubuntu/edgy/xorg-server/edgy-updates

« back to all changes in this revision

Viewing changes to hw/kdrive/vesa/vm86.c

  • Committer: Bazaar Package Importer
  • Author(s): Rodrigo Parra Novo
  • Date: 2006-07-25 20:06:28 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20060725200628-gjmmd9gxfxdc4ejs
Tags: 1:1.1.1-0ubuntu1
* New Upstream version
* Changed Build-Depends from mesa-swrast-source to mesa-swx11-source,
  following Debian package nomenclature
* Re-did 12_security_policy_in_etc.diff for 1.1.1
* Dropped 15_security_allocate_local.diff (applied upstream)
* Dropped 16_SECURITY_setuid.diff (applied upstream)
* Dropped 000_ubuntu_fix_read_kernel_mapping.patch (applied upstream)
* Dropped 002_ubuntu_fix_for_certain_intel_chipsets.patch (applied upstream)
* Updated versioned Build-Depends on mesa-swx11-source to version
  6.5.0.cvs.20060725-0ubuntu1
* Added arrayobj.c, arrayobj.h, bitset.h & rbadaptors.h to
  GL/symlink-mesa.sh (linked from mesa-swx11-source)
* Added arrayobj.c to default build target on GL/mesa/main

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * $RCSId: xc/programs/Xserver/hw/kdrive/vesa/vm86.c,v 1.2 2002/02/19 00:18:05 keithp Exp $
 
3
 *
 
4
 * Copyright � 2000 Keith Packard
 
5
 *
 
6
 * Permission to use, copy, modify, distribute, and sell this software and its
 
7
 * documentation for any purpose is hereby granted without fee, provided that
 
8
 * the above copyright notice appear in all copies and that both that
 
9
 * copyright notice and this permission notice appear in supporting
 
10
 * documentation, and that the name of Keith Packard not be used in
 
11
 * advertising or publicity pertaining to distribution of the software without
 
12
 * specific, written prior permission.  Keith Packard makes no
 
13
 * representations about the suitability of this software for any purpose.  It
 
14
 * is provided "as is" without express or implied warranty.
 
15
 *
 
16
 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 
17
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 
18
 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 
19
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 
20
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 
21
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 
22
 * PERFORMANCE OF THIS SOFTWARE.
 
23
 */
 
24
/* 
 
25
Copyright (c) 2000 by Juliusz Chroboczek
 
26
 
 
27
Permission is hereby granted, free of charge, to any person obtaining a copy
 
28
of this software and associated documentation files (the "Software"), to deal
 
29
in the Software without restriction, including without limitation the rights
 
30
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 
31
copies of the Software, and to permit persons to whom the Software is
 
32
furnished to do so, subject to the following conditions: 
 
33
 
 
34
The above copyright notice and this permission notice shall be included in
 
35
all copies or substantial portions of the Software. 
 
36
 
 
37
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
38
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
39
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
 
40
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 
41
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 
42
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 
43
THE SOFTWARE.
 
44
*/
 
45
 
 
46
#ifdef HAVE_CONFIG_H
 
47
#include <kdrive-config.h>
 
48
#endif
 
49
#include "vm86.h"
 
50
 
 
51
#define PUSHW(vi, i) \
 
52
{ vi->vms.regs.esp -= 2;\
 
53
  LMW(vi,MAKE_POINTER(vi->vms.regs.ss, vi->vms.regs.esp)) = i;}
 
54
 
 
55
static int vm86old(struct vm86_struct *vms);
 
56
static int vm86_loop(Vm86InfoPtr vi);
 
57
 
 
58
static const U8 rev_ints[32] =
 
59
{ 0, 0, 0, 0, 0, 0, 0, 0,
 
60
  0, 0, 0, 0, 0, 0, 0, 0,
 
61
  0, 0, 0, 0, 0, 0, 0, 0,
 
62
  0, 0, 0, 0, 0, 0, 0, 0x80,
 
63
};
 
64
 
 
65
static const U8 retcode_data[2] =
 
66
{ 0xCD, 0xFF };
 
67
 
 
68
Vm86InfoPtr
 
69
Vm86Setup(int mapHoles)
 
70
{
 
71
    int devmem = -1, devzero = -1;
 
72
    void *magicMem, *loMem, *hiMem;
 
73
    void *hole1, *hole2;
 
74
    U32 stack_base, ret_code;
 
75
    Vm86InfoPtr vi = NULL;
 
76
 
 
77
    devmem = open("/dev/mem", O_RDWR);
 
78
    if(devmem < 0) {
 
79
        perror("open /dev/mem");
 
80
        goto fail;
 
81
    }
 
82
 
 
83
    devzero = open("/dev/zero", O_RDWR);
 
84
    if(devzero < 0) {
 
85
        perror("open /dev/zero");
 
86
        goto fail;
 
87
    }
 
88
 
 
89
    magicMem = MAP_FAILED;
 
90
    loMem = MAP_FAILED;
 
91
    hiMem = MAP_FAILED;
 
92
    hole1 = MAP_FAILED;
 
93
    hole2 = MAP_FAILED;
 
94
 
 
95
 
 
96
    magicMem = mmap((void*)MAGICMEM_BASE, MAGICMEM_SIZE,
 
97
                    PROT_READ | PROT_WRITE | PROT_EXEC,
 
98
                    MAP_PRIVATE | MAP_FIXED, devmem, MAGICMEM_BASE);
 
99
    
 
100
    if(magicMem == MAP_FAILED) {
 
101
        ErrorF("Couldn't map magic memory\n");
 
102
        goto unmapfail;
 
103
    }
 
104
 
 
105
    if(mapHoles) {
 
106
        hole1 = mmap((void*)HOLE1_BASE, HOLE1_SIZE,
 
107
                     PROT_READ | PROT_WRITE | PROT_EXEC,
 
108
                     MAP_PRIVATE | MAP_FIXED, devzero, HOLE1_BASE);
 
109
    
 
110
        if(hole1 == MAP_FAILED) {
 
111
            ErrorF("Couldn't map first hole\n");
 
112
            goto unmapfail;
 
113
        }
 
114
    }
 
115
 
 
116
    loMem = mmap((void*)LOMEM_BASE, LOMEM_SIZE,
 
117
                 PROT_READ | PROT_WRITE | PROT_EXEC,
 
118
                 MAP_PRIVATE | MAP_FIXED, devzero, LOMEM_BASE);
 
119
    if(loMem == MAP_FAILED) {
 
120
        ErrorF("Couldn't map low memory\n");
 
121
        munmap(magicMem, MAGICMEM_SIZE);
 
122
        goto unmapfail;
 
123
    }
 
124
 
 
125
    if(mapHoles) {
 
126
        hole2 = mmap((void*)HOLE2_BASE, HOLE2_SIZE,
 
127
                     PROT_READ | PROT_WRITE | PROT_EXEC,
 
128
                     MAP_PRIVATE | MAP_FIXED, devzero, HOLE2_BASE);
 
129
    
 
130
        if(hole2 == MAP_FAILED) {
 
131
            ErrorF("Couldn't map first hole\n");
 
132
            goto unmapfail;
 
133
        }
 
134
    }
 
135
 
 
136
    hiMem = mmap((void*)HIMEM_BASE, HIMEM_SIZE,
 
137
                 PROT_READ | PROT_WRITE | PROT_EXEC,
 
138
                 MAP_SHARED | MAP_FIXED,
 
139
                 devmem, HIMEM_BASE);
 
140
    if(hiMem == MAP_FAILED) {
 
141
        ErrorF("Couldn't map high memory\n");
 
142
        goto unmapfail;
 
143
    }
 
144
 
 
145
    vi = xalloc(sizeof(Vm86InfoRec));
 
146
    if (!vi)
 
147
        goto unmapfail;
 
148
 
 
149
    vi->magicMem = magicMem;
 
150
    vi->hole1 = hole1;
 
151
    vi->loMem = loMem;
 
152
    vi->hole2 = hole2;
 
153
    vi->hiMem = hiMem;
 
154
    vi->brk = LOMEM_BASE;
 
155
 
 
156
    stack_base = Vm86AllocateMemory(vi, STACK_SIZE);
 
157
    if(stack_base == ALLOC_FAIL)
 
158
        goto unmapfail;
 
159
    ret_code = Vm86AllocateMemory(vi, sizeof(retcode_data));
 
160
    if(ret_code == ALLOC_FAIL)
 
161
        goto unmapfail;
 
162
 
 
163
    vi->stack_base = stack_base;
 
164
    vi->ret_code = ret_code;
 
165
 
 
166
    memset(&vi->vms, 0, sizeof(struct vm86_struct));
 
167
    vi->vms.flags = 0;
 
168
    vi->vms.screen_bitmap = 0;
 
169
    vi->vms.cpu_type = CPU_586;
 
170
    memcpy(&vi->vms.int_revectored, rev_ints, sizeof(rev_ints));
 
171
 
 
172
    iopl(3);
 
173
    
 
174
    if(devmem >= 0)
 
175
        close(devmem);
 
176
    if(devzero >= 0)
 
177
        close(devzero);
 
178
 
 
179
    return vi;
 
180
 
 
181
unmapfail:
 
182
    if(magicMem != MAP_FAILED) munmap(magicMem, MAGICMEM_SIZE);
 
183
    if(hole1 != MAP_FAILED) munmap(hole1, HOLE1_SIZE);
 
184
    if(loMem != MAP_FAILED) munmap(loMem, LOMEM_SIZE);
 
185
    if(hole2 != MAP_FAILED) munmap(hole2, HOLE2_SIZE);
 
186
    if(hiMem != MAP_FAILED) munmap(hiMem, HIMEM_SIZE);
 
187
fail:
 
188
    if(devmem >= 0)
 
189
        close(devmem);
 
190
    if(devzero >= 0)
 
191
        close(devzero);
 
192
    if(vi)
 
193
        xfree(vi);
 
194
    return NULL;
 
195
}
 
196
 
 
197
void
 
198
Vm86Cleanup(Vm86InfoPtr vi)
 
199
{
 
200
    if(vi->magicMem != MAP_FAILED) munmap(vi->magicMem, MAGICMEM_SIZE);
 
201
    if(vi->hole1 != MAP_FAILED) munmap(vi->hole1, HOLE1_SIZE);
 
202
    if(vi->loMem != MAP_FAILED) munmap(vi->loMem, LOMEM_SIZE);
 
203
    if(vi->hole2 != MAP_FAILED) munmap(vi->hole2, HOLE2_SIZE);
 
204
    if(vi->hiMem != MAP_FAILED) munmap(vi->hiMem, HIMEM_SIZE);
 
205
    xfree(vi);
 
206
}
 
207
 
 
208
int
 
209
Vm86DoInterrupt(Vm86InfoPtr vi, int num)
 
210
{
 
211
    U16 seg, off;
 
212
    int code;
 
213
 
 
214
    if(num < 0 || num>256) {
 
215
        ErrorF("Interrupt %d doesn't exist\n");
 
216
        return -1;
 
217
    }
 
218
    seg = MMW(vi,num * 4 + 2);
 
219
    off = MMW(vi,num * 4);
 
220
    if(MAKE_POINTER(seg, off) < ROM_BASE ||
 
221
       MAKE_POINTER(seg, off) >= ROM_BASE + ROM_SIZE) {
 
222
        ErrorF("Interrupt pointer (seg %x off %x) doesn't point at ROM\n",
 
223
               seg, off);
 
224
        return -1;
 
225
    }
 
226
    memcpy(&(LM(vi,vi->ret_code)), retcode_data, sizeof(retcode_data));
 
227
    vi->vms.regs.eflags = IF_MASK | IOPL_MASK;
 
228
    vi->vms.regs.ss = POINTER_SEGMENT(vi->stack_base);
 
229
    vi->vms.regs.esp = STACK_SIZE;
 
230
    PUSHW(vi, IF_MASK | IOPL_MASK);
 
231
    PUSHW(vi, POINTER_SEGMENT(vi->ret_code));
 
232
    PUSHW(vi, POINTER_OFFSET(vi->ret_code));
 
233
    vi->vms.regs.cs = seg;
 
234
    vi->vms.regs.eip = off;
 
235
    OsBlockSignals ();
 
236
    code = vm86_loop(vi);
 
237
    OsReleaseSignals ();
 
238
    if(code < 0) {
 
239
        ErrorF("vm86 failed (errno %d)\n", errno);
 
240
        return -1;
 
241
    } else if(code != 0) {
 
242
        ErrorF("vm86 returned 0x%04X\n", code);
 
243
        return -1;
 
244
    } else
 
245
        return 0;
 
246
}
 
247
 
 
248
int
 
249
Vm86DoPOST(Vm86InfoPtr vi)
 
250
{
 
251
    U16 seg, off;
 
252
    int code;
 
253
 
 
254
    seg = 0xC000;
 
255
    off = 3;
 
256
    if(MAKE_POINTER(seg, off) < ROM_BASE ||
 
257
       MAKE_POINTER(seg, off) >= ROM_BASE + ROM_SIZE) {
 
258
        ErrorF("BIOS pointer (seg %x off %x) doesn't point at ROM\n",
 
259
               seg, off);
 
260
        return -1;
 
261
    }
 
262
    memcpy(&(LM(vi,vi->ret_code)), retcode_data, sizeof(retcode_data));
 
263
    vi->vms.regs.ss = POINTER_SEGMENT(vi->stack_base);
 
264
    vi->vms.regs.esp = STACK_SIZE;
 
265
    PUSHW(vi, POINTER_SEGMENT(vi->ret_code));
 
266
    PUSHW(vi, POINTER_OFFSET(vi->ret_code));
 
267
    vi->vms.regs.cs = seg;
 
268
    vi->vms.regs.eip = off;
 
269
    OsBlockSignals ();
 
270
    code = vm86_loop(vi);
 
271
    OsReleaseSignals ();
 
272
    if(code < 0) {
 
273
        ErrorF("vm86 failed (errno %d)\n", errno);
 
274
        return -1;
 
275
    } else if(code != 0) {
 
276
        ErrorF("vm86 returned 0x%04X\n", code);
 
277
        return -1;
 
278
    } else
 
279
        return 0;
 
280
}
 
281
 
 
282
#define DEBUG_VBE 0
 
283
#if DEBUG_VBE
 
284
#define DBG(x) ErrorF x; usleep(10*1000)
 
285
#else
 
286
#define DBG(x)
 
287
#endif
 
288
 
 
289
static inline U8 
 
290
vm86_inb(U16 port)
 
291
{
 
292
    U8 value;
 
293
    
 
294
    if (port != 0x3da)
 
295
    {
 
296
        DBG(("inb  0x%04x", port));
 
297
    }
 
298
    asm volatile ("inb %w1,%b0" : "=a" (value) : "d" (port));
 
299
    if (port != 0x3da)
 
300
    {
 
301
        DBG((" = 0x%02x\n", value));
 
302
    }
 
303
    return value;
 
304
}
 
305
 
 
306
static inline U16
 
307
vm86_inw(U16 port)
 
308
{
 
309
    U16 value;
 
310
    DBG(("inw  0x%04x", port));
 
311
    asm volatile ("inw %w1,%w0" : "=a" (value) : "d" (port));
 
312
    DBG((" = 0x%04x\n", value));
 
313
    return value;
 
314
}
 
315
 
 
316
static inline U32
 
317
vm86_inl(U16 port)
 
318
{
 
319
    U32 value;
 
320
    DBG(("inl  0x%04x", port));
 
321
    asm volatile ("inl %w1,%0" : "=a" (value) : "d" (port));
 
322
    DBG((" = 0x%08x\n", value));
 
323
    return value;
 
324
}
 
325
 
 
326
static inline void
 
327
vm86_outb(U16 port, U8 value)
 
328
{
 
329
#if 0
 
330
    static U8 CR;
 
331
 
 
332
    if (port == 0x3d4)
 
333
        CR = value;
 
334
    if (port == 0x3d5 && CR == 0xa4)
 
335
    {
 
336
        DBG(("outb 0x%04x = 0x%02x (skipped)\n", port, value));
 
337
        return;
 
338
    }
 
339
#endif
 
340
    DBG(("outb 0x%04x = 0x%02x\n", port, value));
 
341
    asm volatile ("outb %b0,%w1" : : "a" (value), "d" (port));
 
342
}
 
343
 
 
344
static inline void
 
345
vm86_outw(U16 port, U16 value)
 
346
{
 
347
    DBG(("outw 0x%04x = 0x%04x\n", port, value));
 
348
    asm volatile ("outw %w0,%w1" : : "a" (value), "d" (port));
 
349
}
 
350
 
 
351
static inline void
 
352
vm86_outl(U16 port, U32 value)
 
353
{
 
354
    DBG(("outl 0x%04x = 0x%08x\n", port, value));
 
355
    asm volatile ("outl %0,%w1" : : "a" (value), "d" (port));
 
356
}
 
357
 
 
358
#define SEG_CS 1
 
359
#define SEG_DS 2
 
360
#define SEG_ES 3
 
361
#define SEG_SS 4
 
362
#define SEG_GS 5
 
363
#define SEG_FS 6
 
364
#define REP 1
 
365
#define REPNZ 2
 
366
#define SET_8(_x, _y) (_x) = ((_x) & ~0xFF) | ((_y) & 0xFF);
 
367
#define SET_16(_x, _y) (_x) = ((_x) & ~0xFFFF) | ((_y) & 0xFFFF);
 
368
#define INC_IP(_i) SET_16(regs->eip, (regs->eip + _i))
 
369
#define AGAIN INC_IP(1); goto again;
 
370
 
 
371
static int
 
372
vm86_emulate(Vm86InfoPtr vi)
 
373
{
 
374
    struct vm86_regs *regs = &vi->vms.regs;
 
375
    U8 opcode;
 
376
    int size;
 
377
    int pref_seg = 0, pref_rep = 0, pref_66 = 0, pref_67 = 0;
 
378
 
 
379
  again:
 
380
    if(!Vm86IsMemory(vi, MAKE_POINTER(regs->cs, regs->eip))) {
 
381
        ErrorF("Trying to execute unmapped memory\n");
 
382
        return -1;
 
383
    }
 
384
    opcode = Vm86Memory(vi, MAKE_POINTER(regs->cs, regs->eip));
 
385
    switch(opcode) {
 
386
    case 0x2E: pref_seg = SEG_CS; AGAIN;
 
387
    case 0x3E: pref_seg = SEG_DS; AGAIN;
 
388
    case 0x26: pref_seg = SEG_ES; AGAIN;
 
389
    case 0x36: pref_seg = SEG_SS; AGAIN;
 
390
    case 0x65: pref_seg = SEG_GS; AGAIN;
 
391
    case 0x64: pref_seg = SEG_FS; AGAIN;
 
392
    case 0x66: pref_66 = 1; AGAIN;
 
393
    case 0x67: pref_67 = 1; AGAIN;
 
394
    case 0xF2: pref_rep = REPNZ; AGAIN;
 
395
    case 0xF3: pref_rep = REP; AGAIN;
 
396
 
 
397
    case 0xEC:                  /* IN AL, DX */
 
398
        SET_8(regs->eax, vm86_inb(regs->edx & 0xFFFF));
 
399
        INC_IP(1);
 
400
        break;
 
401
    case 0xED:                  /* IN AX, DX */
 
402
        if(pref_66)
 
403
            regs->eax = vm86_inl(regs->edx & 0xFFFF);
 
404
        else
 
405
            SET_16(regs->eax, vm86_inw(regs->edx & 0xFFFF));
 
406
        INC_IP(1);
 
407
        break;
 
408
    case 0xE4:                  /* IN AL, imm8 */
 
409
        SET_8(regs->eax, 
 
410
              vm86_inb(Vm86Memory(vi, MAKE_POINTER(regs->cs, regs->eip+1))));
 
411
        INC_IP(2);
 
412
        break;
 
413
    case 0xE5:                  /* IN AX, imm8 */
 
414
        if(pref_66)
 
415
            regs->eax =
 
416
                vm86_inl(Vm86Memory(vi, MAKE_POINTER(regs->cs, regs->eip+1)));
 
417
        else
 
418
            SET_16(regs->eax, 
 
419
                   vm86_inw(Vm86Memory(vi, MAKE_POINTER(regs->cs, regs->eip+1))));
 
420
        INC_IP(2);
 
421
        break;
 
422
    case 0x6C:                  /* INSB */
 
423
    case 0x6D:                  /* INSW */
 
424
        if(opcode == 0x6C) {
 
425
            Vm86WriteMemory(vi, MAKE_POINTER(regs->es, regs->edi),
 
426
                vm86_inb(regs->edx & 0xFFFF));
 
427
            size = 1;
 
428
        } else if(pref_66) {
 
429
            Vm86WriteMemoryL(vi, MAKE_POINTER(regs->es, regs->edi),
 
430
                vm86_inl(regs->edx & 0xFFFF));
 
431
            size = 4;
 
432
        } else {
 
433
            Vm86WriteMemoryW(vi, MAKE_POINTER(regs->es, regs->edi),
 
434
                vm86_inw(regs->edx & 0xFFFF));
 
435
            size = 2;
 
436
        }
 
437
        if(regs->eflags & (1<<10))
 
438
            regs->edi -= size;
 
439
        else
 
440
            regs->edi += size;
 
441
        if(pref_rep) {
 
442
            if(pref_66) {
 
443
                regs->ecx--;
 
444
                if(regs->ecx != 0)
 
445
                    goto again;
 
446
            } else {
 
447
                SET_16(regs->ecx, regs->ecx - 1);
 
448
                if((regs->ecx & 0xFFFF) != 0)
 
449
                    goto again;
 
450
            }
 
451
        }
 
452
        INC_IP(1);
 
453
        break;
 
454
 
 
455
    case 0xEE:                  /* OUT DX, AL */
 
456
        vm86_outb(regs->edx & 0xFFFF, regs->eax & 0xFF);
 
457
        INC_IP(1);
 
458
        break;
 
459
    case 0xEF:                  /* OUT DX, AX */
 
460
        if(pref_66)
 
461
            vm86_outl(regs->edx & 0xFFFF, regs->eax);
 
462
        else
 
463
            vm86_outw(regs->edx & 0xFFFF, regs->eax & 0xFFFF);
 
464
        INC_IP(1);
 
465
        break;
 
466
    case 0xE6:                  /* OUT imm8, AL */
 
467
        vm86_outb(Vm86Memory(vi, MAKE_POINTER(regs->cs, regs->eip+1)),
 
468
             regs->eax & 0xFF);
 
469
        INC_IP(2);
 
470
        break;
 
471
    case 0xE7:                  /* OUT imm8, AX */
 
472
        if(pref_66)
 
473
            vm86_outl(Vm86Memory(vi, MAKE_POINTER(regs->cs, regs->eip+1)),
 
474
                  regs->eax);
 
475
        else
 
476
            vm86_outw(Vm86Memory(vi, MAKE_POINTER(regs->cs, regs->eip+1)),
 
477
                 regs->eax & 0xFFFF);
 
478
        INC_IP(2);
 
479
        break;
 
480
    case 0x6E:                  /* OUTSB */
 
481
    case 0x6F:                  /* OUTSW */
 
482
        if(opcode == 0x6E) {
 
483
            vm86_outb(regs->edx & 0xFFFF, 
 
484
                 Vm86Memory(vi, MAKE_POINTER(regs->es, regs->edi)));
 
485
            size = 1;
 
486
        } else if(pref_66) {
 
487
            vm86_outl(regs->edx & 0xFFFF, 
 
488
                 Vm86Memory(vi, MAKE_POINTER(regs->es, regs->edi)));
 
489
            size = 4;
 
490
        } else {
 
491
            vm86_outw(regs->edx & 0xFFFF, 
 
492
                 Vm86Memory(vi, MAKE_POINTER(regs->es, regs->edi)));
 
493
            size = 2;
 
494
        }
 
495
        if(regs->eflags & (1<<10))
 
496
            regs->edi -= size;
 
497
        else
 
498
            regs->edi += size;
 
499
        if(pref_rep) {
 
500
            if(pref_66) {
 
501
                regs->ecx--;
 
502
                if(regs->ecx != 0)
 
503
                    goto again;
 
504
            } else {
 
505
                SET_16(regs->ecx, regs->ecx - 1);
 
506
                if((regs->ecx & 0xFFFF) != 0)
 
507
                    goto again;
 
508
            }
 
509
        }
 
510
        INC_IP(1);
 
511
        break;
 
512
 
 
513
    case 0x0F:
 
514
        ErrorF("Hit 0F trap in VM86 code\n");
 
515
        return -1;
 
516
    case 0xF0:
 
517
        ErrorF("Hit lock prefix in VM86 code\n");
 
518
        return -1;
 
519
    case 0xF4:
 
520
        ErrorF("Hit HLT in VM86 code\n");
 
521
        return -1;
 
522
 
 
523
    default:
 
524
        ErrorF("Unhandled GP fault in VM86 code (opcode = 0x%02X)\n",
 
525
               opcode);
 
526
        return -1;
 
527
    }
 
528
    return 0;
 
529
}
 
530
#undef SEG_CS
 
531
#undef SEG_DS
 
532
#undef SEG_ES
 
533
#undef SEG_SS
 
534
#undef SEG_GS
 
535
#undef SEG_FS
 
536
#undef REP
 
537
#undef REPNZ
 
538
#undef SET_8
 
539
#undef SET_16
 
540
#undef INC_IP
 
541
#undef AGAIN
 
542
 
 
543
static int
 
544
vm86_loop(Vm86InfoPtr vi)
 
545
{
 
546
    int code;
 
547
    
 
548
    while(1) {
 
549
        code = vm86old(&vi->vms);
 
550
        switch(VM86_TYPE(code)) {
 
551
        case VM86_SIGNAL:
 
552
            continue;
 
553
        case VM86_UNKNOWN:
 
554
            code = vm86_emulate(vi);
 
555
            if(code < 0) {
 
556
                Vm86Debug(vi);
 
557
                return -1;
 
558
            }
 
559
            break;
 
560
        case VM86_INTx:
 
561
            if(VM86_ARG(code) == 0xFF)
 
562
                return 0;
 
563
            else {
 
564
                PUSHW(vi, vi->vms.regs.eflags)
 
565
                PUSHW(vi, vi->vms.regs.cs);
 
566
                PUSHW(vi, vi->vms.regs.eip);
 
567
                vi->vms.regs.cs = MMW(vi,VM86_ARG(code) * 4 + 2);
 
568
                vi->vms.regs.eip = MMW(vi,VM86_ARG(code) * 4);
 
569
            }
 
570
            break;
 
571
        case VM86_STI:
 
572
            ErrorF("VM86 code enabled interrupts\n");
 
573
            Vm86Debug(vi);
 
574
            return -1;
 
575
        default:
 
576
            ErrorF("Unexpected result code 0x%X from vm86\n", code);
 
577
            Vm86Debug(vi);
 
578
            return -1;
 
579
        }
 
580
    }
 
581
}
 
582
 
 
583
int 
 
584
Vm86IsMemory(Vm86InfoPtr vi, U32 i) 
 
585
{
 
586
    if(i >= MAGICMEM_BASE && i< MAGICMEM_BASE + MAGICMEM_SIZE)
 
587
        return 1;
 
588
    else if(i >= LOMEM_BASE && i< LOMEM_BASE + LOMEM_SIZE)
 
589
        return 1;
 
590
    else if(i >= HIMEM_BASE && i< HIMEM_BASE + HIMEM_SIZE)
 
591
        return 1;
 
592
    else
 
593
        return 0;
 
594
}
 
595
 
 
596
U8 
 
597
Vm86Memory(Vm86InfoPtr vi, U32 i)
 
598
{
 
599
    if(i >= MAGICMEM_BASE && i< MAGICMEM_BASE + MAGICMEM_SIZE)
 
600
        return MM(vi, i);
 
601
    else if(i >= LOMEM_BASE && i< LOMEM_BASE + LOMEM_SIZE)
 
602
        return LM(vi, i);
 
603
    else if(i >= HIMEM_BASE && i< HIMEM_BASE + HIMEM_SIZE)
 
604
        return HM(vi, i);
 
605
    else {
 
606
        ErrorF("Reading unmapped memory at 0x%08X\n", i);
 
607
        return 0;
 
608
    }
 
609
}
 
610
 
 
611
U16
 
612
Vm86MemoryW(Vm86InfoPtr vi, U32 i)
 
613
{
 
614
    if(i >= MAGICMEM_BASE && i< MAGICMEM_BASE + MAGICMEM_SIZE)
 
615
        return MMW(vi, i);
 
616
    else if(i >= LOMEM_BASE && i< LOMEM_BASE + LOMEM_SIZE)
 
617
        return LMW(vi, i);
 
618
    else if(i >= HIMEM_BASE && i< HIMEM_BASE + HIMEM_SIZE)
 
619
        return HMW(vi, i);
 
620
    else {
 
621
        ErrorF("Reading unmapped memory at 0x%08X\n", i);
 
622
        return 0;
 
623
    }
 
624
}
 
625
 
 
626
U32
 
627
Vm86MemoryL(Vm86InfoPtr vi, U32 i)
 
628
{
 
629
    if(i >= MAGICMEM_BASE && i< MAGICMEM_BASE + MAGICMEM_SIZE)
 
630
        return MML(vi, i);
 
631
    else if(i >= LOMEM_BASE && i< LOMEM_BASE + LOMEM_SIZE)
 
632
        return LML(vi, i);
 
633
    else if(i >= HIMEM_BASE && i< HIMEM_BASE + HIMEM_SIZE)
 
634
        return HML(vi, i);
 
635
    else {
 
636
        ErrorF("Reading unmapped memory at 0x%08X\n", i);
 
637
        return 0;
 
638
    }
 
639
}
 
640
 
 
641
void
 
642
Vm86WriteMemory(Vm86InfoPtr vi, U32 i, U8 val)
 
643
{
 
644
    if(i >= MAGICMEM_BASE && i< MAGICMEM_BASE + MAGICMEM_SIZE)
 
645
        MM(vi, i) = val;
 
646
    else if(i >= LOMEM_BASE && i< LOMEM_BASE + LOMEM_SIZE)
 
647
        LM(vi, i) = val;
 
648
    else if(i >= HIMEM_BASE && i< HIMEM_BASE + HIMEM_SIZE)
 
649
        HM(vi, i) = val;
 
650
    else {
 
651
        ErrorF("Writing unmapped memory at 0x%08X\n", i);
 
652
    }
 
653
}
 
654
 
 
655
void
 
656
Vm86WriteMemoryW(Vm86InfoPtr vi, U32 i, U16 val)
 
657
{
 
658
    if(i >= MAGICMEM_BASE && i< MAGICMEM_BASE + MAGICMEM_SIZE)
 
659
        MMW(vi, i) = val;
 
660
    else if(i >= LOMEM_BASE && i< LOMEM_BASE + LOMEM_SIZE)
 
661
        LMW(vi, i) = val;
 
662
    else if(i >= HIMEM_BASE && i< HIMEM_BASE + HIMEM_SIZE)
 
663
        HMW(vi, i) = val;
 
664
    else {
 
665
        ErrorF("Writing unmapped memory at 0x%08X\n", i);
 
666
    }
 
667
}
 
668
 
 
669
void
 
670
Vm86WriteMemoryL(Vm86InfoPtr vi, U32 i, U32 val)
 
671
{
 
672
    if(i >= MAGICMEM_BASE && i< MAGICMEM_BASE + MAGICMEM_SIZE)
 
673
        MML(vi, i) = val;
 
674
    else if(i >= LOMEM_BASE && i< LOMEM_BASE + LOMEM_SIZE)
 
675
        LML(vi, i) = val;
 
676
    else if(i >= HIMEM_BASE && i< HIMEM_BASE + HIMEM_SIZE)
 
677
        HML(vi, i) = val;
 
678
    else {
 
679
        ErrorF("Writing unmapped memory at 0x%08X\n", i);
 
680
    }
 
681
}
 
682
 
 
683
int
 
684
Vm86AllocateMemory(Vm86InfoPtr vi, int n)
 
685
{
 
686
    int ret;
 
687
    if(n<0) {
 
688
        ErrorF("Asked to allocate negative amount of memory\n");
 
689
        return vi->brk;
 
690
    }
 
691
      
 
692
    n = (n + 15) & ~15;
 
693
    if(vi->brk + n > LOMEM_BASE + LOMEM_SIZE) {
 
694
        ErrorF("Out of low memory\n");
 
695
        exit(2);
 
696
    }
 
697
    ret = vi->brk;
 
698
    vi->brk += n;
 
699
    return ret;
 
700
}
 
701
 
 
702
int
 
703
Vm86MarkMemory (Vm86InfoPtr vi)
 
704
{
 
705
    return vi->brk;
 
706
}
 
707
 
 
708
void
 
709
Vm86ReleaseMemory (Vm86InfoPtr vi, int mark)
 
710
{
 
711
    vi->brk = mark;
 
712
}
 
713
 
 
714
static int
 
715
vm86old(struct vm86_struct *vm)
 
716
{
 
717
    int res;
 
718
    
 
719
    asm volatile (
 
720
        "pushl %%ebx\n\t"
 
721
        "movl %2, %%ebx\n\t"
 
722
        "movl %1,%%eax\n\t"
 
723
        "int $0x80\n\t"
 
724
        "popl %%ebx"
 
725
        : "=a" (res)  : "n" (113), "r" (vm));
 
726
    if(res < 0) {
 
727
        errno = -res;
 
728
        res = -1;
 
729
    } else 
 
730
        errno = 0;
 
731
    return res;
 
732
}
 
733
 
 
734
void
 
735
Vm86Debug(Vm86InfoPtr vi)
 
736
{
 
737
    struct vm86_regs *regs = &vi->vms.regs;
 
738
    int i;
 
739
 
 
740
    ErrorF("eax=0x%08lX ebx=0x%08lX ecx=0x%08lX edx=0x%08lX\n",
 
741
           regs->eax, regs->ebx, regs->ecx, regs->edx);
 
742
    ErrorF("esi=0x%08lX edi=0x%08lX ebp=0x%08lX\n",
 
743
           regs->esi, regs->edi, regs->ebp);
 
744
    ErrorF("eip=0x%08lX esp=0x%08lX eflags=0x%08lX\n",
 
745
           regs->eip, regs->esp, regs->eflags);
 
746
    ErrorF("cs=0x%04lX      ds=0x%04lX      es=0x%04lX      fs=0x%04lX      gs=0x%04lX\n",
 
747
           regs->cs, regs->ds, regs->es, regs->fs, regs->gs);
 
748
    for(i=-7; i<8; i++) {
 
749
        ErrorF(" %s%02X",
 
750
               i==0?"->":"",
 
751
               Vm86Memory(vi, MAKE_POINTER(regs->cs, regs->eip + i)));
 
752
    }
 
753
    ErrorF("\n");
 
754
}
 
755
 
 
756
#ifdef NOT_IN_X_SERVER
 
757
static void 
 
758
ErrorF(char *f, ...)
 
759
{
 
760
    va_list args;
 
761
    va_start(args, f);
 
762
    vfprintf(stderr, f, args);
 
763
    va_end(args);
 
764
}
 
765
#endif