f571dc1af8
Is more portable. Binary is unchanged (verified).
217 lines
4.6 KiB
ArmAsm
217 lines
4.6 KiB
ArmAsm
/*
|
|
* 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
|