summaryrefslogtreecommitdiffstats
path: root/arch/x86/boot/bioscall.S
diff options
context:
space:
mode:
authorJuergen Beisert <jbe@pengutronix.de>2010-01-12 11:15:41 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2010-01-14 10:06:16 +0100
commit7dcc15e8197e647abc80b1d3298a91edd45a8c2d (patch)
treef0bb5981a61c989ce37d40554971b9adc49e2b3e /arch/x86/boot/bioscall.S
parent2bdd75bd02f3d214b285429be72b3a0eab4e9610 (diff)
downloadbarebox-7dcc15e8197e647abc80b1d3298a91edd45a8c2d.tar.gz
barebox-7dcc15e8197e647abc80b1d3298a91edd45a8c2d.tar.xz
Add functions to be able to boot with BIOSs help
These functions are special: They are running in the 16 bit real mode world to bring up barebox on an x86 box. Signed-off-by: Juergen Beisert <jbe@pengutronix.de> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'arch/x86/boot/bioscall.S')
-rw-r--r--arch/x86/boot/bioscall.S99
1 files changed, 99 insertions, 0 deletions
diff --git a/arch/x86/boot/bioscall.S b/arch/x86/boot/bioscall.S
new file mode 100644
index 0000000000..84d2577eb6
--- /dev/null
+++ b/arch/x86/boot/bioscall.S
@@ -0,0 +1,99 @@
+/* -----------------------------------------------------------------------
+ *
+ * Copyright 2009 Intel Corporation; author H. Peter Anvin
+ *
+ * This file is part of the Linux kernel, and is made available under
+ * the terms of the GNU General Public License version 2 or (at your
+ * option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * "Glove box" for BIOS calls. Avoids the constant problems with BIOSes
+ * touching registers they shouldn't be.
+ */
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+ .file "bioscall.S"
+ .code16
+ .section .boot.text.intcall, "ax"
+
+ .globl intcall
+ .type intcall, @function
+intcall:
+ /* Self-modify the INT instruction. Ugly, but works. */
+ cmpb %al, 3f
+ je 1f
+ movb %al, 3f
+ jmp 1f /* Synchronize pipeline */
+1:
+ /* Save state */
+ pushfl
+ pushw %fs
+ pushw %gs
+ pushal
+
+ /* Copy input state to stack frame */
+ subw $44, %sp
+ movw %dx, %si
+ movw %sp, %di
+ movw $11, %cx
+ rep; movsd
+
+ /* Pop full state from the stack */
+ popal
+ popw %gs
+ popw %fs
+ popw %es
+ popw %ds
+ popfl
+
+ /* Actual INT */
+ .byte 0xcd /* INT opcode */
+3: .byte 0
+
+ /* Push full state to the stack */
+ pushfl
+ pushw %ds
+ pushw %es
+ pushw %fs
+ pushw %gs
+ pushal
+
+ /* Re-establish C environment invariants */
+ cld
+ movzwl %sp, %esp
+ movw %cs, %ax
+ movw %ax, %ds
+ movw %ax, %es
+
+ /* Copy output state from stack frame */
+ movw 68(%esp), %di /* Original %cx == 3rd argument */
+ andw %di, %di
+ jz 4f
+ movw %sp, %si
+ movw $11, %cx
+ rep; movsd
+4: addw $44, %sp
+
+ /* Restore state and return */
+ popal
+ popw %gs
+ popw %fs
+ popfl
+ retl
+ .size intcall, .-intcall
+
+/* ------------------------------------------------------------------------ */
+ .code16
+ .section .boot.text.die, "ax"
+
+ .globl die
+ .type die, @function
+die:
+ hlt
+ jmp die
+ .size die, .-die
+
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */