u-boot增加自定义命令

0、说明

本文基于U-Boot 2022.01-v2.07版本进行分析。

1、u-boot编译流程简要分析

2、u-boot启动流程简要分析

3、u-boot增加自定义命令

  • 3.1、u-boot命令行实现简要分析

    • 1)cli_init命令行初始化
      cli_init定义在common\cli.c中:
      void cli_init(void)
      {
      #ifdef CONFIG_HUSH_PARSER
      	u_boot_hush_start();
      #endif
      
      #if defined(CONFIG_HUSH_INIT_VAR)
      	hush_init_var();
      #endif
      }
      
      它的调用是在common\main.c文件的u-boot主循环main_loop中。
      我的u-boot的配置只使能了CONFIG_HUSH_PARSER,因此其只调用了u_boot_hush_start:
      int u_boot_hush_start(void)
      {
      	if (top_vars == NULL) {
      		top_vars = malloc(sizeof(struct variables));
      		top_vars->name = "HUSH_VERSION";
      		top_vars->value = "0.01";
      		top_vars->next = NULL;
      		top_vars->flg_export = 0;
      		top_vars->flg_read_only = 1;
      #ifdef CONFIG_NEEDS_MANUAL_RELOC
      		u_boot_hush_reloc();
      #endif
      	}
      	return 0;
      }
      
      主要完成了全局指针top_vars的初始化。
    • 2)命令的执行过程
      main_loop中的autoboot_command函数开始追踪命令的执行过程:
      common\autoboot.c: autoboot_command()
      => common\cli.c: run_command_list()
      => common\cli_simple.c:cli_simple_run_command_list()
      => common\cli_simple.c:cli_simple_run_command()
      => common\command.c:cmd_process()
      => common\command.c:find_cmd()
      
      autoboot_command最终会执行find_cmd(),这个等会分析。
      同样从main_loop中的cli_loop函数开始追踪命令的执行过程:
      common\cli.c:cli_loop()
      => common\cli_simple.c:cli_simple_loop()
      => common\cli.c:run_command_repeatable()
      => common\cli_simple.c:cli_simple_run_command()
      => common\command.c:cmd_process()
      => common\command.c:find_cmd()
      
      cli_loop()最终也会会执行find_cmd()
    • 3)find_cmd
      find_cmd的实现如下:
      struct cmd_tbl *find_cmd(const char *cmd)
      {
      	struct cmd_tbl *start = ll_entry_start(struct cmd_tbl, cmd);
      	const int len = ll_entry_count(struct cmd_tbl, cmd);
      	return find_cmd_tbl(cmd, start, len);
      }
      
      它主要是通过ll_entry_start取出命令表,并返回命令表。ll_entry_start的数据结构如下定义:
      #define ll_entry_start(_type, _list)					\
      ({									\
      	static char start[0] __aligned(CONFIG_LINKER_LIST_ALIGN)	\
      		__attribute__((unused))					\
      		__section(".u_boot_list_2_"#_list"_1");			\
      	(_type *)&start;						\
      })
      
      从上面可以看出,这些命令会放在特定的代码段里,构成一个命令表。
  • 3.2、实现自定义命令

    • 1)实现自定义命令
      u-boot里提供了一个专门的宏来定义命令,这个宏如下:
      #define U_BOOT_CMD(_name, _maxargs, _rep, _cmd, _usage, _help)		\
      U_BOOT_CMD_COMPLETE(_name, _maxargs, _rep, _cmd, _usage, _help, NULL)
      
      U_BOOT_CMD_COMPLETE定义如下:
      #define U_BOOT_CMD_COMPLETE(_name, _maxargs, _rep, _cmd, _usage, _help, _comp) \
      ll_entry_declare(struct cmd_tbl, _name, cmd) =			\
      U_BOOT_CMD_MKENT_COMPLETE(_name, _maxargs, _rep, _cmd,	\
      				_usage, _help, _comp);
      
      U_BOOT_CMD_MKENT_COMPLETE定义如下:
      #define U_BOOT_CMD_MKENT_COMPLETE(_name, _maxargs, _rep, _cmd,		\
      		_usage, _help, _comp)			\
      { #_name, _maxargs,					\
       _rep ? cmd_always_repeatable : cmd_never_repeatable,	\
       _cmd, _usage, _CMD_HELP(_help) _CMD_COMPLETE(_comp) }
      
      至此可以看出U_BOOT_CMD所做的事情就是通过ll_entry_declare定义了struct cmd_tbl,并对其进行赋值。
    • 2)示例
      以一个简单的dhcp命令为例,看下u-boot命令的定义:
      static int do_dhcp(struct cmd_tbl *cmdtp, int flag, int argc,
         char *const argv[])
      {
      	return netboot_common(DHCP, cmdtp, argc, argv);
      }
      
      U_BOOT_CMD(
      	dhcp,	3,	1,	do_dhcp,
      	"boot image via network using DHCP/TFTP protocol",
      	"[loadAddress] [[hostIPaddr:]bootfilename]"
      );
      
      主要就是按找命令的要求定义命令执行函数,最后再通过U_BOOT_CMD进行定义即可,使用非常简单。
    • 3)在程序中执行命令
      u-boot也可以在代码中,通过编写代码执行命令,也提供了对应的函数:
      int run_command(const char *cmd, int flag);
      
      例如在u-boot里实现自定义升级固件的代码,可以这样写:
      int do_upgrade(const ulong size, const int upgrade_type) 
      {
      	char buf[96];
      	ulong eraseblk = size / MMC_BLK_SIZE + ((size % MMC_BLK_SIZE) ? 1 : 0);
      
      	sprintf(buf,
                  "mmc dev %d;mmc erase 0x%lx 0x%lx;mmc write 0x%lx 0x%lx 0x%lx;",
                  CONFIG_HTTPD_MMC_DEV,
                  (unsigned long int)CONFIG_HTTPD_UBOOT_ADDRESS / MMC_BLK_SIZE,
                  (unsigned long int)eraseblk,
                  (unsigned long int)CONFIG_HTTPD_UPLOAD_RAM_ADDRESS,
                  (unsigned long int)CONFIG_HTTPD_UBOOT_ADDRESS / MMC_BLK_SIZE,
                  (unsigned long int)eraseblk);
      
      	printf("Executing: %s\n\n", buf);
      	return(run_command(buf, 0));
      }
      

    4、u-boot的DM驱动模型

  • 17
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值