📄 head.s
字号:
/* * linux/arch/arm/boot/compressed/head.S * * Copyright (C) 1996-2002 Russell King * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */#include <linux/config.h>#include <linux/linkage.h>/* * Debugging stuff * * Note that these macros must not contain any code which is not * 100% relocatable. Any attempt to do so will result in a crash. * Please select one of the following when turning on debugging. */#ifdef DEBUG#if defined(CONFIG_DEBUG_ICEDCC) .macro loadsp, rb .endm .macro writeb, ch, rb mcr p14, 0, \ch, c0, c1, 0 .endm#else#include <asm/arch/debug-macro.S> .macro writeb, ch, rb senduart \ch, \rb .endm#if defined(CONFIG_ARCH_SA1100) .macro loadsp, rb mov \rb, #0x80000000 @ physical base address#ifdef CONFIG_DEBUG_LL_SER3 add \rb, \rb, #0x00050000 @ Ser3#else add \rb, \rb, #0x00010000 @ Ser1#endif .endm#elif defined(CONFIG_ARCH_IOP331) .macro loadsp, rb mov \rb, #0xff000000 orr \rb, \rb, #0x00ff0000 orr \rb, \rb, #0x0000f700 @ location of the UART .endm#elif defined(CONFIG_ARCH_S3C2410) .macro loadsp, rb mov \rb, #0x50000000 add \rb, \rb, #0x4000 * CONFIG_S3C2410_LOWLEVEL_UART_PORT .endm#else .macro loadsp, rb addruart \rb .endm#endif#endif#endif .macro kputc,val mov r0, \val bl putc .endm .macro kphex,val,len mov r0, \val mov r1, #\len bl phex .endm .macro debug_reloc_start#ifdef DEBUG kputc #'\n' kphex r6, 8 /* processor id */ kputc #':' kphex r7, 8 /* architecture id */ kputc #':' mrc p15, 0, r0, c1, c0 kphex r0, 8 /* control reg */ kputc #'\n' kphex r5, 8 /* decompressed kernel start */ kputc #'-' kphex r8, 8 /* decompressed kernel end */ kputc #'>' kphex r4, 8 /* kernel execution address */ kputc #'\n'#endif .endm .macro debug_reloc_end#ifdef DEBUG kphex r5, 8 /* end of kernel */ kputc #'\n' mov r0, r4 bl memdump /* dump 256 bytes at start of kernel */#endif .endm .section ".start", #alloc, #execinstr/* * sort out different calling conventions */ .alignstart: .type start,#function .rept 8 mov r0, r0 .endr b 1f .word 0x016f2818 @ Magic numbers to help the loader .word start @ absolute load/run zImage address .word _edata @ zImage end address1: mov r7, r1 @ save architecture ID mov r8, #0 @ save r0#ifndef __ARM_ARCH_2__ /* * Booting from Angel - need to enter SVC mode and disable * FIQs/IRQs (numeric definitions from angel arm.h source). * We only do this if we were in user mode on entry. */ mrs r2, cpsr @ get current mode tst r2, #3 @ not user? bne not_angel mov r0, #0x17 @ angel_SWIreason_EnterSVC swi 0x123456 @ angel_SWI_ARMnot_angel: mrs r2, cpsr @ turn off interrupts to orr r2, r2, #0xc0 @ prevent angel from running msr cpsr_c, r2#else teqp pc, #0x0c000003 @ turn off interrupts#endif /* * Note that some cache flushing and other stuff may * be needed here - is there an Angel SWI call for this? */ /* * some architecture specific code can be inserted * by the linker here, but it should preserve r7 and r8. */ .text adr r0, LC0 ldmia r0, {r1, r2, r3, r4, r5, r6, ip, sp} subs r0, r0, r1 @ calculate the delta offset @ if delta is zero, we are beq not_relocated @ running at the address we @ were linked at. /* * We're running at a different address. We need to fix * up various pointers: * r5 - zImage base address * r6 - GOT start * ip - GOT end */ add r5, r5, r0 add r6, r6, r0 add ip, ip, r0#ifndef CONFIG_ZBOOT_ROM /* * If we're running fully PIC === CONFIG_ZBOOT_ROM = n, * we need to fix up pointers into the BSS region. * r2 - BSS start * r3 - BSS end * sp - stack pointer */ add r2, r2, r0 add r3, r3, r0 add sp, sp, r0 /* * Relocate all entries in the GOT table. */1: ldr r1, [r6, #0] @ relocate entries in the GOT add r1, r1, r0 @ table. This fixes up the str r1, [r6], #4 @ C references. cmp r6, ip blo 1b#else /* * Relocate entries in the GOT table. We only relocate * the entries that are outside the (relocated) BSS region. */1: ldr r1, [r6, #0] @ relocate entries in the GOT cmp r1, r2 @ entry < bss_start || cmphs r3, r1 @ _end < entry addlo r1, r1, r0 @ table. This fixes up the str r1, [r6], #4 @ C references. cmp r6, ip blo 1b#endifnot_relocated: mov r0, #01: str r0, [r2], #4 @ clear bss str r0, [r2], #4 str r0, [r2], #4 str r0, [r2], #4 cmp r2, r3 blo 1b /* * The C runtime environment should now be setup * sufficiently. Turn the cache on, set up some * pointers, and start decompressing. */ bl cache_on mov r1, sp @ malloc space above stack add r2, sp, #0x10000 @ 64k max/* * Check to see if we will overwrite ourselves. * r4 = final kernel address * r5 = start of this image * r2 = end of malloc space (and therefore this image) * We basically want: * r4 >= r2 -> OK * r4 + image length <= r5 -> OK */ cmp r4, r2 bhs wont_overwrite add r0, r4, #4096*1024 @ 4MB largest kernel size cmp r0, r5 bls wont_overwrite mov r5, r2 @ decompress after malloc space mov r0, r5 mov r3, r7 bl decompress_kernel add r0, r0, #127 bic r0, r0, #127 @ align the kernel length/* * r0 = decompressed kernel length * r1-r3 = unused * r4 = kernel execution address * r5 = decompressed kernel start * r6 = processor ID * r7 = architecture ID * r8-r14 = unused */ add r1, r5, r0 @ end of decompressed kernel adr r2, reloc_start ldr r3, LC1 add r3, r2, r31: ldmia r2!, {r8 - r13} @ copy relocation code stmia r1!, {r8 - r13} ldmia r2!, {r8 - r13} stmia r1!, {r8 - r13} cmp r2, r3 blo 1b bl cache_clean_flush add pc, r5, r0 @ call relocation code/* * We're not in danger of overwriting ourselves. Do this the simple way. * * r4 = kernel execution address * r7 = architecture ID */wont_overwrite: mov r0, r4 mov r3, r7 bl decompress_kernel b call_kernel .type LC0, #objectLC0: .word LC0 @ r1 .word __bss_start @ r2 .word _end @ r3 .word zreladdr @ r4 .word _start @ r5 .word _got_start @ r6 .word _got_end @ ip .word user_stack+4096 @ spLC1: .word reloc_end - reloc_start .size LC0, . - LC0#ifdef CONFIG_ARCH_RPC .globl paramsparams: ldr r0, =params_phys mov pc, lr .ltorg .align#endif/* * Turn on the cache. We need to setup some page tables so that we * can have both the I and D caches on. * * We place the page tables 16k down from the kernel execution address, * and we hope that nothing else is using it. If we're using it, we * will go pop! * * On entry, * r4 = kernel execution address * r6 = processor ID * r7 = architecture number * r8 = run-time address of "start" * On exit, * r1, r2, r3, r8, r9, r12 corrupted * This routine must preserve: * r4, r5, r6, r7 */ .align 5cache_on: mov r3, #8 @ cache_on function b call_cache_fn__setup_mmu: sub r3, r4, #16384 @ Page directory size bic r3, r3, #0xff @ Align the pointer bic r3, r3, #0x3f00/* * Initialise the page tables, turning on the cacheable and bufferable * bits for the RAM area only. */ mov r0, r3 mov r8, r0, lsr #18 mov r8, r8, lsl #18 @ start of RAM add r9, r8, #0x10000000 @ a reasonable RAM size mov r1, #0x12 orr r1, r1, #3 << 10 add r2, r3, #163841: cmp r1, r8 @ if virt > start of RAM orrhs r1, r1, #0x0c @ set cacheable, bufferable cmp r1, r9 @ if virt > end of RAM bichs r1, r1, #0x0c @ clear cacheable, bufferable str r1, [r0], #4 @ 1:1 mapping add r1, r1, #1048576 teq r0, r2 bne 1b/* * If ever we are running from Flash, then we surely want the cache * to be enabled also for our execution instance... We map 2MB of it * so there is no map overlap problem for up to 1 MB compressed kernel. * If the execution is in RAM then we would only be duplicating the above. */ mov r1, #0x1e orr r1, r1, #3 << 10 mov r2, pc, lsr #20 orr r1, r1, r2, lsl #20 add r0, r3, r2, lsl #2 str r1, [r0], #4 add r1, r1, #1048576 str r1, [r0] mov pc, lr__armv4_cache_on:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -