grub/grub-core/kern/arm/uboot/startup.S

189 lines
4.7 KiB
ArmAsm
Raw Normal View History

2013-04-07 00:41:07 +00:00
/*
* 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>:
2013-04-07 00:41:07 +00:00
* <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
2013-04-07 00:41:07 +00:00
VARIABLE(grub_total_module_size)
.long 0
VARIABLE(grub_uboot_machine_type)
.long 0
VARIABLE(grub_uboot_boot_data)
.long 0
VARIABLE(grub_modbase)
.long 0
bss_start_ptr:
.long EXT_C(__bss_start)
end_ptr:
.long EXT_C(_end)
2013-04-07 00:41:07 +00:00
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
2013-04-07 00:41:07 +00:00
push {r4-r12,lr} @ store U-Boot context (sp in r12)
str r1, EXT_C(grub_uboot_machine_type)
str r2, EXT_C(grub_uboot_boot_data)
2013-04-07 00:41:07 +00:00
@ Modules have been stored as a blob in BSS,
@ they need to be manually relocated to _end
ldr r0, bss_start_ptr @ src
2013-04-12 14:50:58 +00:00
add r0, r0, #(GRUB_KERNEL_MACHINE_MOD_ALIGN - 1)
mvn r1, #(GRUB_KERNEL_MACHINE_MOD_ALIGN - 1)
and r0, r0, r1
ldr r1, end_ptr @ dst = End of BSS
2013-04-07 00:41:07 +00:00
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
2013-04-12 14:50:58 +00:00
str r1, EXT_C(grub_modbase)
2013-04-12 14:50:58 +00:00
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
2013-04-07 00:41:07 +00:00
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
2013-05-16 14:30:41 +00:00
@ If unaligned, bytewise zero until base address aligned.
2013-04-07 00:41:07 +00:00
mov r2, #0
2013-05-16 14:30:41 +00:00
1: tst r0, #3
beq 2f
strb r2, [r0], #1
b 1b
2: ldr r1, end_ptr @ to here
2013-04-07 00:41:07 +00:00
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.
*/
2013-05-03 13:07:39 +00:00
FUNCTION(grub_uboot_syscall)
str r8, transition_space
str lr, transition_space + 4
str r9, transition_space + 8
str sp, transition_space + 12
sub sp, sp, #0x20
lsr sp, sp, #3
lsl sp, sp, #3
ldr r8, gd_backup
ldr r9, gd_backup + 4
2013-04-07 00:41:07 +00:00
mov lr, pc
ldr pc, grub_uboot_syscall_ptr
str r8, gd_backup
ldr r8, transition_space
ldr lr, transition_space + 4
ldr r9, transition_space + 8
ldr sp, transition_space + 12
2013-04-07 00:41:07 +00:00
bx lr
2013-05-03 13:07:39 +00:00
FUNCTION(grub_uboot_return)
adr sp, entry_state_end
2013-04-07 00:41:07 +00:00
pop {r4-r12, lr}
mov sp, r12
bx lr
.align 3
2013-04-07 00:41:07 +00:00
@ U-boot context stack space
entry_state_end:
2013-04-07 00:41:07 +00:00
.long 0 @ r4
.long 0 @ r5
.long 0 @ r6
.long 0 @ r7
gd_backup:
.long 0 @ r8 - U-Boot global data pointer
.long 0 @ r9
.long 0 @ r10
.long 0 @ r11
2013-05-03 13:07:39 +00:00
VARIABLE(grub_uboot_search_hint)@ U-Boot stack pointer -
2013-04-07 00:41:07 +00:00
.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
.long 0 @ sp
2013-04-07 00:41:07 +00:00
2013-05-03 13:07:39 +00:00
VARIABLE(grub_uboot_syscall_ptr)
2013-04-07 00:41:07 +00:00
.long 0 @
END