先分一下,uboot如何解析我们输进去的命令,其中 然后是在表中查找是否有输入的命令,后续还要做一些命令合格性的检查 其中有个结构体需要注意,每个命令,都有一个名字,还有对应的参数,以及执行命令的函数,这些都被打包放在一起结构体变量中 在 其中 再看一下 如果现在执行 展开后,发现是定义了一个 这里面的usage和help,是替换上面的字符串,其中 接下来自己写一个命令试试看,在common目录下创建文件cmd_hello.c 修改command目录下的Makefile文件,增加一个源文件cmd_hello.o,编译烧录即可 通过之前的分析,可以知道,内核是由bootm启动,所以接下来分析整个bootcmd命令的参数 这条命令,第一句话,将内核从kernel分区读出,并放到SDRAM的指定地址,然后从这个地址启动内核 在uboot中,一般会将分区大小写死 所以第一句话等价于下面的,从0x00060000读取内核,大小为0x00200000,存放到0x30007FC0 接下来看如何从nand中读取内核,重点在于 读出了内核后,接下来如何启动,分析bootm 首先分析一下uImage的结构,它是一个64字节的头部+真正的内核组成,其中有两项比较重要的参数 bootm命令先去读取uImage的头部信息,如果发现当前内核并不位于它指定的加载地址,就将内核移到指定的加载地址,然后uboot需要告诉内核一些启动参数,这些参数是存放到某些地址,然后内核去这些地址去读取对应的参数,就是所谓的tag,参数传完后,跳转到入口地址执行 启动内核时传递了三个参数,其中
uboot命令的实现
argv[x]
就是用来保存每一条指令,uboot支持多条命令一起输入,用分号;隔开/* Extract arguments */ if ((argc = parse_line (finaltoken, argv)) == 0) { rc = -1; /* no command at all */ continue; }
/* Look up command in command table */ if ((cmdtp = find_cmd(argv[0])) == NULL) { printf ("Unknown command '%s' - try 'help'n", argv[0]); rc = -1; /* give up after bad command */ continue; } /* found - check max args */ if (argc > cmdtp->maxargs) { printf ("Usage:n%sn", cmdtp->usage); rc = -1; continue; }
struct cmd_tbl_s { char *name; /* Command Name */ int maxargs; /* maximum number of arguments */ int repeatable; /* autorepeat allowed? */ /* Implementation function */ int (*cmd)(struct cmd_tbl_s *, int, int, char *[]); char *usage; /* Usage message (short) */ #ifdef CFG_LONGHELP char *help; /* Help message (long) */ #endif #ifdef CONFIG_AUTO_COMPLETE /* do auto completion on the arguments */ int (*complete)(int argc, char *argv[], char last_char, int maxv, char *cmdv[]); #endif };
find_cmd
中,通过一个for循环去找命令是否存在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++; } }
__u_boot_cmd_start
和__u_boot_cmd_end
是在链接脚本中指定的. = .; __u_boot_cmd_start = .; .u_boot_cmd : { *(.u_boot_cmd) } __u_boot_cmd_end = .;
u_boot_cmd
这个段到底是干嘛的,可以找到两个宏定义,第一个定义了一个段,第二个在执行命令时进行宏展开#define Struct_Section __attribute__ ((unused,section (".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 0x30007FC0
,看看跟宏U_BOOT_CMD
有什么关系U_BOOT_CMD( bootm, CFG_MAXARGS, 1, do_bootm, "bootm - boot application image from memoryn", "[addr [arg ...]]n - boot application image stored in memoryn" "tpassing arguments 'arg ...'; when booting a Linux kernel,n" "t'arg' can be the address of an initrd imagen" #ifdef CONFIG_OF_FLAT_TREE "tWhen booting a Linux kernel which requires a flat device-treen" "ta third argument is required which is the address of the of then" "tdevice-tree blob. To boot that kernel without an initrd image,n" "tuse a '-' for the second argument. If you do not pass a thirdn" "ta bd_info struct will be passed insteadn" #endif );
cmd_tbl_t
类型的结构体变量__u_boot_cmd_bootm
,后面的Struct_Section
也宏展开,发现段属性被强制设为u_boot_cmd
段cmd_tbl_t __u_boot_cmd_bootm Struct_Section = {"bootm", CFG_MAXARGS, 1, do_bootm, usage, help} Struct_Section __attribute__ ((unused,section (".u_boot_cmd")))
可以发现usage替换的后面是有逗号的,help的字符串双引号之间没有任何间隔符号#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 world uboot sb thingsn"); } U_BOOT_CMD( hello, CFG_MAXARGS, 1, do_hello, "hello - this is a first uboot cmd, hello worldn", "this is a infomation for help, long string" );
uboot启动内核
s = getenv ("bootcmd"); printf("Booting Linux ...n"); run_command (s, 0);
bootcmd=nand read.jffs2 0x30007FC0 kernel; bootm 0x30007FC0
#define MTDPARTS_DEFAULT "mtdparts=nandflash0:256k@0(bootloader)," "128k(params)," "2m(kernel)," "-(root)"
bootcmd=nand read.jffs2 0x30007FC0 kernel; bootcmd=nand read.jffs2 0x30007FC0 0x00060000 0x00200000;
nand_read_opts
int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) { ... if (read) { /* read */ nand_read_options_t opts; memset(&opts, 0, sizeof(opts)); opts.buffer = (u_char*) addr; opts.length = size; opts.offset = off; opts.quiet = quiet; ret = nand_read_opts(nand, &opts); } ... }
bootm 0x30007FC0
ih_load加载地址
和ih_ep入口地址
typedef struct image_header { uint32_t ih_magic; /* Image Header Magic Number */ uint32_t ih_hcrc; /* Image Header CRC Checksum */ uint32_t ih_time; /* Image Creation Timestamp */ uint32_t ih_size; /* Image Data Size */ uint32_t ih_load; /* Data Load Address */ uint32_t ih_ep; /* Entry Point Address */ uint32_t ih_dcrc; /* Image Data CRC Checksum */ uint8_t ih_os; /* Operating System */ uint8_t ih_arch; /* CPU architecture */ uint8_t ih_type; /* Image Type */ uint8_t ih_comp; /* Compression Type */ uint8_t ih_name[IH_NMLEN]; /* Image Name */ } image_header_t;
memmove (&header, (char *)addr, sizeof(image_header_t)); memmove ((void *) ntohl(hdr->ih_load), (uchar *)data, len); do_bootm_linux(...); setup_start_tag (bd); //设置参数 setup_serial_tag (¶ms); setup_revision_tag (¶ms); setup_memory_tags (bd); setup_commandline_tag (bd, commandline); 等等 theKernel = (void (*)(int, int, uint))ntohl(hdr->ih_ep); theKernel (0, bd->bi_arch_number, bd->bi_boot_params); //启动内核
bd->bi_arch_number
是机器ID,bd->bi_boot_params
是传递的参数地址
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算