码迷,mamicode.com
首页 > 其他好文 > 详细

u-boot分析

时间:2014-07-08 15:34:46      阅读:151      评论:0      收藏:0      [点我收藏+]

标签:style   文件   os   art   cti   for   

4.Bootloader:u-boot.2009.08分析与移植
4.1:分析u-boot根目录下的Makefile,可以看到uboot编译的顺序如下,由此可知编译执行的第一个文件是cpu/$(CPU)/start.o,又由于是基于


arm920t架构的,所以去分析cpu/arm920t/start.S源文件。
# U-Boot objects....order is important (i.e. start must be first)
OBJS  = cpu/$(CPU)/start.o
OBJS := $(addprefix $(obj),$(OBJS))


LIBS  = lib_generic/libgeneric.a
LIBS += lib_generic/lzma/liblzma.a
LIBS += lib_generic/lzo/liblzo.a 
LIBS += $(shell if [ -f board/$(VENDOR)/common/Makefile ]; then echo \
"board/$(VENDOR)/common/lib$(VENDOR).a"; fi)
LIBS += cpu/$(CPU)/lib$(CPU).a
LIBS += lib_$(ARCH)/lib$(ARCH).a
LIBS += fs/...(.a)
LIBS += net/libnet.a
LIBS += disk/libdisk.a
LIBS += drivers/...(.a)
LIBS += common/libcommon.a
LIBS += libfdt/libfdt.a
LIBS += api/libapi.a
LIBS += post/libpost.a
LIBS := $(addprefix $(obj),$(LIBS))


4.2:分析cpu/arm920t/start.S源文件:由ARM架构可知程序的执行顺序是开发板一上电即从零地址开始执行,在零地址存放的是一条复位异常中断处


理,依次分析可知程序从上电开始的执行依次如下:设置处理器模式、关闭看门狗、关闭中断、设置分频系数比、系统初始化(flush I/D cache、disable MMU


、内存sdram相关初始化)、重定位代码(从flash复制uboot代码到SDRAM中)、初始化堆栈、清除bss段、跳转到第二阶段的C语言代码入口函数start_armboot处


执行。
(1).globl _start
 _start: b       start_code

(2)start_code:
  /* set the cpu to SVC32 mode*/
/* turn off the watchdog */
/* mask all IRQs by setting all bits in the INTMR - default */
/* setup FCLK:HCLK:PCLK */
bl cpu_init_crit  /*do sys-critical inits only at reboot*/
#ifndef CONFIG_SKIP_RELOCATE_UBOOT
/* relocate U-Boot from nor flash to RAM */
/* Set up the stack */
/* Clear bss */
/*  jump to second stage */
ldr pc, _start_armboot
_start_armboot: .word start_armboot


4.3:分析/lib_arm/board.c里的start_armboot函数:
gd = (gd_t*)(_armboot_start - CONFIG_SYS_MALLOC_LEN - sizeof(gd_t));
memset ((void*)gd, 0, sizeof (gd_t));等,初始化gd_t结构体指针gd,并初始化。


typedef int (init_fnc_t) (void);
init_fnc_t *init_sequence[] = {
#if defined(CONFIG_ARCH_CPU_INIT)
arch_cpu_init, /* basic arch cpu dependent setup */
#endif
board_init, /* basic board dependent setup */
#if defined(CONFIG_USE_IRQ)
interrupt_init, /* set up exceptions */
#endif
timer_init, /* initialize timer */
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 */
#if defined(CONFIG_DISPLAY_CPUINFO)
print_cpuinfo, /* display cpu info (and speed) */
#endif
#if defined(CONFIG_DISPLAY_BOARDINFO)
checkboard, /* display board info */
#endif
#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)
init_func_i2c,
#endif
dram_init, /* configure available RAM banks */
#if defined(CONFIG_CMD_PCI) || defined (CONFIG_PCI)
arm_pci_init,
#endif
display_dram_config,
NULL,
};


for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
if ((*init_fnc_ptr)() != 0) {
hang ();
}
},通过一个for循环来依次访问函数指针数组init_sequence中的成员函数,进一步完成相关初始化和相关设置。


nand_init(); /* go init the NAND */,初始化nand flash。
serial_initialize();   ,初始化串口。


/* main_loop() can return to retry autoboot, if so just run it again. */
for (;;) {
main_loop ();
}


/* NOTREACHED - no way out of command loop except booting */,在无限for循环内,执行main_loop函数。


4.4:分析/common/main.c里的main_loop函数:处理uboot命令。
/*
* Main Loop for Monitor Command Processing
*/
for(;;){
#ifdef CONFIG_BOOT_RETRY_TIME
if (rc >= 0) {
/* Saw enough of a valid command to
* restart the timeout.
*/
reset_cmd_timeout();
}
#endif
len = readline (CONFIG_SYS_PROMPT);


flag = 0; /* assume no special flags for now */
if (len > 0)
strcpy (lastcommand, console_buffer);
else if (len == 0)
flag |= CMD_FLAG_REPEAT;
#ifdef CONFIG_BOOT_RETRY_TIME
else if (len == -2) {
/* -2 means timed out, retry autoboot
*/
puts ("\nTimed out waiting for command\n");
# ifdef CONFIG_RESET_TO_RETRY
/* Reinit board to run initialization code again */
do_reset (NULL, 0, 0, NULL);
# else
return; /* retry autoboot */
# endif
}
#endif


if (len == -1)
puts ("<INTERRUPT>\n");
else
rc = run_command (lastcommand, flag);


if (rc <= 0) {
/* invalid command or not repeatable, forget it */
lastcommand[0] = 0;
}
}

根据输入的命令格式,解析命令参数,执行命令(执行run_command函数),/commmon/main.c里的run_command函数,根据命令表结构体cmd_tbl_s来找


到输入命令所对应的实现函数。
/*
  * Monitor Command Table
  */


struct cmd_tbl_s {
char *name; /* Command Name */
int maxargs; /* maximum number of arguments */
int repeatable; /* autorepeat allowed? */
/* Implementation function */
int (*cmd)(struct cmd_tbl_s *, int, int, char *[]);
char *usage; /* Usage message (short) */
#ifdef CONFIG_SYS_LONGHELP
char *help; /* Help  message (long) */
#endif
#ifdef CONFIG_AUTO_COMPLETE
/* do auto completion on the arguments */
int (*complete)(int argc, char *argv[], char last_char, int maxv, char *cmdv[]);
#endif
};
typedef struct cmd_tbl_s cmd_tbl_t;
cmd_tbl_t *cmdtp;
/* OK - call function to do the command */
if ((cmdtp->cmd) (cmdtp, flag, argc, argv) != 0) {
rc = -1;
}//至此,根据不同的uboot命令,去执行不同的实现函数。
4.5:uboot启动linux操作系统的命令是bootm,uboot的bootm命令的实现文件是cmd_bootm.c,所以接着来分析/common/cmd_bootm.c文件:命令实


现的格式如下:其中命令是bootm,实现函数是do_bootm函数。
#define Struct_Section  __attribute__ ((unused,section (".u_boot_cmd")))
#ifdef  CONFIG_SYS_LONGHELP
#define U_BOOT_CMD(name,maxargs,rep,cmd,usage,help) \
cmd_tbl_t __u_boot_cmd_##name Struct_Section = {#name, maxargs, rep, cmd, usage, help}
#else /* no long help info */
#define U_BOOT_CMD(name,maxargs,rep,cmd,usage,help) \
cmd_tbl_t __u_boot_cmd_##name Struct_Section = {#name, maxargs, rep, cmd, usage}
#endif /* CONFIG_SYS_LONGHELP */


U_BOOT_CMD(
bootm, CONFIG_SYS_MAXARGS, 1, do_bootm,
"boot application image from memory",
"[addr [arg ...]]\n    - boot application image stored in memory\n"
"\tpassing arguments ‘arg ...‘; when booting a Linux kernel,\n"
"\t‘arg‘ can be the address of an initrd image\n"
"\tbdt     - OS specific bd_t processing\n"
"\tcmdline - OS specific command line processing/setup\n"
"\tprep    - OS specific prep before relocation or go\n"
"\tgo      - start OS"
);


4.6:分析/common/cmd_bootm.c中的do_bootm函数:
static bootm_headers_t images; /* pointers to os/initrd/fdt images */
int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
disable_interrupts();
usb_stop();
icache_disable();
dcache_disable();
ret = bootm_load_os(images.os, &load_end, 1); //加载具体的操作系统
images.os.os == IH_OS_LINUX  //如果具体加载的是linux,则有以下
boot_os_fn *boot_fn;
boot_fn = boot_os[images.os.os];//boot_fn指针指向boot_os数组中的特定类型函数
boot_fn(0, argc, argv, &images);//调用do_bootm_linux函数
boot_os_fn * boot_os[] = {
#ifdef CONFIG_BOOTM_LINUX
[IH_OS_LINUX] = do_bootm_linux,
#endif
... ...
}; //由此可知,若加载的是linux系统,则调用do_bootm_linux函数,do_bootm_linuxm在/lib_arm/bootm.c文件里


4.7:分析/lib_arm/bootm.c中的do_bootm_linux函数:
void (*theKernel)(int zero, int arch, uint params);
theKernel = (void (*)(int, int, uint))images->ep;//images->ep(entry point)
setup_start_tag (bd);
... ...
setup_end_tag (bd);
theKernel (0, machid, bd->bi_boot_params); //至此,跳转到linux内核开始执行,系统启动起来
/* does not return */
return 1;

u-boot分析,布布扣,bubuko.com

u-boot分析

标签:style   文件   os   art   cti   for   

原文地址:http://blog.csdn.net/qiaojianqj/article/details/37348469

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!