summaryrefslogtreecommitdiffstats
path: root/arch/x86/bios
diff options
context:
space:
mode:
authorJean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>2017-02-15 20:34:14 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2017-02-24 08:21:33 +0100
commit64db2d497ca4e1db7be08e303c17ed92c99af897 (patch)
tree88d8f73af13cde50766d00ea7919885145f3c218 /arch/x86/bios
parentc3931154de674962db4a633794ec9dcd3f9d4fef (diff)
downloadbarebox-64db2d497ca4e1db7be08e303c17ed92c99af897.tar.gz
barebox-64db2d497ca4e1db7be08e303c17ed92c99af897.tar.xz
x86: move bios bootup code to arch/x86/bios
Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'arch/x86/bios')
-rw-r--r--arch/x86/bios/Makefile3
-rw-r--r--arch/x86/bios/bios_disk.S70
-rw-r--r--arch/x86/bios/memory16.S67
-rw-r--r--arch/x86/bios/traveler.S179
4 files changed, 319 insertions, 0 deletions
diff --git a/arch/x86/bios/Makefile b/arch/x86/bios/Makefile
new file mode 100644
index 0000000000..414ee42a4a
--- /dev/null
+++ b/arch/x86/bios/Makefile
@@ -0,0 +1,3 @@
+obj-y += memory16.o
+obj-y += traveler.o
+obj-y += bios_disk.o
diff --git a/arch/x86/bios/bios_disk.S b/arch/x86/bios/bios_disk.S
new file mode 100644
index 0000000000..cce33e67af
--- /dev/null
+++ b/arch/x86/bios/bios_disk.S
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2009 Juergen Beisert, Pengutronix
+ *
+ * Mostly stolen from the GRUB2 project
+ * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ *
+ */
+
+/**
+ * @file
+ * @brief Do BIOS calls to load or save data from disks
+ *
+ * @note These functions are running in flat and real mode. Due to some
+ * other restrictions these routines must running from an address
+ * space below 0x10000
+ */
+
+/*
+ * int bios_disk_rw_int13_extensions (int ah, int drive, void *dap)
+ *
+ * Call IBM/MS INT13 Extensions (int 13 %ah=AH) for DRIVE. DAP
+ * is passed for disk address packet. If an error occurs, return
+ * non-zero, otherwise zero.
+ */
+ .section .boot.text.bios_disk_rw_int13_extensions, "ax"
+ .code32
+ .globl bios_disk_rw_int13_extensions
+ .type bios_disk_rw_int13_extensions, @function
+
+ .extern prot_to_real
+ .extern real_to_prot
+
+bios_disk_rw_int13_extensions:
+ pushl %ebp
+ pushl %esi
+
+ /* compute the address of disk_address_packet */
+ movw %cx, %si
+ xorw %cx, %cx
+ shrl $4, %ecx /* save the segment to cx */
+
+ movb %al, %dh
+ call prot_to_real /* enter real mode right now */
+
+ .code16
+ movb %dh, %ah
+ movw %cx, %ds
+ int $0x13 /* do the operation */
+ movb %ah, %dl /* save return value */
+ /* back to protected mode */
+ DATA32 call real_to_prot
+
+ .code32
+ movb %dl, %al /* return value in %eax */
+
+ popl %esi
+ popl %ebp
+
+ ret
diff --git a/arch/x86/bios/memory16.S b/arch/x86/bios/memory16.S
new file mode 100644
index 0000000000..76ee72b56c
--- /dev/null
+++ b/arch/x86/bios/memory16.S
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2009 Juergen Beisert, Pengutronix
+ *
+ * This code was inspired by the GRUB2 project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ *
+ */
+
+/**
+ * @file
+ * @brief Query the memory layout information from the BIOS
+ *
+ * Note: This function is running in flat and real mode. Due to some
+ * other restrictions it must running from an address space below 0x10000
+ */
+
+/**
+ * @fn unsigned short bios_get_memsize(void)
+ * @brief Does a BIOS call "INT 15H, AH=88H" to get extended memory size
+ * @return Extended memory size in KB
+ *
+ * @note This call is limited to 64 MiB. So, if the system provides more than
+ * 64 MiB of memory, still 64 MiB are reported.
+ *
+ */
+
+
+ .section .boot.text.bios_get_memsize, "ax"
+ .code32
+ .globl bios_get_memsize
+ .type bios_get_memsize, @function
+
+ .extern prot_to_real
+
+bios_get_memsize:
+
+ pushl %ebp
+
+ call prot_to_real /* enter real mode */
+ .code16
+
+ movb $0x88, %ah
+ int $0x15
+
+ movw %ax, %dx
+
+ DATA32 call real_to_prot
+
+ .code32
+
+ movw %dx, %ax
+
+ popl %ebp
+ ret
+
+ .size bios_get_memsize, .-bios_get_memsize
+
diff --git a/arch/x86/bios/traveler.S b/arch/x86/bios/traveler.S
new file mode 100644
index 0000000000..113b19802e
--- /dev/null
+++ b/arch/x86/bios/traveler.S
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2009 Juergen Beisert, Pengutronix
+ *
+ * Mostly stolen from the GRUB2 project
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ *
+ */
+
+/**
+ * @file
+ * @brief Switch from the flat mode world into the real mode world and vice versa
+ *
+ * Note: These functions are *called* and return in a different operating mode
+ */
+
+/**
+ * @fn void real_to_prot(void)
+ * @brief Switch from temp. real mode back to flat mode
+ *
+ * Called from a 32 bit flat mode segment and returns into a 16 bit segment
+ */
+
+/**
+ * @fn void prot_to_real(void)
+ * @brief Switch from flat mode to real mode
+ *
+ * Called from a 16 bit real mode segment and returns into a 32 bit segment
+ */
+
+#include <asm/modes.h>
+
+ .file "walkyrie.S"
+
+/* keep the current flat mode stack pointer, while playing in real mode */
+ .section .boot.data.protstack
+ .code32
+protstack: .long 4
+/* temp. store */
+return_addr: .long 4
+
+
+ .section .boot.text.real_to_prot, "ax"
+ .code16
+ .globl real_to_prot
+ .type real_to_prot, @function
+
+/* Note: This routine should not change any other standard registers than eax */
+real_to_prot:
+ /*
+ * Always disable the interrupts, when returning to flat mode
+ */
+ cli
+
+ /* turn on protected mode */
+ movl %cr0, %eax
+ orl $0x00000001, %eax
+ movl %eax, %cr0
+
+ /* jump to relocation, flush prefetch queue, and reload %cs */
+ DATA32 ljmp $__BOOT_CS, $return_to_flatmode
+ .size real_to_prot, .-real_to_prot
+
+/* ----------------------------------------------------------------------- */
+ .section .boot.text.return_to_flatmode, "ax"
+ .type return_to_flatmode, @function
+ .code32
+
+return_to_flatmode:
+ /* reload other segment registers */
+ movw $__BOOT_DS, %ax
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %fs
+ movw %ax, %gs
+ movw %ax, %ss
+
+ /* move the return address from the real mode to the flat mode stack */
+ movl (%esp), %eax
+ movl %eax, return_addr
+
+ /* setup again the flat mode stack */
+ movl protstack, %eax
+ movl %eax, %esp
+ movl %eax, %ebp
+
+ movl return_addr, %eax
+ movl %eax, (%esp)
+
+ /* flag we returned happy here */
+ xorl %eax, %eax
+ ret
+ .size return_to_flatmode, .-return_to_flatmode
+
+/* ------------------------------------------------------------------------ */
+
+/* Note: This routine should not change any other standard registers than eax */
+
+ .section .boot.text.prot_to_real, "ax"
+ .globl prot_to_real
+ .type prot_to_real, @function
+ .extern boot_stack
+ .code32
+
+prot_to_real:
+ /* save the protected mode stack */
+ movl %esp, %eax
+ movl %eax, protstack
+
+ /* prepare the real mode stack */
+ /* - address to call to the top of this stack */
+ movl (%esp), %eax
+ movl %eax, boot_stack - 4
+
+ /* - the stack itself */
+ movl $boot_stack - 4, %eax
+ movl %eax, %esp
+ movl %eax, %ebp
+
+ /* prepare segments limits to 16 bit */
+ movw $__REAL_DS, %ax
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %fs
+ movw %ax, %gs
+ movw %ax, %ss
+
+ /* at last, also limit the code segment to 16 bit */
+ ljmp $__REAL_CS, $return_to_realmode
+ .size prot_to_real, .-prot_to_real
+
+/* ----------------------------------------------------------------------- */
+
+ .section .boot.text.return_to_realmode, "ax"
+ .globl return_to_realmode
+ .type return_to_realmode, @function
+ .code16
+
+return_to_realmode:
+ /* disable protected mode */
+ movl %cr0, %eax
+ andl $(~0x00000001), %eax
+ movl %eax, %cr0
+
+ /*
+ * all the protected mode settings are still cached in the CPU.
+ * Refresh them by re-loading all registers in realmode
+ * Start with the CS, continue with the data registers
+ */
+ ljmp $0, $enter_realmode
+
+enter_realmode:
+ xorl %eax, %eax
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %fs
+ movw %ax, %gs
+ movw %ax, %ss
+ /*
+ * back in plain real mode now, we can play again with the BIOS
+ */
+
+ /* restore interrupts */
+ sti
+
+ /* return on realmode stack! */
+ DATA32 ret
+
+ .size return_to_realmode, .-return_to_realmode
+