summaryrefslogtreecommitdiffstats
path: root/ddcprobe
diff options
context:
space:
mode:
authornalin <nalin>1999-07-19 02:42:45 +0000
committernalin <nalin>1999-07-19 02:42:45 +0000
commitca7bf6afc296d97835f894e53a74a0fab2d8e7d4 (patch)
tree2bcf153efde07c55645f989f423ba9ad605c14e2 /ddcprobe
parent7ed8488db0acde7a732c4f5281b318e1dfe91b81 (diff)
downloadanaconda-ca7bf6afc296d97835f894e53a74a0fab2d8e7d4.tar.gz
anaconda-ca7bf6afc296d97835f894e53a74a0fab2d8e7d4.tar.xz
anaconda-ca7bf6afc296d97835f894e53a74a0fab2d8e7d4.zip
add emulation for ret, pushf, popf, etc.
Diffstat (limited to 'ddcprobe')
-rw-r--r--ddcprobe/bioscall.c63
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));