diff options
Diffstat (limited to 'arch/arm/boot/compressed/head.S')
-rw-r--r-- | arch/arm/boot/compressed/head.S | 167 |
1 files changed, 118 insertions, 49 deletions
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index e28de2a..8c57359 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S @@ -10,6 +10,7 @@ */ #include <linux/linkage.h> + .arch armv7-a /* * Debugging stuff * @@ -216,6 +217,104 @@ restart: adr r0, LC0 mov r10, r6 #endif + mov r5, #0 @ init dtb size to 0 +#ifdef CONFIG_ARM_APPENDED_DTB +/* + * r0 = delta + * r2 = BSS start + * r3 = BSS end + * r4 = final kernel address + * r5 = appended dtb size (still unknown) + * r6 = _edata + * r7 = architecture ID + * r8 = atags/device tree pointer + * r9 = size of decompressed image + * r10 = end of this image, including bss/stack/malloc space if non XIP + * r11 = GOT start + * r12 = GOT end + * sp = stack pointer + * + * if there are device trees (dtb) appended to zImage, advance r10 so that the + * dtb data will get relocated along with the kernel if necessary. + */ + + ldr lr, [r6, #0] +#ifndef __ARMEB__ + ldr r1, =0xedfe0dd0 @ sig is 0xd00dfeed big endian +#else + ldr r1, =0xd00dfeed +#endif + cmp lr, r1 + bne dtb_check_done @ not found + +#ifdef CONFIG_ARM_ATAG_DTB_COMPAT + /* + * OK... Let's do some funky business here. + * If we do have a DTB appended to zImage, and we do have + * an ATAG list around, we want the later to be translated + * and folded into the former here. To be on the safe side, + * let's temporarily move the stack away into the malloc + * area. No GOT fixup has occurred yet, but none of the + * code we're about to call uses any global variable. + */ + add sp, sp, #0x10000 + stmfd sp!, {r0-r3, ip, lr} + mov r0, r8 + mov r1, r6 + sub r2, sp, r6 + bl atags_to_fdt + + /* + * If returned value is 1, there is no ATAG at the location + * pointed by r8. Try the typical 0x100 offset from start + * of RAM and hope for the best. + */ + cmp r0, #1 + sub r0, r4, #TEXT_OFFSET + add r0, r0, #0x100 + mov r1, r6 + sub r2, sp, r6 + bleq atags_to_fdt + + ldmfd sp!, {r0-r3, ip, lr} + sub sp, sp, #0x10000 +#endif + + mov r8, r6 @ use the appended device tree + + /* + * Make sure that the DTB doesn't end up in the final + * kernel's .bss area. To do so, we adjust the decompressed + * kernel size to compensate if that .bss size is larger + * than the relocated code. + */ + ldr r5, =_kernel_bss_size + adr r1, wont_overwrite + sub r1, r6, r1 + subs r1, r5, r1 + addhi r9, r9, r1 + + /* Get the dtb's size */ + ldr r5, [r6, #4] +#ifndef __ARMEB__ + /* convert r5 (dtb size) to little endian */ + eor r1, r5, r5, ror #16 + bic r1, r1, #0x00ff0000 + mov r5, r5, ror #8 + eor r5, r5, r1, lsr #8 +#endif + + /* preserve 64-bit alignment */ + add r5, r5, #7 + bic r5, r5, #7 + + /* relocate some pointers past the appended dtb */ + add r6, r6, r5 + add r10, r10, r5 + add sp, sp, r5 +dtb_check_done: +#endif + /* * Check to see if we will overwrite ourselves. * r4 = final kernel address @@ -223,15 +322,14 @@ restart: adr r0, LC0 * r10 = end of this image, including bss/stack/malloc space if non XIP * We basically want: * r4 - 16k page directory >= r10 -> OK - * r4 + image length <= current position (pc) -> OK + * r4 + image length <= address of wont_overwrite -> OK */ add r10, r10, #16384 cmp r4, r10 bhs wont_overwrite add r10, r4, r9 - ARM( cmp r10, pc ) - THUMB( mov lr, pc ) - THUMB( cmp r10, lr ) + adr r9, wont_overwrite + cmp r10, r9 bls wont_overwrite /* @@ -285,20 +383,16 @@ wont_overwrite: * r2 = BSS start * r3 = BSS end * r4 = kernel execution address + * r5 = appended dtb size (0 if not present) * r7 = architecture ID * r8 = atags pointer * r11 = GOT start * r12 = GOT end * sp = stack pointer */ - teq r0, #0 -#ifndef CONFIG_CRYPTO_FIPS + orrs r1, r0, r5 beq not_relocated -#else - movw r5, #:lower16:zimage_ram_base_addr - movt r5, #:upper16:zimage_ram_base_addr - beq not_relocated_copy -#endif + add r11, r11, r0 add r12, r12, r0 @@ -311,19 +405,23 @@ wont_overwrite: add r2, r2, r0 add r3, r3, r0 -#ifdef CONFIG_CRYPTO_FIPS - movw r5, #:lower16:zimage_ram_base_addr - movt r5, #:upper16:zimage_ram_base_addr - bl copy_compressed -#endif /* * Relocate all entries in the GOT table. + * Bump bss entries to _edata + dtb size */ 1: ldr r1, [r11, #0] @ relocate entries in the GOT - add r1, r1, r0 @ table. This fixes up the - str r1, [r11], #4 @ C references. + add r1, r1, r0 @ This fixes up C references + cmp r1, r2 @ if entry >= bss_start && + cmphs r3, r1 @ bss_end > entry + addhi r1, r1, r5 @ entry += dtb size + str r1, [r11], #4 @ next entry cmp r11, r12 blo 1b + + /* bump our bss pointers too */ + add r2, r2, r5 + add r3, r3, r5 + #else /* @@ -364,7 +462,8 @@ not_relocated: mov r0, #0 mov r0, #0 @ must be zero mov r1, r7 @ restore architecture number mov r2, r8 @ restore atags pointer - mov pc, r4 @ call kernel + ARM( mov pc, r4 ) @ call kernel + THUMB( bx r4 ) @ entry point is always ARM .align 2 .type LC0, #object @@ -378,10 +477,6 @@ LC0: .word LC0 @ r1 .word .L_user_stack_end @ sp .size LC0, . - LC0 -#ifdef CONFIG_CRYPTO_FIPS - .equ zimage_ram_base_addr, FIPS_KERNEL_RAM_BASE -#endif - #ifdef CONFIG_ARCH_RPC .globl params params: ldr r0, =0x10000100 @ params_phys for RPC @@ -390,29 +485,6 @@ params: ldr r0, =0x10000100 @ params_phys for RPC .align #endif - -#ifdef CONFIG_CRYPTO_FIPS -not_relocated_copy: - bl copy_compressed - b not_relocated - -copy_compressed: - mov r1, r5 - add r9, r4, #CONFIG_CRYPTO_FIPS_INTEG_OFFSET - -1: - ldmia r1!, {r5} - stmia r9!, {r5} - cmp r1, r2 - blo 1b - - .rept 8 - ldmia r1!, {r5} - stmia r9!, {r5} - .endr - mov pc, lr -#endif - /* * Turn on the cache. We need to setup some page tables so that we * can have both the I and D caches on. @@ -695,8 +767,6 @@ proc_types: @ b __arm6_mmu_cache_off @ b __armv3_mmu_cache_flush -#if !defined(CONFIG_CPU_V7) - /* This collides with some V7 IDs, preventing correct detection */ .word 0x00000000 @ old ARM ID .word 0x0000f000 mov pc, lr @@ -705,7 +775,6 @@ proc_types: THUMB( nop ) mov pc, lr THUMB( nop ) -#endif .word 0x41007000 @ ARM7/710 .word 0xfff8fe00 |