首先要明确:uboot目标是从flash读出内核(nand read.jffs2 0x30007FC0 kernel;),启动它(bootm 0x30007FC0)。
一、分析uboot源码
/*初始化nor flash*/
#ifndef CFG_NO_FLASH
/* configure available FLASH banks */
size = flash_init ();
display_flash_config (size);
#endif /* CFG_NO_FLASH */
/*初始化nand flash*/
#if (CONFIG_COMMANDS & CFG_CMD_NAND)
puts ("NAND: ");
nand_init(); /* go init the NAND */
#endif
/*完成以上两个步骤后,已经有能力去读写flash*/
/*环境变量的初始化,uboot中输入printf后输出的一些变量如波特率,IP地址等*/
/* initialize environment */
env_relocate ();
/* main_loop() can return to retry autoboot, if so just run it again. 跳转mainloop*/
for (;;) {
main_loop ();
}
main_loop
/*启动命令*/
#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 */
/*启动内核bootcmd=nand read.jffs2 0x30007FC0 kernel; bootm 0x30007FC0*/
s = getenv ("bootcmd");
/*倒数计时*/
if (bootdelay >= 0 && s && !abortboot (bootdelay)) {
# ifdef CONFIG_AUTOBOOT_KEYED
int prev = disable_ctrlc(1); /* disable Control C checking */
# endif
/*如果倒数计时前没有按空格 打印那句话*/
# ifndef CFG_HUSH_PARSER
{
printf("Booting Linux ...\n");
/*运行上面s命令,内核的启动依赖于bootcmd*/
run_command (s, 0);
}
# else
parse_string_outer(s, FLAG_PARSE_SEMICOLON |
FLAG_EXIT_FROM_LOOP);
# endif
/*启动菜单*/
run_command("menu", 0)
/*死循环 等待输入*/
PROMPT:
#ifdef CFG_HUSH_PARSER
parse_file_outer();
/* This point is never reached */
for (;;);
#else
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 (CFG_PROMPT);
/*又是bootcmd*/
rc = run_command (lastcommand, flag);
/*处理宏*/
/* find macros in this token and replace them */
process_macros (token, finaltoken);
/*解析输入的文字*/
/*例如 在uboot输入 md.w 0 则argv[0]="md.w" argv[1]="0"*/
if ((argc = parse_line (finaltoken, argv)) == 0) {
rc = -1; /* no command at all */
continue;
/*查找名字的一个结构体,里面有name,maxargs等参数*/
if ((cmdtp = find_cmd(argv[0])) == NULL) {
printf ("Unknown command '%s' - try 'help'\n", argv[0]);
rc = -1; /* give up after bad command */
continue;
/*进入find_cmd*/
/*链接文件中定义的
__u_boot_cmd_start = .;
.u_boot_cmd : { *(.u_boot_cmd) }
__u_boot_cmd_end = .;
*/
for (cmdtp = &__u_boot_cmd_start;
cmdtp != &__u_boot_cmd_end;
cmdtp++) {
/*比较名字成功则返回结构体*/
if (strncmp (cmd, cmdtp->name, len) == 0) {
if (len == strlen (cmdtp->name))
return cmdtp; /* full match */
/*不成功则指向下一个*/
cmdtp_temp = cmdtp; /* abbreviated command ? */
n_found++;
/*bootcmd到底是什么东西,搜索bootcmd*/
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"
#ifdef CONFIG_OF_FLAT_TREE
"\tWhen booting a Linux kernel which requires a flat device-tree\n"
"\ta third argument is required which is the address of the of the\n"
"\tdevice-tree blob. To boot that kernel without an initrd image,\n"
"\tuse a '-' for the second argument. If you do not pass a third\n"
"\ta bd_info struct will be passed instead\n"
#endif
/*command.h*/
#define Struct_Section _attribute_((unused,section(".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}
/*展开U_BOOT_CMD*/
/*定义了 __u_boot_cmd_结构体,结构体类型cmd_tbl_t 。强制把段属性设置为section(".u_boot_cmd"),正好和链接文件对应。U_BOOT_CMD宏展开后如下。所有用U_BOOT_CMD声明的都会定义一个__u_boot_cmd_结构体。所有的命令都会集中到链接文件的__u_boot_cmd_。开始就是__u_boot_cmd_start ,结束就是__u_boot_cmd_end*/
cmd_tbl_t __u_boot_cmd_##bootm _attribute_((unused,section(".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"}
);
二、实验增加hello word
hello_command.c
/*包含Cmd_bootm.c(common)头文件*/
#include <common.h>
#include <watchdog.h>
#include <command.h>
#include <image.h>
#include <malloc.h>
#include <zlib.h>
#include <bzlib.h>
#include <environment.h>
#include <asm/byteorder.h>
int do_hello (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
printf ("hello,word!, %d\n",argc);
/*打印参数看下*/
for (i=0;i<argc;i++)
{
printf ("argv[]: %s\n",i,argv[i]);
}
return 0;
}
U_BOOT_CMD(
hello, CFG_MAXARGS, 1, do_bootm,
"hello- just for test\n",
"hello- long help ...................\n",
);
将文件拖入linux中common文件夹下,修改common下的makefile,增加cmd_hello.o。使用make 100ask24x0_config命令重新编译uboot。编译完成,将uboot.bin烧写进板子。输入help命令后会输出hello,word!等。