http://chxxxyg.blog.163.com/blog/static/150281193201072603030285/
文件arch/arm/boot/compressed/head.S是linux内核启动过程执行的第一个文件。
119 .align
120 .arm @ Always enter in ARM state
121 start:
122 .type start,#function @type指定start这个符号是函数类型
123 .rept 7 @重复7次 mov r0, r0,
124 mov r0, r0 @空操作,让前面所取指令得以执行。
125 .endr
126 ARM( mov r0, r0 ) @空操作,让前面所取指令得以执行。
127 ARM( b 1f ) @跳转
128 THUMB( adr r12, BSYM(1f) )
129 THUMB( bx r12 )
130
/*
魔数0x016f2818是在bootloader中用于判断zImage的存在,
而zImage的判别的magic number为0x016f2818,这个也是内核和bootloader约定好的。
*/
131 .word 0x016f2818 @ Magic numbers to help the loader
132 .word start @ absolute load/run zImage address
133 .word _edata @ zImage end address
134 THUMB( .thumb )
r1和r2中分别存放着由bootloader传递过来的architecture ID和指向标记列表的指针。
135 1: mov r7, r1 @ save architecture ID
136 mov r8, r2 @ save atags pointer
/*
这也标志着u-boot将系统完全的交给了OS,bootloader生命终止。之后会读取
cpsr并判断是否处理器处于supervisor模式——从u-boot进入kernel,系统已经处于SVC32模式;
而利用angel进入则处于user模式,还需要额外两条指令。之后是再次确认中断关闭,并完成cpsr写入
*/
137
138 #ifndef __ARM_ARCH_2__
139 /*
140 * Booting from Angel - need to enter SVC mode and disable
141 * FIQs/IRQs (numeric definitions from angel arm.h source).
142 * We only do this if we were in user mode on entry.
143 */
144 mrs r2, cpsr @ get current mode
145 tst r2, #3 @ not user?
146 bne not_angel
147 mov r0, #0x17 @ angel_SWIreason_EnterSVC 0x17是angel_SWIreason_EnterSVC半主机操作
148 ARM( swi 0x123456 ) @ angel_SWI_ARM 0x123456是arm指令集的半主机操作编号
149 THUMB( svc 0xab ) @ angel_SWI_THUMB
150 not_angel:
151 mrs r2, cpsr @ turn off interrupts to
152 orr r2, r2, #0xc0 @ prevent angel from running
153 msr cpsr_c, r2 @这里将cpsr中I、F位分别置“1”,关闭IRQ和FIQ
154 #else
155 teqp pc, #0x0c000003 @ turn off interrupts
156 #endif
/*LC0表是链接文件arch/arm/boot/compressed/vmlinux.lds
(这个lds文件是由arch/arm/boot/compressed/vmlinux.lds.in生成的)的各段入口。
10 OUTPUT_ARCH(arm)
11 ENTRY(_start)
12 SECTIONS
13 {
14 /DISCARD/ : {
15 *(.ARM.exidx*)
16 *(.ARM.extab*)
17 /*
18 * Discard any r/w data - this produces a link error if we have any,
19 * which is required for PIC decompression. Local data generates
20 * GOTOFF relocations, which prevents it being relocated independently
21 * of the text/got segments.
22 */
23 *(.data)
24 }
25
26 . = 0;
27 _text = .;
28
29 .text : {
30 _start = .;
31 *(.start)
32 *(.text)
33 *(.text.*)
34 *(.fixup)
35 *(.gnu.warning)
36 *(.rodata)
37 *(.rodata.*)
38 *(.glue_7)
39 *(.glue_7t)
40 *(.piggydata)
41 . = ALIGN(4);
42 }
43
44 _etext = .;
45
46 _got_start = .;
47 .got : { *(.got) }
48 _got_end = .;
49 .got.plt : { *(.got.plt) }
50 _edata = .;
51
52 . = ALIGN(8);
53 __bss_start = .;
54 .bss : { *(.bss) }
55 _end = .;
56
57 . = ALIGN(8); /* the stack must be 64-bit aligned */
58 .stack : { *(.stack) }
59
60 .stab 0 : { *(.stab) }
61 .stabstr 0 : { *(.stabstr) }
62 .stab.excl 0 : { *(.stab.excl) }
63 .stab.exclstr 0 : { *(.stab.exclstr) }
64 .stab.index 0 : { *(.stab.index) }
65 .stab.indexstr 0 : { *(.stab.indexstr) }
66 .comment 0 : { *(.comment) }
67 }
68
展开如下表:
假定zImage在内存中的初始地址为0x30008000(这个地址由bootloader决定,位置不固定)1、初始状态
链接文件arch/arm/boot/compressed/vmlinux.lds中的连接地址都是位置无关的,即都是以0地址为偏移的。
而此时内核已被bootloader搬移到了SDRAM中。链接地址应该加上这个偏移。
*/
.........前面是注释
168 .text
169
170 #ifdef CONFIG_AUTO_ZRELADDR
171 @ determine final kernel image address
172 mov r4, pc
173 and r4, r4, #0xf8000000
174 add r4, r4, #TEXT_OFFSET
175 #else
176 ldr r4, =zreladdr
177 #endif
178
179 bl cache_on
180
181 restart: adr r0, LC0
指令adr是基于PC的值来获取标号LC0 的地址的,由于内核已被搬移,标号LC0的地址不是以地址0为偏移的,这中间就存在一个固定的地址偏移,在s3c2410中是0x30008000.
182 ldmia r0, {r1, r2, r3, r6, r10, r11, r12}
183 ldr sp, [r0, #28]
184
185 /*
186 * We might be running at a different address. We need
187 * to fix up various pointers.
188 */
189 sub r0, r0, r1 @ calculate the delta offset这里获得当前运行地址与链接地址的偏移量,存入r0中为0x30008000.
190 add r6, r6, r0 @ _edata
191 add r10, r10, r0 @ inflated kernel size location
192
193 /*
194 * The kernel build system appends the size of the
195 * decompressed kernel at the end of the compressed data
196 * in little-endian form.
197 */
198 ldrb r9, [r10, #0]
199 ldrb lr, [r10, #1]
阅读(1685) | 评论(0) | 转发(0) |