ARM uboot 源码分析7 - uboot的命令体系
一、uboot 命令体系基础
1、使用 uboot 命令
(1) uboot 启动后进入命令行环境下,在此输入命令按回车结束,uboot 会收取这个命令然后解析,然后执行。
2、uboot 命令体系实现代码在哪里
(1) uboot 命令体系的实现代码在 uboot/common/cmd_xxx.c 中。有若干个 .c 文件和命令体系有关。(还有 command.c main.c 也是和命令有关的)
3、每个命令对应一个函数
(1) 每一个 uboot 的命令背后都对应一个函数。这就是 uboot 实现命令体系的一种思路和方法。
(2) 我们要找到每一个命令背后所对应的那个函数,而且要分析这个函数和这个命令是怎样对应起来的。
4、命令参数以 argc & argv 传给函数
(1) 有些 uboot 的命令还支持传递参数。也就是说命令背后对应的函数接收的参数列表中有 argc 和 argv,然后命令体系会把我们执行命令时的命令+参数(md 30000000 10)以 argc(3)和 argv(argv[0]=md, argv[1]=30000000 argv[2]=10)的方式传递给执行命令的函数。
举例分析,以 help 命令为例:
help 命令背后对应的函数名叫:do_help。在 uboot/common/command.c 的236行。int do_help (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
二、uboot 命令解析和执行过程分析
1、从 main_loop 说起
(1) uboot 启动的第二阶段,在初始化了所有该初始化的东西后,进入了一个死循环,死循环的循环体就是 main_loop。
(2) main_loop 函数执行一遍,就是一个获取命令、解析命令、执行命令的过程。
(3) run_command 函数就是用来执行命令的函数。
2、run_command 函数关键点分析
(1) 控制台命令获取;
(2) 命令解析。parse_line 函数把 “md 30000000 10” 解析成 argv[0]=md, argv[1]=30000000 argv[2]=10;
(3) 在命令集中去查找命令。find_cmd(argv[0]) 函数去 uboot 的命令集合当中搜索有没有 argv[0] 这个命令。
(4) 执行命令。最后用函数指针的方式调用执行了对应函数。
思考:关键点就在于 find_cmd 函数如何查找到这个命令是不是 uboot 的合法支持的命令?这取决于 uboot 的命令体系机制(uboot 是如何完成命令的这一套设计的,命令如何去注册、存储、管理、索引。)。
三、uboot如何处理命令集1
1、可能的管理方式
(1) 数组。结构体数组,数组中每一个结构体成员就是一个命令的所有信息。
(2) 链表。链表的每个节点 data 段就是一个命令结构体,所有的命令都放在一条链表上。这样就解决了数组方式的不灵活。坏处是需要额外的内存开销,然后各种算法(遍历、插入、删除等)需要一定复杂度的代码执行。
(3) 有第三种吗?uboot 没有使用数组或者链表,而是使用了一种新的方式来实现这个功能。
2、命令结构体 cmd_tbl_t
(1) name:命令名称,字符串格式。
(2) maxargs:命令最多可以接收多少个参数。
(3) repeatable:指示这个命令是否可重复执行。重复执行是 uboot 命令行的一种工作机制,就是直接按回车则执行上一条执行的命令。
(4) cmd:函数指针,命令对应的函数的函数指针,将来执行这个命令的函数时,使用这个函数指针来调用。
(5) usage:命令的短帮助信息。对命令的简单描述。
(6) help:命令的长帮助信息。细节的帮助信息。
(7) complete:函数指针,指向这个命令的自动补全的函数。
总结:uboot 的命令体系在工作时,一个命令对应一个 cmd_tbl_t 结构体的一个实例,然后 uboot 支持多少个命令,就需要多少个结构体实例。uboot 的命令体系把这些结构体实例管理起来,当用户输入了一个命令时,uboot 会去这些结构体实例中查找(查找方法和存储管理的方法有关)。如果找到则执行命令,如果未找到则提示命令未知。
3、uboot 实现命令管理的思路
(1) 填充 1 个结构体实例构成一个命令
(2) 给命令结构体实例附加特定段属性(用户自定义段),链接时将带有该段属性的内容链接在一起排列(挨着的,不会夹杂其他东西,也不会丢掉一个带有这种段属性的,但是顺序是乱序的)。
(3) uboot 重定位时,将该段整体加载到 DDR 中。加载到 DDR 中的 uboot 镜像中,带有特定段属性的这一段,其实就是命令结构体的集合,有点像一个命令结构体数组。
(4) 段起始地址和结束地址(链接地址、定义在 u-boot.lds 中)决定了这些命令集的开始和结束地址。
四、uboot 如何处理命令集2
1、uboot 命令定义具体实现分析
(1) U_BOOT_CMD 宏基本分析
这个宏定义在 uboot/include/command.h 中。
U_BOOT_CMD(
version, 1, 1, do_version,
“version - print monitor version\n”,
NULL
);
这个宏替换后变成:
cmd_tbl_t __u_boot_cmd_version attribute ((unused,section (“.u_boot_cmd”))) = {#name, maxargs, rep, cmd, usage, help}
总结:这个 U_BOOT_CMD 宏的理解,关键在于结构体变量的名字和段属性。名字使用 ## 作为连字符,附加了用户自定义段属性,以保证链接时将这些数据结构链接在一起排布。
(2) 链接脚本。
2、find_cmd 函数详解
(1) find_cmd 函数的任务,是从当前 uboot 的命令集中查找是否有某个命令。如果找到则返回这个命令结构体的指针,如果未找到返回 NULL。
(2) 函数的实现思路很简单,如果不考虑命令带点的情况(md.b md.w 这种)就更简单了。查找命令的思路其实就是 for 循环遍历数组的思路,不同的是数组的起始地址和结束地址是用地址值来给定的,数组中的元素个数是结构体变量类型。
3、U_BOOT_CMD 宏详解
(1) 这个宏其实就是定义了一个命令对应的结构体变量,这个变量名和宏的第一个参数有关;因此只要宏调用时,传参的第一个参数不同,则定义的结构体变量不会重名。
4、命令举例:version 命令
五、uboot 中增加自定义命令
1、在已有的 c 文件中直接添加命令
(1) 在uboot/common/command.c中添加一个命令,叫:mycmd。
(2) 在已有的.c文件中添加命令比较简单,直接使用U_BOOT_CMD宏即可添加命令,给命令提供一个do_xxx的对应的函数这个命令就齐活了。
(3) 添加完成后要重新编译工程(make distclean; make x210_sd_config; make),然后烧录新的uboot去运行即可体验新命令。
(4)还可以在函数中使用argc和argv来验证传参。
2、自建一个 c 文件并添加命令
(1) 在uboot/common目录下新建一个命令文件,叫cmd_aston.c(对应的命令名就叫aston,对应的函数就叫do_aston函数),然后在c文件中添加命令对应的U_BOOT_CMD宏和函数。注意头文件包含不要漏掉。
(2) 在uboot/common/Makefile中添加上aston.o,目的是让Make在编译时能否把cmd_aston.c编译链接进去。
(3) 重新编译烧录。重新编译步骤是:make distclean; make x210_sd_config; make
3、体会:uboot 命令体系的优点
(1) uboot的命令体系本身稍微复杂,但是他写好之后就不用动了。我们后面在移植uboot时也不会去动uboot的命令体系。我们最多就是向uboot中去添加命令,就像本节课所做的这样。
(2) 向uboot中添加命令非常简单。
源自朱友鹏老师.
相关文章:

ARM uboot 源码分析7 - uboot的命令体系
一、uboot 命令体系基础 1、使用 uboot 命令 (1) uboot 启动后进入命令行环境下,在此输入命令按回车结束,uboot 会收取这个命令然后解析,然后执行。 2、uboot 命令体系实现代码在哪里 (1) uboot 命令体系的实现代码在 uboot/common/cmd_xx…...

物理服务器与云服务器备份相同吗?
自从云计算兴起以来,服务器备份已经从两阶段的模拟操作演变为由云服务器备份软件执行的复杂的多个过程。但是支持物理服务器和虚拟服务器之间的备份相同吗?主要区别是什么?我们接下来将详细讨论这个问题。 物理服务器与云服务器备份的区别 如果您不熟悉虚拟服务器…...

【Linux】system V共享内存 | 消息队列 | 信号量
🌠 作者:阿亮joy. 🎆专栏:《学会Linux》 🎇 座右铭:每个优秀的人都有一段沉默的时光,那段时光是付出了很多努力却得不到结果的日子,我们把它叫做扎根 目录👉system V共…...

FSC的宣传许可 答疑
【FSC的宣传许可 答疑】问:已经采购了认证产品但没有贴FSC标签,是否可以申请宣传许可?答:不可以。要宣传您采用了FSC认证产品的前提条件之一是产品必须是认证且贴有标签的。如果产品没有贴标,则不可申请宣传许可。您的…...

Leetcode力扣秋招刷题路-0100
从0开始的秋招刷题路,记录下所刷每道题的题解,帮助自己回顾总结 100. 相同的树 给你两棵二叉树的根节点 p 和 q ,编写一个函数来检验这两棵树是否相同。 如果两个树在结构上相同,并且节点具有相同的值,则认为它们是…...

协作对象死锁及其解决方案
协作对象死锁及其解决方案 1.前言 在遇到转账等的需要保证线程安全的情况时,我们通常会使用加锁的方式来保证线程安全,但如果无法合理的使用锁,很可能导致死锁。或者有时我们使用线程池来进行资源的使用,如调用数据库࿰…...

良许也成为砖家啦~
大家好,我是良许。 没错,良许成为砖家啦,绝不是口嗨,有图有真相! 有人会说,咦,这明明是严宇啊,跟你良许有啥关系? 额。。老读者应该知道良许的来历—— 鄙人真名严宇&a…...

Java中的编程细节
前言: 学习过程中有不少时候遇到一些看似简单,做起来事倍功半的问题。我也想自己是个聪明人,学东西一听就懂,一学就会,马上就能灵活应用。但这种事不能强求,要么自己要看个十遍二十遍最后理清逻辑…...

Yolov8从pytorch到caffe (一) 环境搭建
Yolov8从pytorch到caffe (一) 环境搭建 1. 创建虚拟环境2. 安装pytorch与v8相关库3. 测试安装是否成功4. 测试推理图像在windows上配置YOLOv8的环境,训练自己的数据集并转换到caffemodel1. 创建虚拟环境 利用conda创建虚拟环境 conda create -n yolo python=3.8 -y 并进入ac…...

2023年CDGA考试-第16章-数据管理组织与角色期望(含答案)
2023年CDGA考试-第16章-数据管理组织与角色期望(含答案) 单选题 1.在定义任何新组织或尝试改进现有组织之前了解当前组织的哪些方面非常重要? A.企业文化、运营模式和人员 B.业务战略、技术战略、数据战略 C.工具、方法和流程 D.事业环境因素、组织过程资产,行动路线图 …...

Stream——集合数据按照某一字段排序
文章目录前言假设业务场景排序前的准备正序排序1、数据集合的判空 Optional.isPresent()2、使用sort排序3、将排序后的数据流转换为list你以为这样就完了?倒序排序前言 之前,针对Stream链式编程中的几个方法做了大致的说明。详情可以参考: J…...

ubuntu:20.04编译arrow
1)拉取代码 git clone https://github.com/apache/arrow.git 2)切换分支 git checkout apache-arrow-11.0.0 3)拉入测试数据并设置环境变量 pushd arrow git submodule update --init export PARQUET_TEST_DATA"${PWD}/cpp/submodules/parquet-testing/da…...

2023如果纯做业务测试的话,在测试行业有出路吗?
直接抛出我的结论:手工做业务类测试,没有前途。 个人建议赶紧从业务测试跳出来,立即学习代码,走自动化测试方向。目前趋势,业务测试需要用自动化做。 为了让大家能够信服我的观点,本文将从以下方面进行阐…...

golang grpc ssl
无CA场景 在不考虑CA的场景下呢,client有client.key和client.crt,server有server.key和server.crt,生成方式可以如下: $ openssl genrsa -out server.key 2048 $ openssl req -new -x509 -days 3650 \-subj "/CGB/LChina/Og…...

华为服务器驱动下载及安装
1.服务器技术支持网站 https://support.xfusion.com/support/#/zh/home 2.选择软件下载 3.选择服务器型号 4.选择驱动 5.根据需求选择驱动 例如红帽7.4系统 6.安装驱动 自动安装驱动步骤: 1)使用BMC虚拟光驱挂载onboard_driver_xxx.iso: 2)mount /dev/sr0 /mnt …...

【Shell】常用命令合集
常用命令: 文件和目录: cd /home 进入 ‘/home’ 目录 cd … 返回上一级目录 cd …/… 返回上两级目录 cd - 返回上次所在目录 cp file1 file2 将file1复制为file2 cp -a dir1 dir2 复制一个目录 cp -a /tmp/dir1 . 复制一个目录到当前工作目录(.代表当前目录…...

15- 答题卡识别及分数判定项目 (OpenCV系列) (项目十五)
项目要点 图片读取 : img cv2.imread(./images/test_01.png)灰度图: gray cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)高斯模糊: blurred cv2.GaussianBlur(gray, (5, 5), 0) # 去噪点边缘检测: edged cv2.Canny(blurred, 75, 200)检测轮廓: cnts cv2.findContours(e…...

LeetCode 热题 C++ 146. LRU 缓存
力扣146 请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。 实现 LRUCache 类: LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否…...

Java线程池使用与原理解析(线程池优点、使用方法、参数含义及线程池运转机制)
为什么要使用线程池? JDK1.5后JUC包添加了线程池相关接口,在Java诞生之初并没有线程池这个概念。刚开始Java程序都是自行创建线程去处理任务。随着应用使用的线程越来越多,JDK开发者们发现有必要使用一个统一的类来管理这些线程,…...

mybatis入门配置
mybatis mybatis是一款持久层框架,用于简化JDBC开发 持久层:负责将数据保存到数据库的那一层代码JavaEE的三层架构:表现层、业务层、持久层、,就相当与mvc设计模式过程中的Controller、service、dao 1.创建一个maven模块&#…...

黑客入门(超级详细版)
据我了解,“黑客”大体上应该分为“正”、“邪”两类,正派黑客依靠自己掌握的知识帮助系统管理员找出系统中的漏洞并加以完善,而邪派黑客则是通过各种黑客技能对系统进行攻击、入侵或者做其他一些有害于网络的事情,因为邪派黑客所…...

Java多线程(三)---synchronized、Lock和volatile
Java内存模型(非JVM)Java内存模型(Java Memory Model简称JMM),是一种共享内存模型,是多线程的东西,并不是JVM(Java Virtual Machine(Java虚拟机)的缩写),这是俩玩意儿!&a…...

JVM-Java内存区域
运行时数据区:1、程序计数器:当前线程所执行的字节码指令的行号指示器。在Java虚拟机的概念模型里,字节码解释器的工作就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,它是程序控制流的指示器,分支、循环…...

毕业季,毕业论文查重,paper系列五个免费查重网站推荐
推荐五个常用的免费查重网站 注意: (1)这些网站基本上都可以通过关注公众号或者转发等来获取免费查重机会,但有些也会有字数限制。每个网站的数据库可能不同,所以建议大家多换几个平台查一查,反正是免费的…...

破解票房之谜:为何高票房电影绕不过“猫眼们”?
如此火爆的春节档很多,如此毁誉参半的春节档鲜有。2023开年,集齐张艺谋、沈腾的《满江红》,以及有票房前作打底的《流浪地球2》接连两部春节档电影票房进入前十,为有些颓靡的中国电影市场注入了一针“强心剂”。与票房同样热闹起来…...

订单服务-----遇到的问题及解决方案
订单服务的问题及解决方案问题1:Feign远程调用时丢失请求头编辑出现这个Feign远程调用时丢失请求头的问题是因为Feign在远程调用的时候会创建一个新的请求,但是这个新的请求里啥都没有,没有cookie值,而这个cookie值里有成功登录后…...

项目经理如何度量项目?及项目度量指标实例【静说】
度量项目是项目经理的一个重要职责,通过度量项目,项目经理可以了解项目的进展情况,及时发现问题并采取相应的措施,以确保项目能够按时、按质、按预算完成。 分享给大家一些常见的项目度量指标: 1. 项目进度ÿ…...

我们应该如何优雅的处理 React 中受控与非受控
引言 大家好,我是19组清风。有段时间没有和大家见面了,最近因为有一些比较重要的事情(陪女朋友和换了新公司)在忙碌所以销声匿迹了一小段时间, 后续会陆陆续续补充之前构建 & 编译系列中缺失的部分,提…...

力扣热题100Day06:20. 有效的括号,21. 合并两个有序链表,22. 括号生成
20. 有效的括号 题目链接:20. 有效的括号 - 力扣(Leetcode) 思路:使用栈 (1)遇到左括号就将其对应的右括号压入到栈中 (2)如果遇到右括号 a. 如果弹出的元素与当前不等ÿ…...

【Yolov5】保姆级别源码讲解之-推理部分detect.py文件
推理部分之detect.py文件讲解1.下载Yolov5的源码2. 主函数讲解3.文件标头的注释4. main函数的5. run函数5.1 第一块参数部分5.2第二块,传入数据预处理5.3 第三块创建文件夹5.4 第四块 加载模型的权重5.5 第五块 Dataloader 加载模块5.6 第六块 推理部分 Run inferen…...