mirror of
				https://git.proxmox.com/git/grub2
				synced 2025-10-30 23:34:47 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			222 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
			
		
		
	
	
			222 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
| /*
 | |
|  *  GRUB  --  GRand Unified Bootloader
 | |
|  *  Copyright (C) 2013  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/>.
 | |
|  */
 | |
| 
 | |
| #include <grub/offsets.h>
 | |
| #include <grub/symbol.h>
 | |
| #include <grub/machine/kernel.h>
 | |
| 
 | |
| /*
 | |
|  * GRUB is called from U-Boot as a Linux Kernel type image, which
 | |
|  * means among other things that it always enters in ARM state.
 | |
|  *
 | |
|  *
 | |
|  * Overview of GRUB image layout:
 | |
|  *
 | |
|  * _start:
 | |
|  *              Entry point (1 ARM branch instruction, to "codestart")
 | |
|  * grub_total_module_size:
 | |
|  *              Data field: Size of included module blob
 | |
|  *              (when generated by grub-mkimage)
 | |
|  * codestart:
 | |
|  *              Remainder of statically-linked executable code and data.
 | |
|  * __bss_start:
 | |
|  *              Start of included module blob.
 | |
|  *              Also where global/static variables are located.
 | |
|  * _end:
 | |
|  *              End of bss region (but not necessarily module blob).
 | |
|  * <stack>:     
 | |
|  * <modules>:
 | |
|  *              Loadable modules, post relocation.
 | |
|  * <heap>:
 | |
|  */
 | |
| 	
 | |
| 	.text
 | |
| 	.arm
 | |
| FUNCTION(_start)
 | |
| 	b	codestart
 | |
| 	
 | |
| 	@ Size of final image integrated module blob - set by grub-mkimage
 | |
| 	.org _start + GRUB_KERNEL_MACHINE_TOTAL_MODULE_SIZE
 | |
| VARIABLE(grub_total_module_size)
 | |
| 	.long 	0
 | |
| 
 | |
| VARIABLE(grub_modbase)
 | |
| 	.long 0
 | |
| bss_start_ptr:
 | |
| 	.long   EXT_C(__bss_start)
 | |
| end_ptr:
 | |
| 	.long   EXT_C(_end)
 | |
| 
 | |
| 	@ Memory map at start:
 | |
| 	@ * text+data
 | |
| 	@ * list relocations
 | |
| 	@ * modules
 | |
| 	@ Before we enter C, we need to apply the relocations
 | |
| 	@ and get following map:
 | |
| 	@ * text+data
 | |
| 	@ * BSS (cleared)
 | |
| 	@ * stack
 | |
| 	@ * modules
 | |
| 	@
 | |
| 	@ To make things easier we ensure
 | |
| 	@ that BSS+stack is larger than list of relocations
 | |
| 	@ by increasing stack if necessarry.
 | |
| 	@ This allows us to always unconditionally copy backwards
 | |
| 	@ Currently list of relocations is ~5K and stack is set
 | |
| 	@ to be at least 256K
 | |
| 
 | |
| FUNCTION(codestart)
 | |
| 	@ Store context: Machine ID, atags/dtb, ...
 | |
| 	@ U-Boot API signature is stored on the U-Boot heap
 | |
| 	@ Stack pointer used as start address for signature probing
 | |
| 	mov	r12, sp
 | |
| 	adr	sp, entry_state
 | |
| 	push	{r1-r12,lr}	@ store U-Boot context (sp in r12)
 | |
| 
 | |
| 	adr     r1, _start
 | |
| 	ldr	r0, bss_start_ptr		@ src
 | |
| 	add     r0, r0, r1
 | |
| 
 | |
| 	add	r0, r0, #(GRUB_KERNEL_MACHINE_MOD_ALIGN - 1)
 | |
| 	mvn	r2, #(GRUB_KERNEL_MACHINE_MOD_ALIGN - 1)
 | |
| 	and	r0, r0, r2
 | |
| 1:	
 | |
|         ldr     r3, [r0], #4  @load next offset
 | |
| 	@ both -2 and -1 are treated the same as we have only one type of relocs
 | |
| 	@ -2 means "end of this type of relocs" and -1 means "end of all relocs"
 | |
|         add     r2, r3, #2
 | |
|         cmp     r2, #1
 | |
|         bls     reloc_done
 | |
| 	@ Adjust next offset
 | |
|         ldr     r2, [r3, r1]
 | |
|         add     r2, r2, r1
 | |
|         str     r2, [r3, r1]
 | |
| 	b 1b
 | |
| 
 | |
| reloc_done:
 | |
| 
 | |
| 	@ Modules have been stored as a blob
 | |
| 	@ they need to be manually relocated to _end
 | |
| 	add	r0, r0, #(GRUB_KERNEL_MACHINE_MOD_ALIGN - 1)
 | |
| 	mvn	r1, #(GRUB_KERNEL_MACHINE_MOD_ALIGN - 1)
 | |
| 	and	r0, r0, r1	@ src = aligned end of relocations
 | |
| 
 | |
| 	ldr	r1, end_ptr		@ dst = End of BSS
 | |
| 	ldr	r2, grub_total_module_size	@ blob size
 | |
| 
 | |
| 	add     r1, r1, #GRUB_KERNEL_MACHINE_STACK_SIZE
 | |
| 	and	r1, r1, #~0x7	@ Ensure 8-byte alignment
 | |
| 	
 | |
| 	sub	sp, r1, #8
 | |
| 	add     r1, r1, #1024
 | |
| 
 | |
| 	str     r1, EXT_C(grub_modbase)
 | |
| 
 | |
| 	add	r1, r1, r2
 | |
| 	add	r0, r0, r2
 | |
| 	sub     r1, r1, #4
 | |
| 	sub     r0, r0, #4
 | |
| 
 | |
| 1:	ldr	r3, [r0], #-4 			@ r3 = *src--
 | |
| 	str	r3, [r1], #-4			@ *dst-- = r3 
 | |
| 	subs	r2, #4				@ remaining -= 4
 | |
| 	bne	1b				@ while remaining != 0
 | |
| 
 | |
| 	@ Since we _are_ the C run-time, we need to manually zero the BSS
 | |
| 	@ region before continuing
 | |
| 	ldr	r0, bss_start_ptr	@ zero from here
 | |
| 	@ If unaligned, bytewise zero until base address aligned.
 | |
| 	mov	r2, #0
 | |
| 1:	tst	r0, #3
 | |
| 	beq	2f
 | |
| 	strb	r2, [r0], #1
 | |
| 	b	1b
 | |
| 2:	ldr	r1, end_ptr		@ to here
 | |
| 1:	str	r2, [r0], #4
 | |
| 	cmp	r0, r1
 | |
| 	bne	1b
 | |
| 	
 | |
| 	b	EXT_C(grub_main)
 | |
| 
 | |
| 	/*
 | |
| 	 * uboot_syscall():
 | |
| 	 *   This function is effectively a veneer, so it cannot
 | |
| 	 *   modify the stack or corrupt any registers other than
 | |
| 	 *   r12 (ip). Furthermore it needs to restore r8 for
 | |
| 	 *   U-Boot (Global Data Pointer) and preserve it for Grub.
 | |
| 	 */
 | |
| FUNCTION(grub_uboot_syscall)
 | |
| 	str     r8, transition_space
 | |
| 	str     lr, transition_space + 4
 | |
| 	str     r9, transition_space + 8
 | |
| 
 | |
| 	ldr	r8, gd_backup
 | |
| 	ldr	r9, gd_backup + 4
 | |
| 
 | |
| 	bl	do_syscall
 | |
| 
 | |
| 	ldr     r8, transition_space
 | |
| 	ldr     lr, transition_space + 4
 | |
| 	ldr     r9, transition_space + 8
 | |
| 
 | |
| 	bx	lr
 | |
| do_syscall:
 | |
| 
 | |
| 	ldr	ip, grub_uboot_syscall_ptr
 | |
| 	bx	ip
 | |
| 	
 | |
| FUNCTION(grub_uboot_return)
 | |
| 	adr	sp, entry_state_end
 | |
| 	pop	{r4-r12, lr}
 | |
| 	mov	sp, r12
 | |
| 	bx	lr
 | |
| 
 | |
| 	
 | |
| 	.align	3
 | |
| @ U-boot context stack space
 | |
| entry_state_end:
 | |
| VARIABLE(grub_uboot_machine_type)
 | |
| 	.long	0	@ r1
 | |
| VARIABLE(grub_uboot_boot_data)
 | |
| 	.long	0	@ r2
 | |
| 	.long	0	@ r3
 | |
| 	.long	0	@ r4
 | |
| 	.long	0	@ r5
 | |
| 	.long	0	@ r6
 | |
| 	.long	0	@ r7
 | |
| gd_backup:	
 | |
| 	.long	0	@ r8 - U-Boot global data pointer up to 2013-09-21
 | |
| 	.long	0	@ r9 - U-Boot global data pointer 2013-09-21 onwards
 | |
| 	.long	0	@ r10
 | |
| 	.long	0	@ r11
 | |
| VARIABLE(grub_uboot_search_hint)@ U-Boot stack pointer - 
 | |
| 	.long	0	@ also API signature address hint.
 | |
| 	.long	0	@ lr
 | |
| entry_state:		@ backup for U-Boot context
 | |
| 
 | |
| @ GRUB context stack space
 | |
| transition_space:	
 | |
| 	.long	0	@ r8
 | |
| 	.long	0	@ lr
 | |
| 	.long	0	@ r9
 | |
| 
 | |
| VARIABLE(grub_uboot_syscall_ptr)
 | |
| 	.long	0	@
 | |
| 
 | |
| 	END
 | 
