2N/A/*
2N/A * GRUB -- GRand Unified Bootloader
2N/A * Copyright (C) 1999,2000,2001,2002,2003,2005,2006,2007,2008,2009,2011 Free Software Foundation, Inc.
2N/A *
2N/A * GRUB is free software: you can redistribute it and/or modify
2N/A * it under the terms of the GNU General Public License as published by
2N/A * the Free Software Foundation, either version 3 of the License, or
2N/A * (at your option) any later version.
2N/A *
2N/A * GRUB is distributed in the hope that it will be useful,
2N/A * but WITHOUT ANY WARRANTY; without even the implied warranty of
2N/A * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2N/A * GNU General Public License for more details.
2N/A *
2N/A * You should have received a copy of the GNU General Public License
2N/A * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
2N/A */
2N/A
2N/A
2N/A/*
2N/A * Note: These functions defined in this file may be called from C.
2N/A * Be careful of that you must not modify some registers. Quote
2N/A * from gcc-2.95.2/gcc/config/i386/i386.h:
2N/A
2N/A 1 for registers not available across function calls.
2N/A These must include the FIXED_REGISTERS and also any
2N/A registers that can be used without being saved.
2N/A The latter must include the registers where values are returned
2N/A and the register where structure-value addresses are passed.
2N/A Aside from that, you can include as many other registers as you like.
2N/A
2N/A ax,dx,cx,bx,si,di,bp,sp,st,st1,st2,st3,st4,st5,st6,st7,arg
2N/A{ 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }
2N/A */
2N/A
2N/A/*
2N/A * Note: GRUB is compiled with the options -mrtd and -mregparm=3.
2N/A * So the first three arguments are passed in %eax, %edx, and %ecx,
2N/A * respectively, and if a function has a fixed number of arguments
2N/A * and the number is greater than three, the function must return
2N/A * with "ret $N" where N is ((the number of arguments) - 3) * 4.
2N/A */
2N/A
2N/A#include <config.h>
2N/A#include <grub/symbol.h>
2N/A#include <multiboot.h>
2N/A
2N/A .file "startup.S"
2N/A
2N/A .text
2N/A
2N/A .globl start, _start
2N/Astart:
2N/A_start:
2N/A .code32
2N/A
2N/A movl %ecx, (LOCAL(real_to_prot_addr) - _start) (%esi)
2N/A movl %edi, (LOCAL(prot_to_real_addr) - _start) (%esi)
2N/A
2N/A /* copy back the decompressed part (except the modules) */
2N/A movl $(_edata - _start), %ecx
2N/A movl $(_start), %edi
2N/A rep
2N/A movsb
2N/A
2N/A movl $LOCAL (cont), %esi
2N/A jmp *%esi
2N/ALOCAL(cont):
2N/A
2N/A#if 0
2N/A /* copy modules before cleaning out the bss */
2N/A movl EXT_C(grub_total_module_size), %ecx
2N/A movl EXT_C(grub_kernel_image_size), %esi
2N/A addl %ecx, %esi
2N/A addl $_start, %esi
2N/A decl %esi
2N/A movl $END_SYMBOL, %edi
2N/A addl %ecx, %edi
2N/A decl %edi
2N/A std
2N/A rep
2N/A movsb
2N/A#endif
2N/A
2N/A /* clean out the bss */
2N/A movl $BSS_START_SYMBOL, %edi
2N/A
2N/A /* compute the bss length */
2N/A movl $END_SYMBOL, %ecx
2N/A subl %edi, %ecx
2N/A
2N/A /* clean out */
2N/A xorl %eax, %eax
2N/A cld
2N/A rep
2N/A stosb
2N/A
2N/A movl %edx, EXT_C(grub_boot_device)
2N/A
2N/A /*
2N/A * Call the start of main body of C code.
2N/A */
2N/A call EXT_C(grub_main)
2N/A
2N/ALOCAL(real_to_prot_addr):
2N/A .long 0
2N/ALOCAL(prot_to_real_addr):
2N/A .long 0
2N/A
2N/A .macro PROT_TO_REAL
2N/A movl LOCAL(prot_to_real_addr), %eax
2N/A call *%eax
2N/A .endm
2N/A
2N/A .macro REAL_TO_PROT
2N/A movl LOCAL(real_to_prot_addr), %eax
2N/A DATA32 call *%ax
2N/A .endm
2N/A
2N/A/*
2N/A * grub_exit()
2N/A *
2N/A * Exit the system.
2N/A */
2N/AFUNCTION(grub_exit)
2N/A PROT_TO_REAL
2N/A .code16
2N/A /* Tell the BIOS a boot failure. If this does not work, reboot. */
2N/A int $0x18
2N/A /* set 0x472 to 0x0000 for cold boot (0x1234 for warm boot) */
2N/A xorw %ax, %ax
2N/A movw $0x0472, %di
2N/A movw %ax, (%di)
2N/A ljmp $0xf000, $0xfff0
2N/A .code32
2N/A
2N/A/*
2N/A * int grub_pxe_call (int func, void* data, grub_uint32_t pxe_rm_entry);
2N/A */
2N/AFUNCTION(grub_pxe_call)
2N/A pushl %ebp
2N/A movl %esp, %ebp
2N/A pushl %esi
2N/A pushl %edi
2N/A pushl %ebx
2N/A
2N/A movl %ecx, %ebx
2N/A movl %eax, %ecx
2N/A movl %edx, %eax
2N/A andl $0xF, %eax
2N/A shrl $4, %edx
2N/A shll $16, %edx
2N/A addl %eax, %edx
2N/A
2N/A PROT_TO_REAL
2N/A .code16
2N/A
2N/A pushl %ebx
2N/A pushl %edx
2N/A pushw %cx
2N/A movw %sp, %bx
2N/A lcall *%ss:6(%bx)
2N/A cld
2N/A addw $10, %sp
2N/A movw %ax, %cx
2N/A
2N/A REAL_TO_PROT
2N/A .code32
2N/A
2N/A movzwl %cx, %eax
2N/A
2N/A popl %ebx
2N/A popl %edi
2N/A popl %esi
2N/A popl %ebp
2N/A ret
2N/A
2N/A#include "../int.S"
2N/A
2N/A .bss
2N/AVARIABLE(grub_boot_device)
2N/A .long 0