![U-boot分析与移植(3)----U-boot stage2分析_第1张图片](http://img.e-com-net.com/image/info5/4542552a3a97469787359336a152ea39.jpg)
一来到void start_armboot (void)函数,马上出现两个很重要的数据结构gd_t和bd_t
1、gd_t : global data数据结构定义,位于文件 include/asm-arm/global_data.h。其成员主要是一些全局的系统初始化参数。
- typedef struct global_data {
- bd_t *bd;
- unsigned long flags;
- unsigned long baudrate;
- unsigned long have_console;
- unsigned long reloc_off;
- unsigned long env_addr;
- unsigned long env_valid;
- unsigned long fb_base;
- #ifdef CONFIG_VFD
- unsigned char vfd_type;
- #endif
- #if 0
- unsigned long cpu_clk;
- unsigned long bus_clk;
- unsigned long ram_size;
- unsigned long reset_status;
- #endif
- void **jt;
- } gd_t;
2.、bd_t :board info数据结构定义,位于文件 include/asm-arm/u-boot.h。保存板子参数。
- typedef struct bd_info {
- int bi_baudrate;
- unsigned long bi_ip_addr;
- unsigned char bi_enetaddr[6];
- struct environment_s *bi_env;
- ulong bi_arch_number;
- ulong bi_boot_params;
- struct
- {
- ulong start;
- ulong size;
- } bi_dram[CONFIG_NR_DRAM_BANKS];
- #ifdef CONFIG_HAS_ETH1
-
- unsigned char bi_enet1addr[6];
- #endif
- } bd_t;
分配一个存储全局数据的区域,地 址给指针 gd
- gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t));
清0并分配空间
- memset ((void*)gd, 0, sizeof (gd_t));
在gd前面的位置给 gd->bd赋值地址
- gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));
清0并分配空间
- memset (gd->bd, 0, sizeof (bd_t));
执行一系列初始化函数
- for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
- if ((*init_fnc_ptr)() != 0) {
- hang ();
- }
- }
假如函数指针指向的函数返回值不为0,那么在hang()里就会死循环,初始化失败
- void hang (void)
- {
- puts ("### ERROR ### Please RESET the board ###\n");
- for (;;);
- }
函数列表如下:
每个初始化函数正常情况下返回值是0
- init_fnc_t *init_sequence[] = {
- cpu_init,
- board_init,
- interrupt_init,
- env_init,
- init_baudrate,
- serial_init,
- console_init_f,
- display_banner,
接着进行一些NOR FLASH,LCD,串口,控制台,sd卡,网卡等初始化,不一一列举了。
终于来到重要的时刻了 - -#
进入一个死循环
- for (;;)
- {
- main_loop ();
- }
继续跟踪
发现在bootdelay时间内按下键进入命令行,用run_command来解析命令
- #if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
- s = getenv ("bootdelay");
- bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY;
-
- debug ("### main_loop entered: bootdelay=%d\n\n", bootdelay);
如果CONFIG_BOOTDELAY已经定义,用s得到环境变量bootdelay,然后倒数启动内核
- #ifdef CONFIG_BOOTCOUNT_LIMIT
- if (bootlimit && (bootcount > bootlimit)) {
- printf ("Warning: Bootlimit (%u) exceeded. Using altbootcmd.\n",
- (unsigned)bootlimit);
- s = getenv ("altbootcmd");
- }
- else
- #endif /* CONFIG_BOOTCOUNT_LIMIT */
- s = getenv ("bootcmd");
CONFIG_BOOTCOUNT_LIMIT是设置u-boot启动次数的限制
最后s = getenv ("bootcmd");获得启动参数
启动命令解析
在run_command 函数里最终执行命令
-
- if ((cmdtp->cmd) (cmdtp, flag, argc, argv) != 0) {
- rc = -1;
- }
这是一个命令结构体,原型如下:
- struct cmd_tbl_s {
- char *name;
- int maxargs;
- int repeatable;
- int (*cmd)(struct cmd_tbl_s *, int, int, char *[]);
- char *usage;
正常情况下就会执行U_BOOT_CMD命令,U_BOOT_CMD宏定义一个命令,命令宏原型如下:
-
- #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}
假若上面是传入的是一个bootm命令启动内核,将会调用相应的
U_BOOT_CMD里的do_bootm函数
- U_BOOT_CMD(
- bootm, CFG_MAXARGS, 1, do_bootm,
- "bootm - boot application image from memory\n",
- "[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"
在do_bootm函数里,将用switch case检查内核zImage类型,解压方式,操作系统等,因为zImage是自解压的,不用解压
- switch (hdr->ih_os) {
- default:
- case IH_OS_LINUX:
-
- do_bootm_linux (cmdtp, flag, argc, argv,
- addr, len_ptr, verify);
- break;
最后,将进入Armlinux.c的do_bootm_linux函数启动Linux内核
U_Boot也是通过标记列表向内核传递参数的
- #ifdef CONFIG_CMDLINE_TAG
- char *commandline = getenv ("bootargs");
- #endif
CONFIG_CMDLINE_TAG在smdk2410.h里已经定义了
theKernel指向内核 存放的地址,(对于ARM架构的CPU,通常是0x30008000),
/*声明内核的入口函数指针*/
- void (*theKernel)(int zero, int arch, uint params);
/*把内核入口地址赋值给theKernel,hdr是image_header_t结构体,指向uImage头部 ,ih_ep是内核的入口点(Entry Point)*/
- theKernel = (void (*)(int, int, uint))ntohl(hdr->ih_ep);
/*最后是对内核入口函数的调用,bd->bi_arch_number是这个板子机器类型ID, bd->bi_boot_params是传给内核的参数,从标记列表地址开始*/
- theKernel (0, bd->bi_arch_number, bd->bi_boot_params);
- * CPU register settings
- o r0 = 0.
- o r1 = machine type number.
- o r2 = physical address of tagged list in system RAM.
- * CPU mode
- o All forms of interrupts must be disabled (IRQs and FIQs.)
- o The CPU must be in SVC mode. (A special exception exists for Angel.)
- * Caches, MMUs
- o The MMU must be off.
- o Instruction cache may be on or off.
- o Data cache must be off and must not contain any stale data.
- * Devices
- o DMA to/from devices should be quiesced.
- * The boot loader is expected to call the kernel image by jumping directly to the first instruction of the kernel image.