169
170 ldrr2, _armboot_start/* _armboot_start在前面定义,是第一条指令的运行地址 */
171 ldrr3, _bss_start/* 在连接脚本u-boot.lds中定义,是代码段的结束地址 */
172 subr2, r3, r2/* r2 = 代码段长度 */
173 addr2, r0, r2/* r2 = NOR Flash上代码段的结束地址 */
174
175 copy_loop:
176 ldmiar0!, {r3-r10}/* 从地址[r0]处获得数据 */
177 stmiar1!, {r3-r10}/* 复制到地址[r1]处 */
178 cmpr0, r2/* 判断是否复制完毕 */
179 blecopy_loop/* 没复制完,则继续 */
(4)设置好栈。
栈的设置灵活性很大,只要让sp寄存器指向一段没有使用的内存即可。
182 /* Set up the stack */
183 stack_setup:
184 ldr r0, _TEXT_BASE /* _TEXT_BASE为代码段的开始地址,值为0x33F80000 */
185 sub r0, r0, #CFG_MALLOC_LEN /* 代码段下面,留出一段内存以实现malloc */
186 sub r0, r0, #CFG_GBL_DATA_SIZE /* 再留出一段内存,存一些全局参数 */
187 #ifdef CONFIG_USE_IRQ
188 sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ) /* IRQ、FIQ模式的栈 */

189 #endif
190 sub sp, r0, #12 /* 最后,留出12字节的内存给abort异常,
* 往下的内存就都是栈了
*/
191
到了这一步,读者可以知道内存的使用情况了,如下图所示(图中与上面的划分稍有不同,这是因为在cpu/arm920t/cpu.c中的cpu_init函数中才真正为IRQ、FIQ模式划分了栈): [[Image:]]
图3 U-Boot内存使用情况
(5)跳转到第二阶段代码的C入口点。
在跳转之前,还要清除BSS段(初始值为0、无初始值的全局变量、静态变量放在BSS段),代码如下:
192 clear_bss:
193 ldrr0, _bss_start/* BSS段的开始地址,它的值在连接脚本u-boot.lds中确定 */
194 ldrr1, _bss_end/* BSS段的结束地址,它的值在连接脚本u-boot.lds中确定 */
195 mov r2, #0x00000000
196
197 clbss_l:strr2, [r0]/* 往BSS段中写入0值 */
198 addr0, r0, #4
199 cmpr0, r1
200 bleclbss_l
201
现在,C函数的运行环境已经完全准备好,通过如下命令直接跳转(这之后,程序才在内存中执行),它将调用lib_arm/board.c中的start_armboot函数,这是第二阶段的入口点:
223 ldrpc, _start_armboot
224
225 _start_armboot:.word start_armboot
226
U-Boot第二阶段代码分析
它与15.1.2节中描述的Bootloader第二阶段所完成的功能基本上一致,不过顺序有点小差别。另外,U-Boot在启动内核之前可以让用户决定是否进入下载模式,即进入U-Boot的控制界面。
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-66092-13.html
赔本的买卖
赚中国人的钱拿去给美国人花
为应对美国的军事威胁
而更多的国家就看到美国在世界的霸权是多么让人讨厌
虚构诋毁攻击竞争对手