cmd_tbl_t;
extern cmd_tbl_t __u_boot_cmd_start; extern cmd_tbl_t __u_boot_cmd_end;
#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}
#define U_BOOT_CMD_MKENT(name,maxargs,rep,cmd,usage,help) / {#name, maxargs, rep, cmd, usage, help}
uboot中的命令使用U_BOOT_CMD这个宏声明来注册进系统,链接脚本会把所有的cmd_tbl_t结构体放在相邻的地方。 链接脚本中的一些内容如下: . = .; __u_boot_cmd_start = .; .u_boot_cmd : { *(.u_boot_cmd) } __u_boot_cmd_end = .; 可见,__u_boot_cmd_start 和__u_boot_cmd_end 分别对应命令结构体在内存中开始和结束的地址。
3。abortboot函数的分析 abortboot是uboot在引导期间的延时函数。期间可以按键进入uboot的命令行。 common/main.c static __inline__ int abortboot(int bootdelay) { int abort = 0; printf("Hit any key to stop autoboot: %2d ", bootdelay);
#if defined CONFIG_ZERO_BOOTDELAY_CHECK //如果定义了这个宏,即使定义延时为0,也会检查一次是否有按键按下。只要在这里执行之前按键,还是能进入uboot的命令行。 if (bootdelay >= 0) { if (tstc()) { /* we got a key press */ 测试是否有按键按下 (void) getc(); /* consume input */接收按键值 puts ("/b/b/b 0"); abort = 1; /* don't auto boot */修改标记,停止自动引导 } } #endif
while ((bootdelay > 0) && (!abort)) { //如果延时大于零并且停止标记没有赋值则进入延时循环,直到延时完或者接收到了按 键 int i;
--bootdelay; /* delay 100 * 10ms */ 每秒中测试按键100次,之后延时10ms。 for (i=0; !abort && i<100; ++i) { if (tstc()) { /* we got a key press */ abort = 1; /* don't auto boot */*/修改标记,停止自动引导 bootdelay = 0; /* no more delay */延时归零 (void) getc(); /* consume input */获取按键 break; } udelay(10000);//延时10000us,也就是10ms }
printf("/b/b/b%2d ", bootdelay);//打印当前剩余时间 }
putc('/n'); return abort;//返回结果:1-停止引导,进入命令行; 0-引导内核。 }
可以看到uboot延时的单位是秒,如果想提高延时的精度,比如想进 10ms级的延时,将udelay(10000)改为udelay(100)就可以了 。
4。引导命令 include/configs/smartarm.h
#define CONFIG_BOOTCOMMAND "run yboot " #define CONFIG_EXTRA_ENV_SETTINGS / "serverip=192.168.1.110/0" / "gatewayip=192.168.1.254/0" / "ipaddr=192.168.1.164/0" / "bootfile=uImage/0"/ / "upkernel=" "tftp 80008000 uImage;"/ "nand erase clean 0x00200000 $(filesize);"/ "nand write.jffs2 0x80008000 0x00200000 $(filesize);"/ "setenv kernelsize $(filesize); saveenv/0"/ / "upsafefs=" "tftp 80008000 safefs.cramfs;"/ "nand erase clean 0x00600000 $(filesize);"/ "nand write.jffs2 0x80008000 0x00600000 $(filesize)/0"/ / "yboot=" "nand read.jffs2 0x81000000 0x00200000 $(filesize);"/ "bootm 81000000/0"/ / "safemode=" "setenv bootargs root=/dev/mtdblock3 console=ttyS0,115200, mem=64M rootfstype=cramfs; run yboot/0"/ / "zhiyuan=" "run upsafefs; run upkernel/0"
可见,引导内核其实就是将内核读取到内存中然后再跳到那个地方引导。
5。run_command common/main.c int run_command (const char *cmd, int flag) { cmd_tbl_t *cmdtp; char cmdbuf[CONFIG_SYS_CBSIZE]; /* working copy of cmd */ char *token; /* start of token in cmdbuf */ char *sep; /* end of token (separator) in cmdbuf */ char finaltoken[CONFIG_SYS_CBSIZE]; char *str = cmdbuf; char *argv[CONFIG_SYS_MAXARGS + 1]; /* NULL terminated */ int argc, inquotes; int repeatable = 1; int rc = 0;
clear_ctrlc(); /* forget a |