UBoot程序分析:程序入口分析--->第一阶段BL1程序分析---->第二阶段BL2程序分析
解压Uboot源码,打开顶层Makefile,每个Uboot所支持的开发板在Makefile中都会有一个配置选项, 在E:uboot\board\samsung\smdk2440,有一个uboot.lds链接器脚本文件,Uboot整个链接就由它控制,打开链接器脚本看到:
.text :
{
cpu/s3c24xx/start.o (.text)
cpu/s3c24xx/s3c2440/cpu_init.o (.text)
*(.text)
}
得出位于整个uboot代码段最前端的是cpu/s3c24xx/start.o,在链接器脚本有ENTRY(_start)用来标明整个程序入口为_start,打开在cpu/s3c24xx/start.s,
_start:
b reset
ldr pc, _undefined_instruction
ldr pc, _software_interrupt
ldr pc, _prefetch_abort
ldr pc, _data_abort
ldr pc, _not_used
ldr pc, _irq
ldr pc, _fiq 整个程序的入口,这部分主要就是设置中断向量表。
首先跳到reset
reset:
/*
* set the cpu to SVC32 mode
*/
。。。。。。。。。。。。。。。。。
cpu_init_crit:
/*
* flush v4 I/D caches
*/
。。。。。。。。。。。。。。。。。
/*
* disable MMU stuff and caches
*/
。。。。。。。。。。。。。。。。
设置处理器为SVC32模式,刷新I/D caches,关闭MMU和cache,下面运行函数lowlevel_init
打开目录E:\uboot\board\samsung\smdk2440找到lowlevel_init.S
lowlevel_init:
mov r12, lr
/*init system clock */
blsystem_clock_init
/* for UART */
bluart_asm_init
/* simple init for NAND */
blnand_asm_init
。。。。。。。。。。。。。。。。。。。。。
adrl r0, mem_cfg_val
bl mem_con_init
。。。。。。。。。。。。。。。。。。。。。。
1: mov lr, r12
mov pc, lr
初始化系统时钟,串口,对nandflash进行简单初始化,判断Uboot是否运行于内存当中,如果没有,那么就是从nandflash启动,就要对内存初始化,然后返回到Start.s。
/* check boot device is nand or nor */
ldr r0, =0x00000000
ldr r3, [r0]
ldr r1, =0xfffffffe
str r1, [r0]
ldr r2, [r0]
str r3, [r0]
cmp r1, r2
。。。。。。。。。。。。。。。。。。。
beq nand_copy
。。。。。。。。。。。。。。。。。
/* nor copy */
。。。。。。。。。。。。。。。。
nand_copy:
mov r0, #0x1000
bl copy_from_nand
判断是否为norflash还是nandflash,如果是nandflash就会beq nand_copy,如果是norflash就会/* nor copy */把剩余在norflash或nandflash中的bootload拷贝到内存,这里是从nandflash启动,调用nand_copy,完成bootload拷贝。
/* Set up the stack */
stack_setup:
。。。。。。。。。。。。。。。。。。。。。。。。。
clear_bss:
ldr r0, _bss_start /* find start of bsssegment */
ldr r1, _bss_end /* stop here */
mov r2, #0x00000000 /*clear*/
设置堆栈,为C编程铺垫,清除BSS段,这样第一阶段代码完成。
ldr pc,_start_armboot 伪指令把_start_armboot值装载到pc指针, _start_armboot 为start_armboot函数地址,pc指针运行start_armboot函数,跳转到内存运行,分析第二阶段程序E:\uboot\lib_arm board.c
void start_armboot() 函数
。。。。。。。。。。。。。。。
for (init_fnc_ptr = init_sequence;*init_fnc_ptr; ++init_fnc_ptr) {
if ((*init_fnc_ptr)() != 0) {
hang();
}
}让一个指针指向指针数组,把指针数组里的函数指针依次调用如下函数,
init_fnc_t *init_sequence[] = {
cpu_init, /*basic cpu dependent setup */
board_init, /*basic board dependent setup */
interrupt_init, /*set up exceptions */
env_init, /*initialize environment */
init_baudrate, /*initialze baudrate settings */
serial_init, /*serial communications setup */
console_init_f, /*stage 1 init of console */
display_banner, /*say that we are here */
};初始化串口,
。。。。。。。。。。。。。。。
size = lcd_setmem (addr);
eth_initialize(gd->bd);
led_init(); //初始化lcd,网卡 ,led
main_loop (); //解析用户输入控制台命令,执行用户相应命令
下面分析6410 Uboot
E:\uboot\cpu\s3c64xx Start.s
_start: b reset
ldr pc, _undefined_instruction
ldr pc, _software_interrupt
ldr pc, _prefetch_abort
ldr pc, _data_abort
ldr pc, _not_used
ldr pc, _irq
ldr pc, _fiq //第一部分也是设置中断向量表,
。。。。。。。。。。。。。。。。。。
reset:
/*
* set the cpu to SVC32 mode
*/
/*
* flush v4 I/D caches
*/
/*
* disable MMU stuff and caches
*/ 同2410,设置CPU为svc模式,刷新I/D caches,关闭MMU和caches。
/* Peri port setup */ //外围设备基地址初始化
bl lowlevel_init /* go setup pll,mux,memory */ 进入lowlevel_init函数
lowlevel_init::
/* LED on only #8 */ //点亮LED
/* Disable Watchdog */ //关闭看门狗
@ Disable all interrupts (VIC0 andVIC1) //关闭所有中断
blsystem_clock_init
bl uart_asm_init
bl nand_asm_init
//初始化系统时钟、串口、nandflash
bl mem_ctrl_asm_init //初始化内存,然后返回Start.s
#ifdef CONFIG_BOOT_NAND
mov r0, #0x1000
bl copy_from_nand //把nandflash里bootload复制到内存
/* Set up the stack*/
stack_setup: //堆栈初始化
clear_bss:
ldr r0, _bss_start /* find start of bss segment*/
ldr r1, _bss_end /*stop here */
mov r2, #0x00000000/* clear*/ //清除bss段
ldr pc, _start_armboot //跳转到start_armboot只有一个地方有,2440,6410共享一个lib_arm/board.c start_armboot ,分析同2440。