From 64db2d497ca4e1db7be08e303c17ed92c99af897 Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Wed, 15 Feb 2017 20:34:14 +0100 Subject: x86: move bios bootup code to arch/x86/bios Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Signed-off-by: Sascha Hauer --- arch/x86/Makefile | 1 + arch/x86/bios/Makefile | 3 + arch/x86/bios/bios_disk.S | 70 ++++++++++++++++++ arch/x86/bios/memory16.S | 67 +++++++++++++++++ arch/x86/bios/traveler.S | 179 ++++++++++++++++++++++++++++++++++++++++++++++ arch/x86/lib/Makefile | 3 - arch/x86/lib/bios_disk.S | 70 ------------------ arch/x86/lib/memory16.S | 67 ----------------- arch/x86/lib/traveler.S | 179 ---------------------------------------------- 9 files changed, 320 insertions(+), 319 deletions(-) create mode 100644 arch/x86/bios/Makefile create mode 100644 arch/x86/bios/bios_disk.S create mode 100644 arch/x86/bios/memory16.S create mode 100644 arch/x86/bios/traveler.S delete mode 100644 arch/x86/lib/bios_disk.S delete mode 100644 arch/x86/lib/memory16.S delete mode 100644 arch/x86/lib/traveler.S (limited to 'arch/x86') diff --git a/arch/x86/Makefile b/arch/x86/Makefile index da17d70bdc..640c24b62a 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -40,6 +40,7 @@ endif common-y += $(BOARD) $(MACH) common-y += arch/x86/lib/ common-y += arch/x86/boot/ +common-$(CONFIG_X86_BIOS_BRINGUP) += arch/x86/bios/ # arch/x86/cpu/ 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 + + .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 + diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index b67629f115..6054b9e3f3 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile @@ -3,7 +3,4 @@ obj-y += memory.o obj-y += gdt.o # needed, when running via a 16 bit BIOS -obj-$(CONFIG_X86_BIOS_BRINGUP) += memory16.o -obj-$(CONFIG_X86_BIOS_BRINGUP) += traveler.o -obj-$(CONFIG_X86_BIOS_BRINGUP) += bios_disk.o obj-$(CONFIG_CMD_LINUX16) += linux_start.o diff --git a/arch/x86/lib/bios_disk.S b/arch/x86/lib/bios_disk.S deleted file mode 100644 index cce33e67af..0000000000 --- a/arch/x86/lib/bios_disk.S +++ /dev/null @@ -1,70 +0,0 @@ -/* - * 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/lib/memory16.S b/arch/x86/lib/memory16.S deleted file mode 100644 index 76ee72b56c..0000000000 --- a/arch/x86/lib/memory16.S +++ /dev/null @@ -1,67 +0,0 @@ -/* - * 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/lib/traveler.S b/arch/x86/lib/traveler.S deleted file mode 100644 index 113b19802e..0000000000 --- a/arch/x86/lib/traveler.S +++ /dev/null @@ -1,179 +0,0 @@ -/* - * 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 - - .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 - -- cgit v1.2.3