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
 | |
| 	DATA32	call	*%ax
 | |
| 	.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
 |