diff options
Diffstat (limited to 'lib_i386/realmode.c')
| -rw-r--r-- | lib_i386/realmode.c | 44 | 
1 files changed, 35 insertions, 9 deletions
| diff --git a/lib_i386/realmode.c b/lib_i386/realmode.c index 27d469382..d7bb81c57 100644 --- a/lib_i386/realmode.c +++ b/lib_i386/realmode.c @@ -33,25 +33,33 @@  extern char realmode_enter; - -int enter_realmode(u16 seg, u16 off, struct pt_regs *in, struct pt_regs *out) +int realmode_setup(void)  { -	 -	/* setup out thin bios emulation */ -	if (bios_setup()) { -		return -1; -	} -		  	/* copy the realmode switch code */  	if (i386boot_realmode_size > (REALMODE_MAILBOX-REALMODE_BASE)) {  		printf("realmode switch too large (%ld bytes, max is %d)\n",  -		       i386boot_realmode_size, (int)(REALMODE_MAILBOX-REALMODE_BASE)); +		       i386boot_realmode_size, (REALMODE_MAILBOX-REALMODE_BASE));  		return -1;  	}  	memcpy(REALMODE_BASE, (void*)i386boot_realmode, i386boot_realmode_size); +	asm("wbinvd\n"); +	 +	return 0; +} +int enter_realmode(u16 seg, u16 off, struct pt_regs *in, struct pt_regs *out) +{ +	/* setup out thin bios emulation */ +	if (bios_setup()) { +		return -1; +	} +	 +	if (realmode_setup()) { +		return -1; +	} +		       	  	in->eip = off;  	in->xcs = seg;  	if (3>(in->esp & 0xffff)) { @@ -59,12 +67,30 @@ int enter_realmode(u16 seg, u16 off, struct pt_regs *in, struct pt_regs *out)  	}  	memcpy(REALMODE_MAILBOX, in, sizeof(struct pt_regs)); +	asm("wbinvd\n");  	__asm__ volatile (   		 "lcall $0x20,%0\n"  : :  "i" (&realmode_enter) ); +	asm("wbinvd\n");  	memcpy(out, REALMODE_MAILBOX, sizeof(struct pt_regs));  	return out->eax;  } + +/* This code is supposed to access a realmode interrupt + * it does currently not work for me */ +int enter_realmode_int(u8 lvl, struct pt_regs *in, struct pt_regs *out) +{ +	/* place two instructions at 0x700 */ +	writeb(0xcd, 0x700);  /* int $lvl */ +	writeb(lvl, 0x701); +	writeb(0xcb, 0x702);  /* lret */ +	asm("wbinvd\n"); +       +	enter_realmode(0x00, 0x700, in, out);	 +	 +	return out->eflags&1; +} + |