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).
|
|
|
|
* <overflow>:
|
|
|
|
* Any part of the module blob that extends beyond _end.
|
|
|
|
* <modules>:
|
|
|
|
* Loadable modules, post relocation.
|
|
|
|
* <stack>:
|
|
|
|
* <heap>:
|
|
|
|
*/
|
|
|
|
|
|
|
|
.text
|
|
|
|
.arm
|
|
|
|
FUNCTION(_start)
|
|
|
|
b codestart
|
|
|
|
|
|
|
|
@ Size of final image integrated module blob - set by grub-mkimage
|
|
|
|
. = _start + GRUB_KERNEL_MACHINE_TOTAL_MODULE_SIZE
|
|
|
|
VARIABLE(grub_total_module_size)
|
|
|
|
.long 0
|
|
|
|
|
|
|
|
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
|
|
|
|
ldr sp, =entry_state
|
|
|
|
push {r4-r12,lr} @ store U-Boot context (sp in r12)
|
|
|
|
|
2013-04-12 14:50:58 +00:00
|
|
|
ldr r12, =EXT_C(uboot_machine_type)
|
|
|
|
str r1, [r12]
|
|
|
|
ldr r12, =EXT_C(uboot_boot_data)
|
|
|
|
str r2, [r12]
|
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 or
|
|
|
|
@ (__bss_start + grub_total_module_size), whichever greater.
|
2013-04-12 14:50:58 +00:00
|
|
|
ldr r0, =EXT_C(__bss_start) @ src
|
|
|
|
add r0, r0, #(GRUB_KERNEL_MACHINE_MOD_ALIGN - 1)
|
|
|
|
mvn r1, #(GRUB_KERNEL_MACHINE_MOD_ALIGN - 1)
|
|
|
|
and r0, r0, r1
|
|
|
|
|
2013-04-07 00:41:07 +00:00
|
|
|
ldr r1, =EXT_C(_end) @ dst = End of BSS
|
|
|
|
ldr r2, grub_total_module_size @ blob size
|
|
|
|
add r3, r0, r2 @ blob end
|
|
|
|
cmp r1, r3 @ _end < blob end?
|
|
|
|
movlt r1, r3 @ dst = blob end + blob size
|
2013-04-12 14:50:58 +00:00
|
|
|
|
|
|
|
ldr r12, =EXT_C(grub_modbase)
|
|
|
|
str r1, [r12]
|
|
|
|
|
2013-04-07 00:41:07 +00:00
|
|
|
1: ldr r3, [r0], #4 @ r3 = *src++
|
|
|
|
str r3, [r1], #4 @ *dst++ = r3
|
|
|
|
subs r2, #4 @ remaining -= 4
|
|
|
|
bne 1b @ while remaining != 0
|
|
|
|
|
|
|
|
@ Set up a new stack, beyond the end of copied modules.
|
|
|
|
ldr r3, =GRUB_KERNEL_MACHINE_STACK_SIZE
|
|
|
|
add r3, r1, r3 @ Place stack beyond end of modules
|
|
|
|
and sp, r3, #~0x7 @ Ensure 8-byte alignment
|
|
|
|
|
|
|
|
@ Since we _are_ the C run-time, we need to manually zero the BSS
|
|
|
|
@ region before continuing
|
2013-04-12 14:50:58 +00:00
|
|
|
ldr r0, =EXT_C(__bss_start) @ zero from here
|
2013-04-07 00:41:07 +00:00
|
|
|
ldr r1, =EXT_C(_end) @ to here
|
|
|
|
mov r2, #0
|
|
|
|
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(uboot_syscall)
|
|
|
|
ldr ip, =transition_space
|
|
|
|
stm ip, {r8, lr}
|
|
|
|
ldr ip, =gd_backup
|
|
|
|
ldr r8, [ip]
|
|
|
|
ldr ip, =uboot_syscall_ptr
|
|
|
|
mov lr, pc
|
|
|
|
ldr pc, [ip]
|
|
|
|
ldr ip, =gd_backup
|
|
|
|
str r8, [ip]
|
|
|
|
ldr ip, =transition_space
|
|
|
|
ldm ip, {r8, lr}
|
|
|
|
bx lr
|
|
|
|
|
|
|
|
FUNCTION(uboot_return)
|
|
|
|
ldr sp, =entry_state_end
|
|
|
|
pop {r4-r12, lr}
|
|
|
|
mov sp, r12
|
|
|
|
bx lr
|
|
|
|
|
|
|
|
|
|
|
|
.data
|
|
|
|
.align 3 @ 8-byte alignment for stack
|
|
|
|
@ U-boot context stack space
|
|
|
|
entry_state_end:
|
|
|
|
.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
|
|
|
|
VARIABLE(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
|
|
|
|
|
|
|
|
VARIABLE(uboot_syscall_ptr)
|
|
|
|
.long 0 @
|
|
|
|
|
|
|
|
.end
|