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_PARSERu_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_RELOCu_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驱动模型

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/722777.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++基础入门 --- 练习案例【1-10】

文章目录 C基础入门 --- 练习案例1.三只小猪称体重2.猜数字3.水仙花数4.敲桌子5.乘法口诀表6.五只小猪称体重7.数组元素逆置8.考试成绩统计9.冒泡排序10.结构体数组排序 C基础入门 — 练习案例 1.三只小猪称体重 说明:有三只小猪分别为A、B、C,分别输入三只小猪的…

【Web】浅浅地聊JDBC java.sql.Driver的SPI后门

目录 SPI定义 SPI核心方法和类 最简单的SPIdemo演示 回顾JCBC基本流程 为什么JDBC要有SPI JDBC java.sql.Driver后门利用与验证 SPI定义 SPI: Service Provider Interface 官方定义: 直译过来是服务提供者接口,学名为服务发现机制 它通…

acme.sh申请ssl免费证书

参考 https://blog.csdn.net/fyhju1/article/details/120452141 获取域名服务商AccessKey ID及AccessKey Secret https://help.aliyun.com/zh/ram/user-guide/create-an-accesskey-pair 安装ACME curl https://get.acme.sh | sh source ~/.bashrc如果使用root用户进行安装&…

如何在windows上像linux的ssh一样远程访问其它windows

主要分成两部分: 1. 如何远程执行指令 使用psexec,示例如下: PsExec64.exe \\远程计算机ip -u 用户名 -p 密码 -i cmd.exe 这样你就能连接到远程计算机上执行命令了,效果如下 2. 如何远程拷贝文件 分成两步: net…

【语法基础练习】1.变量、输入输出、表达式与顺序语句

🌸博主主页:釉色清风🌸文章专栏:算法练习🌸今日语录:You don’t know until you try. 文章简介:下面的题目是AcWing网站语法基础练习篇的第一小节,内容基础,难度&#xf…

计算机组成原理-累加器实验——沐雨先生

一、实验目的 1.理解累加器的概念和作用 2.连接运算器、存储器和累加器,熟悉计算机的数据通路 3.掌握使用微命令执行各种操作的方法。 二、实验要求 1.做好实验预习,读懂实验电路图,熟悉实验元器件的功能特性和使用方法。在实验之前设计…

list链表的创建,排序,插入, test ok

1. 链表的建立&#xff0c;打印 #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <stack> #include <iostream> #include <string.h> #include <string>using namespace std;struct node {int data;s…

Vue项目性能分析工具: vue-cli-plugin-webpack-bundle-analyzer

在优化项目的时候&#xff0c;每次打包后只知道包文件大&#xff0c;却不知道那个文件大&#xff0c;那个文件还有优化的空间&#xff0c;所以&#xff0c;推荐一款工具&#xff0c;只要在项目中安装配置一下&#xff0c;便可以一目了然的呈现出打包后资源所占的比例&#xff0…

【贪心算法】摆动序列

如果连续数字之间的差严格地在正数和负数之间交替&#xff0c;则数字序列称为 摆动序列 。第一个差&#xff08;如果存在的话&#xff09;可能是正数或负数。仅有一个元素或者含两个不等元素的序列也视作摆动序列。 例如&#xff0c; [1, 7, 4, 9, 2, 5] 是一个 摆动序列 &…

【vue项目适配可借助于插件lib-flexible 和postcss-px2rem】

前言&#xff1a;vue项目适配可借助于插件lib-flexible 和postcss-px2rem。 lib-flexible插件的作用&#xff1a;根据屏幕尺寸不同设置html根标签的字体大小&#xff0c;1rem即等于根标签的字体大小。 postcss-px2rem插件的作用&#xff1a;将px转为rem,如此以来我们可以在开…

Python与HTTP服务交互

Python与HTTP服务交互&#xff0c;可以通过http.client requests RissionPage等。 http.client标准库 http.client 是Python标准库中的一个模块&#xff0c;用于发送HTTP请求。这个模块提供了一个低级别的接口&#xff0c;允许你手动构建HTTP请求并处理响应。下面是对 http.c…

(科目三)数据库基础知识

1、基本概念 1.1 数据库 1、数据、信息和数据处理 数据是指表达信息的某种物理符号&#xff1b; 信息是对客观事物的反映&#xff0c;是为某一特定目的二提供的决策数据&#xff1b; 数据处理是指将数据转换成信息的过程&#xff0c;是对各类型的数据进行收集、整理、存储、…

军用技术民用开花,Shokz韶音要做下一个“AirPods”

Shokz韶音对打造消费级骨传导耳机的执念始于2007年。 在这之前&#xff0c;它已经成为亚洲最大的军用耳机生产商&#xff0c;以代工订单为主的商业模式是Shokz韶音的主营业务。虽然Shokz韶音靠代工赚得了第一桶金&#xff0c;但军用耳机的垂直细分市场容量有限&#xff0c;市场…

java构造函数

Java中的构造函数是一种特殊类型的方法&#xff0c;用于在创建对象时初始化对象的状态。构造函数与类同名&#xff0c;没有返回类型&#xff0c;并且在创建对象时自动调用。它可以用于执行必要的初始化操作&#xff0c;例如设置对象的初始值、分配内存等。以下是一个简单的Java…

Python 实现冒泡排序算法

Python 实现冒泡排序算法 下面是用 Python 实现的冒泡排序算法示例代码&#xff1a; def bubble_sort(arr):n len(arr)# 遍历数组元素for i in range(n):# 每次遍历都将最大的元素移动到最后for j in range(0, n-i-1):# 如果相邻的元素逆序&#xff0c;则交换它们if arr[j] …

Kafka数据推送配置 | 如何设置账号密码验证?

背景&#xff1a;之前资产信息用网络接口进行数据推送&#xff0c;但是接口推送需要验证而且反应较慢。Kafak中间件提供了另一种可行的数据推送方式&#xff0c;它可以进行消息队列推送&#xff0c;且反应速度快。但是Kafka需部署在公网环境&#xff0c;并进行登录验证&#xf…

excel 动态列导出

excel动态列&#xff0c;只好用poi来写了&#xff0c;也并不复杂&#xff0c;一样就这个件事情抽像为几步&#xff0c;就是套路了&#xff0c;开发效率就上去了。 1 准备空模板 导出操作与excel模板的导出一样&#xff0c;可以参考excel导出标准化 2 自定义SheetWriteHandler …

网络信息安全:11个常见漏洞类型汇总

一、SQL注入漏洞 SQL注入攻击&#xff08;SQL Injection&#xff09;&#xff0c;简称注入攻击、SQL注入&#xff0c;被广泛用于非法获取网站控制权&#xff0c;是发生在应用程序的数据库层上的安全漏洞。 在设计程序&#xff0c;忽略了对输入字符串中夹带的SQL指令的检查&…

前端上传图片后如何回显图片

在前端上传图片后&#xff0c;可以使用以下几种方法进行回显&#xff1a; 1.使用FileReader API&#xff1a;这是一种常见的方法。在用户选择图片后&#xff0c;可以使用FileReader对象读取图片文件&#xff0c;并将其转换为Base64编码的字符串。然后&#xff0c;将该Base64字…

嵌入式学习 Day 30

消息队列、共享内存、信号灯: 1.IPC对象&#xff08;内存文件&#xff09; 1.ipcs 查看系统重的消息队列、共享内存、信号灯的信息 2.ipcrm 删除消息队列、共享内存、信号灯 ipcrm -Q/-M/-S key ipcrm -q/-m/-s 消息队列ID/共享内存ID/信号灯ID 2.消息队列 1.操作…