03.uboot分析之源码第二阶段

首先要明确: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!等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嵌入式与Linux那些事

您的鼓励将使我写出更好的文章

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值