/* * 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 . */ #include #include #include /* * 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). * : * : * Loadable modules, post relocation. * : */ .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 {r0-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) .align 3 @ U-boot/coreboot context stack space VARIABLE(grub_arm_saved_registers) .long 0 @ r0 .long 0 @ r1 .long 0 @ r2 .long 0 @ r3 .long 0 @ r4 .long 0 @ r5 .long 0 @ r6 .long 0 @ r7 .long 0 @ r8 .long 0 @ r9 .long 0 @ r10 .long 0 @ r11 .long 0 @ sp .long 0 @ lr entry_state: