summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjsing <jsing@openbsd.org>2012-10-08 12:46:37 +0000
committerjsing <jsing@openbsd.org>2012-10-08 12:46:37 +0000
commitd3dce53481564a033ea84598afe3624143018f99 (patch)
treeebd109fef92a48f936129f342a0aac4b1127b020
parentupdate to 1.2.4 (diff)
downloadwireguard-openbsd-d3dce53481564a033ea84598afe3624143018f99.tar.xz
wireguard-openbsd-d3dce53481564a033ea84598afe3624143018f99.zip
Avoid accessing .data or .bss from real mode, since they may not be within
the current segment. Load and store the necessary BIOS registers from protected mode, preserving the register values across the real mode and protected mode switches by directly patching instructions. This allows for boot(8) to be larger than 64KB.
-rw-r--r--sys/arch/amd64/stand/libsa/gidt.S57
-rw-r--r--sys/arch/i386/stand/libsa/gidt.S57
2 files changed, 88 insertions, 26 deletions
diff --git a/sys/arch/amd64/stand/libsa/gidt.S b/sys/arch/amd64/stand/libsa/gidt.S
index 04aab9828b9..325433b45dc 100644
--- a/sys/arch/amd64/stand/libsa/gidt.S
+++ b/sys/arch/amd64/stand/libsa/gidt.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: gidt.S,v 1.6 2006/12/29 11:44:01 tom Exp $ */
+/* $OpenBSD: gidt.S,v 1.7 2012/10/08 12:46:37 jsing Exp $ */
/*
* Copyright (c) 1997 Michael Shalayeff
@@ -312,6 +312,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)
*
@@ -320,7 +324,7 @@ IEMUENT(44); IEMUENT(45); IEMUENT(46); IEMUENT(47)
.align 8, 0x90
EMUh:
/* save %eax */
- mov %eax, 3f
+ mov %eax, 5f
pop %eax
pusha
@@ -332,18 +336,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
@@ -352,20 +367,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)
@@ -411,6 +442,6 @@ ENTRY(bootbuf)
sti
/* Jump to buffer */
- ljmp $0x0, $0x7c00
+ ljmp $0x0, $0x7c00
.end
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