summaryrefslogtreecommitdiff
path: root/sys/arch/i386/stand
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch/i386/stand')
-rw-r--r--sys/arch/i386/stand/libsa/gidt.S57
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