03.uboot分析之源码第二阶段
【摘要】
首先要明确:uboot目标是从flash读出内核(nand read.jffs2 0x30007FC0 kernel;),启动它(bootm 0x30007FC0)。
一、分析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"}
);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
二、实验增加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",
);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
将文件拖入linux中common文件夹下,修改common下的makefile,增加cmd_hello.o。使用make 100ask24x0_config命令重新编译uboot。编译完成,将uboot.bin烧写进板子。输入help命令后会输出hello,word!等。
文章来源: blog.csdn.net,作者:嵌入式与Linux那些事,版权归原作者所有,如需转载,请联系作者。
原文链接:blog.csdn.net/qq_16933601/article/details/102827639
【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)