123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178 |
- /*
- * 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.
- *
- * coreboot starts in ARM mode as well.
- *
- * 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 {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)
- /* Coreboot already places modules at right place. */
- #ifndef GRUB_MACHINE_COREBOOT
- 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
- #endif
- @ 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:
|