u-boot源代码的目录结构
1、board中存放于开发板相关的配置文件,每一个开发板都以子文件夹的形式出现。
2、Commom文件夹实现u-boot行下支持的命令,每一个命令对应一个文件。
3、cpu中存放特定cpu架构相关的目录,每一款cpu架构都对应了一个子目录。
4、Doc是文档目录,有u-boot非常完善的文档。
5、Drivers中是u-boot支持的各种设备的驱动程序。
6、Fs是支持的文件系统,其中最常用的是JFFS2文件系统。
7、Include文件夹是u-boot使用的头文件,还有各种硬件平台支持的汇编文件,系统配置文件和文件系统支持的文件。
8、lib_xxx与体系结构相关的库文件。如ARM相关的库放在lib_arm目录下。
9、Net是与网络协议相关的代码,bootp协议、TFTP协议、NFS文件系统得实现。
10、Tooles是生成U-boot的工具。
start.S -> start_armboot () -> main_loop ()
main_loop()会调用abortboot (bootdelay)判断在delay time内有没有键按下,并给出“Hit
any key to stop autoboot”,若没有键按下则run_command (s,
0)(s为默认的bootcmd)。这里默认的bootcmd需要根据内核的位置设置,若bootcmd未赋值,Uboot就会一直等待。如果敲入bootm,也会启动kernel,并且传入参数。如果使用tftp从pc中下载kernel并启动也是可以的。
cpu/arm920t/start.S:(代码就不展开,简单介绍)
.globl _start
_start: b start_code //set the cpu to SVC32 mode
ldr pc, _undefined_instruction
ldr pc, _software_interrupt
ldr pc, _prefetch_abort
...
start_code: /*set the cpu to SVC32 mode */
...
relocate: /* relocate U-Boot to RAM 将uboot复制到ram */
...
stack_setup: /* Set up the stack 设置程序栈 */
...
ldr pc, _start_armboot //执行_start_armboot,第一个C函数
_start_armboot: .word start_armboot
...
lib_arm/broad.c:
start_armboot 是U-Boot 执行的第一个C 语言函数,完成系统初始化工作,进入主循环,处理用户输入的命令。
void start_armboot (void)
{
...
gd = (gd_t*)(_armboot_start - CONFIG_SYS_MALLOC_LEN - sizeof(gd_t));
...
/* 顺序执行init_sequence 数组中的初始化函数 */
for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
if ((*init_fnc_ptr)() != 0) {
hang ();
}
}
/* initialize environment */
env_relocate ();
//各种初始化...
...
/* Initialize from environment 通过环境变量初始化 */
if ((s = getenv ("loadaddr")) != NULL) {
load_addr = simple_strtoul (s, NULL, 16);
}
...
/* main_loop()循环不断执行 */
for (;;) {
main_loop ();
}
}
init_sequence[]数组保存着基本的初始化函数指针。
init_fnc_t *init_sequence[] = {
cpu_init, /* 基本的处理器相关配置 -- cpu/arm920t/cpu.c */
board_init, /* 基本的板级相关配置 --board/smdk2410/smdk2410.c */
interrupt_init, /* 初始化例外处理 --cpu/arm920t/s3c24x0/interrupt.c */
env_init, /* 初始化环境变量 -- common/env_flash.c */
init_baudrate, /* 初始化波特率设置 -- lib_arm/board.c */
serial_init, /* 串口通讯设置 -- cpu/arm920t/s3c24x0/serial.c*/
console_init_f, /* 控制台初始化阶段1 -- common/console.c */
display_banner, /* 打印u-boot 信息 -- lib_arm/board.c */
dram_init, /* 配置可用的RAM --board/smdk2410/smdk2410.c */
display_dram_config, /* 显示RAM的配置大小 -- lib_arm/board.c */
NULL,
};
common/main.c:
void main_loop (void)
{
...
install_auto_complete();
s = getenv ("bootdelay");
s = getenv ("bootcmd");
if (bootdelay >= 0 && s && !abortboot (bootdelay)) {
run_command (s, 0); //如果延时大于等于零,并且没有在延时过程中接收到按键,则引导内核。
}
}