summaryrefslogtreecommitdiffstats
path: root/grub-core/kern/i386/pc/startup.S
diff options
context:
space:
mode:
Diffstat (limited to 'grub-core/kern/i386/pc/startup.S')
-rw-r--r--grub-core/kern/i386/pc/startup.S217
1 files changed, 217 insertions, 0 deletions
diff --git a/grub-core/kern/i386/pc/startup.S b/grub-core/kern/i386/pc/startup.S
new file mode 100644
index 0000000..b8a9b33
--- /dev/null
+++ b/grub-core/kern/i386/pc/startup.S
@@ -0,0 +1,217 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 1999,2000,2001,2002,2003,2005,2006,2007,2008,2009,2011 Free Software Foundation, Inc.
+ *
+ * GRUB 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+/*
+ * Note: These functions defined in this file may be called from C.
+ * Be careful of that you must not modify some registers. Quote
+ * from gcc-2.95.2/gcc/config/i386/i386.h:
+
+ 1 for registers not available across function calls.
+ These must include the FIXED_REGISTERS and also any
+ registers that can be used without being saved.
+ The latter must include the registers where values are returned
+ and the register where structure-value addresses are passed.
+ Aside from that, you can include as many other registers as you like.
+
+ ax,dx,cx,bx,si,di,bp,sp,st,st1,st2,st3,st4,st5,st6,st7,arg
+{ 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }
+ */
+
+/*
+ * Note: GRUB is compiled with the options -mrtd and -mregparm=3.
+ * So the first three arguments are passed in %eax, %edx, and %ecx,
+ * respectively, and if a function has a fixed number of arguments
+ * and the number is greater than three, the function must return
+ * with "ret $N" where N is ((the number of arguments) - 3) * 4.
+ */
+
+#include <config.h>
+#include <grub/symbol.h>
+#include <multiboot.h>
+#ifdef __APPLE__
+#include <grub/i386/pc/memory.h>
+#endif
+
+ .file "startup.S"
+
+ .text
+
+ .globl start, _start, __start
+start:
+_start:
+__start:
+#ifdef __APPLE__
+LOCAL(start):
+#endif
+ .code32
+
+ movl %ecx, (LOCAL(real_to_prot_addr) - _start) (%esi)
+ movl %edi, (LOCAL(prot_to_real_addr) - _start) (%esi)
+ movl %eax, (EXT_C(grub_realidt) - _start) (%esi)
+
+ /* copy back the decompressed part (except the modules) */
+#ifdef __APPLE__
+ movl $EXT_C(_edata), %ecx
+ subl $LOCAL(start), %ecx
+#else
+ movl $(_edata - _start), %ecx
+#endif
+ movl $(_start), %edi
+ rep
+ movsb
+
+ movl $LOCAL (cont), %esi
+ jmp *%esi
+LOCAL(cont):
+
+#if 0
+ /* copy modules before cleaning out the bss */
+ movl EXT_C(grub_total_module_size), %ecx
+ movl EXT_C(grub_kernel_image_size), %esi
+ addl %ecx, %esi
+ addl $_start, %esi
+ decl %esi
+ movl $END_SYMBOL, %edi
+ addl %ecx, %edi
+ decl %edi
+ std
+ rep
+ movsb
+#endif
+
+#ifdef __APPLE__
+ /* clean out the bss */
+ movl $EXT_C(_edata), %edi
+
+ /* compute the bss length */
+ movl $GRUB_MEMORY_MACHINE_SCRATCH_ADDR, %ecx
+#else
+ /* clean out the bss */
+ movl $BSS_START_SYMBOL, %edi
+
+ /* compute the bss length */
+ movl $END_SYMBOL, %ecx
+#endif
+ subl %edi, %ecx
+
+ /* clean out */
+ xorl %eax, %eax
+ cld
+ rep
+ stosb
+
+ movl %edx, EXT_C(grub_boot_device)
+
+ /*
+ * Call the start of main body of C code.
+ */
+ call EXT_C(grub_main)
+
+LOCAL(real_to_prot_addr):
+ .long 0
+LOCAL(prot_to_real_addr):
+ .long 0
+
+ .macro PROT_TO_REAL
+ movl LOCAL(prot_to_real_addr), %eax
+ call *%eax
+ .endm
+
+ .macro REAL_TO_PROT
+ movl LOCAL(real_to_prot_addr), %eax
+ calll *%eax
+ .endm
+
+/*
+ * grub_exit()
+ *
+ * Exit the system.
+ */
+FUNCTION(grub_exit)
+ PROT_TO_REAL
+ .code16
+ /* Tell the BIOS a boot failure. If this does not work, reboot. */
+ int $0x18
+ /* set 0x472 to 0x0000 for cold boot (0x1234 for warm boot) */
+ xorw %ax, %ax
+ movw $0x0472, %di
+ movw %ax, (%di)
+ ljmp $0xf000, $0xfff0
+ .code32
+
+/*
+ * int grub_pxe_call (int func, void* data, grub_uint32_t pxe_rm_entry);
+ */
+FUNCTION(grub_pxe_call)
+ pushl %ebp
+ movl %esp, %ebp
+ pushl %esi
+ pushl %edi
+ pushl %ebx
+
+ movl %ecx, %ebx
+ movl %eax, %ecx
+ movl %edx, %eax
+ andl $0xF, %eax
+ shrl $4, %edx
+ shll $16, %edx
+ addl %eax, %edx
+
+ PROT_TO_REAL
+ .code16
+
+ pushl %ebx
+ pushl %edx
+ pushw %cx
+ movw %sp, %bx
+ lcall *%ss:6(%bx)
+ cld
+ addw $10, %sp
+ movw %ax, %cx
+
+ REAL_TO_PROT
+ .code32
+
+ movzwl %cx, %eax
+
+ popl %ebx
+ popl %edi
+ popl %esi
+ popl %ebp
+ ret
+
+#include "../int.S"
+
+VARIABLE(grub_realidt)
+ .long 0
+
+#ifdef __APPLE__
+ /* Older versions of objconv assume that there is the same number
+ of text and data sections. Hence this dummy. */
+ .section __TEXT, __zz_dummy
+ .byte 0
+ .globl EXT_C(_edata)
+ .globl EXT_C(grub_boot_device)
+ .zerofill __DATA, __aa_before_bss, EXT_C(_edata), 1, 0
+ .zerofill __DATA, __bss, EXT_C(grub_boot_device), 4, 2
+#else
+ .bss
+VARIABLE(grub_boot_device)
+ .long 0
+#endif