diff options
author | nalin <nalin> | 1999-07-19 02:42:45 +0000 |
---|---|---|
committer | nalin <nalin> | 1999-07-19 02:42:45 +0000 |
commit | ca7bf6afc296d97835f894e53a74a0fab2d8e7d4 (patch) | |
tree | 2bcf153efde07c55645f989f423ba9ad605c14e2 | |
parent | 7ed8488db0acde7a732c4f5281b318e1dfe91b81 (diff) | |
download | anaconda-ca7bf6afc296d97835f894e53a74a0fab2d8e7d4.tar.gz anaconda-ca7bf6afc296d97835f894e53a74a0fab2d8e7d4.tar.xz anaconda-ca7bf6afc296d97835f894e53a74a0fab2d8e7d4.zip |
add emulation for ret, pushf, popf, etc.
-rw-r--r-- | ddcprobe/bioscall.c | 63 |
1 files changed, 57 insertions, 6 deletions
diff --git a/ddcprobe/bioscall.c b/ddcprobe/bioscall.c index 40e9b448d..011960fdb 100644 --- a/ddcprobe/bioscall.c +++ b/ddcprobe/bioscall.c @@ -103,6 +103,38 @@ void do_vm86(struct vm86_struct *vm, char *memory, unsigned stop_eip) { vm->regs.eip++; break; } + case 0xfa: { /* cli */ + vm->regs.eflags &= ~(0x0200); + vm->regs.eip++; + break; + } + case 0xfb: { /* sti */ + vm->regs.eflags |= ~(0x0200); + vm->regs.eip++; + break; + } + case 0x9c: { /* pushf */ + vm->regs.esp -= 2; + *(u_int16_t*) &memory[vm->regs.ss * 16 + + vm->regs.esp] + = vm->regs.eflags & 0xffff; + vm->regs.eip++; + break; + } + case 0x9d: { /* popf */ + vm->regs.esp += 2; + vm->regs.eflags &= 0xffff0000; + vm->regs.eflags |= + *(u_int16_t*) &memory[vm->regs.ss * 16 + + vm->regs.esp]; + vm->regs.eip++; + break; + } + case 0xf0: { /* lock prefix */ + /* ignore it */ + vm->regs.eip++; + break; + } case 0x66: { /* 32-bit extension prefix. Valid, even in v86 mode. Weird. */ @@ -133,17 +165,35 @@ void do_vm86(struct vm86_struct *vm, char *memory, unsigned stop_eip) { vm->regs.esp -= 2; *(u_int16_t*) &memory[vm->regs.ss * 16 + vm->regs.esp] - = vm->regs.ebp; + = vm->regs.ebp & 0xffff; vm->regs.eip++; break; } case 0x5d: { /* pop bp */ - vm->regs.ebp = *(u_int16_t*) + vm->regs.ebp &= 0xffff0000; + vm->regs.ebp |= *(u_int16_t*) &memory[vm->regs.ss*16 + vm->regs.esp]; vm->regs.esp += 2; vm->regs.eip++; break; } + case 0xc3: { /* ret near, just pop ip */ + vm->regs.eip &= 0xffff0000; + vm->regs.eip |= *(u_int16_t*) + &memory[vm->regs.ss*16 + vm->regs.esp]; + vm->regs.esp += 2; + break; + } + case 0xcb: { /* ret far, pop both ip and cs */ + vm->regs.eip &= 0xffff0000; + vm->regs.eip |= *(u_int16_t*) + &memory[vm->regs.ss*16 + vm->regs.esp]; + vm->regs.esp += 2; + vm->regs.cs = *(u_int16_t*) + &memory[vm->regs.ss*16 + vm->regs.esp]; + vm->regs.esp += 2; + break; + } default: { fprintf(stderr, "Unexpected stop!\n"); dump_regs(&vm->regs); @@ -173,8 +223,8 @@ unsigned char *vm86_ram_alloc() unsigned char *memory; int fd; - /* Grab address 0 for this process. */ - memory = mmap(0, 0x100000, PROT_READ | PROT_EXEC | PROT_WRITE, + /* Grab address 0 for this process. mmap() 1 megabyte + 64k HMA */ + memory = mmap(0, 0x110000, PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE | MAP_FIXED | MAP_ANON, -1, 0x00000); if(memory == MAP_FAILED) { perror("error mmap()ing memory for the BIOS"); @@ -187,7 +237,7 @@ unsigned char *vm86_ram_alloc() perror("reading kernel memory"); return MAP_FAILED; } - read(fd, memory, 0x100000); + read(fd, memory, 0x110000); close(fd); return memory; @@ -195,7 +245,7 @@ unsigned char *vm86_ram_alloc() void vm86_ram_free(unsigned char *ram) { - munmap(ram, 0x100000); + munmap(ram, 0x110000); } void bioscall(unsigned char int_no, struct vm86_regs *regs, unsigned char *mem) @@ -206,6 +256,7 @@ void bioscall(unsigned char int_no, struct vm86_regs *regs, unsigned char *mem) memcpy(&vm.regs, regs, sizeof(vm.regs)); vm.regs.cs = BIOSCALL_START_SEG; vm.regs.eip = BIOSCALL_START_OFS; + vm.flags = VM_MASK | IOPL_MASK; memcpy(&mem[BIOSCALL_START_SEG * 16 + BIOSCALL_START_OFS], call, sizeof(call)); do_vm86(&vm, mem, BIOSCALL_START_OFS + sizeof(call)); |