diff options
Diffstat (limited to 'sys/arch/i386/stand')
-rw-r--r-- | sys/arch/i386/stand/libsa/gidt.S | 57 |
1 files changed, 44 insertions, 13 deletions
diff --git a/sys/arch/i386/stand/libsa/gidt.S b/sys/arch/i386/stand/libsa/gidt.S index 9fe2d7ac0cb..6ea7e8323d4 100644 --- a/sys/arch/i386/stand/libsa/gidt.S +++ b/sys/arch/i386/stand/libsa/gidt.S @@ -1,4 +1,4 @@ -/* $OpenBSD: gidt.S,v 1.32 2006/12/26 19:30:44 tom Exp $ */ +/* $OpenBSD: gidt.S,v 1.33 2012/10/08 12:46:37 jsing Exp $ */ /* * Copyright (c) 1997 Michael Shalayeff @@ -314,6 +314,10 @@ IEMUENT(44); IEMUENT(45); IEMUENT(46); IEMUENT(47) * entry point for BIOS real-mode interface * all the magic for real-prot mode switching is here * + * Note: Once in real mode access to .data or .bss should be avoided since it + * may not be reachable within the current segment. The following code also + * assumes that .text is writeable. + * * Call: %eax, %ecx, %edx, %ebx, %ebp, %esi, %edi, %es, %ds * Return: %eax, %edx, %ecx, %eflags (as returned from BIOS) * @@ -322,7 +326,7 @@ IEMUENT(44); IEMUENT(45); IEMUENT(46); IEMUENT(47) .align 8, 0x90 EMUh: /* save %eax */ - mov %eax, 3f + mov %eax, 5f pop %eax pusha @@ -334,18 +338,29 @@ EMUh: /* save BIOS int vector */ mov %al, intno + /* Load BIOS registers prior to switching to real mode. */ + movl _C_LABEL(BIOS_regs)+BIOSR_ES, %eax + mov %eax, 7f + movl _C_LABEL(BIOS_regs)+BIOSR_DS, %eax + mov %eax, 6f + prot2real push %ds - addr32 movw (_C_LABEL(BIOS_regs)+(BIOSR_ES) - LINKADDR), %ax - movw %ax, %es - addr32 movw (_C_LABEL(BIOS_regs)+(BIOSR_DS) - LINKADDR), %ax - movw %ax, %ds + # data32 movl $Leax, %eax + .byte 0x66, 0xb8 +7: .long 0x90909090 + mov %ax, %es + + # data32 movl $Leax, %eax + .byte 0x66, 0xb8 +6: .long 0x90909090 + mov %ax, %ds # data32 movl $Leax, %eax .byte 0x66, 0xb8 -3: .long 0x90909090 +5: .long 0x90909090 ;sti int $0 @@ -354,20 +369,36 @@ intno = . - 1 pop %ds - addr32 movl %ebx, (_C_LABEL(BIOS_regs)+(BIOSR_BX) - LINKADDR) - movw %es, %bx - addr32 movw %bx, (_C_LABEL(BIOS_regs)+(BIOSR_ES) - LINKADDR) + /* Preserve BX and ES for protected mode. */ + addr32 movl %eax, (2f - LINKADDR) + movl %ebx, %eax + addr32 movl %eax, (4f - LINKADDR) + movl %es, %eax + addr32 movl %eax, (3f - LINKADDR) + addr32 movl (2f - LINKADDR), %eax + movb %ah, %bh lahf xchgb %ah, %bh + /* Preserve AX for protected mode. */ addr32 movl %eax, (2f - LINKADDR) real2prot # movl $Leax, %eax - .byte 0xb8 -2: .long 0x90909090 + .byte 0xb8 +4: .long 0x90909090 + movl %eax, _C_LABEL(BIOS_regs)+BIOSR_BX + + # movl $Leax, %eax + .byte 0xb8 +3: .long 0x90909090 + movl %eax, _C_LABEL(BIOS_regs)+BIOSR_ES + + # movl $Leax, %eax + .byte 0xb8 +2: .long 0x90909090 /* pass BIOS return values back to caller */ movl %eax, 0xb*4(%esp) @@ -413,6 +444,6 @@ ENTRY(bootbuf) sti /* Jump to buffer */ - ljmp $0x0, $0x7c00 + ljmp $0x0, $0x7c00 .end |