find_cmd函数分析
一、概述
1、函数位置
common/command.c
2、函数功能分析
解析命令的关键环节是如何根据输入命令查找对应命令的信息,从而跳转到对应命令的函数处执行程序。这必然涉及到如何存放命令的详细信息这个问题。因为一种存法,对应一种查法,进而取法。也就是说,实际上是两个问题:
(1)命令的详细信息是如何存放的
(2)如何在命令存储区查找是否有与输入命令匹配的命令
就这两个问题,我们来分别分析uboot的设计方法。
二、".u_boot_cmd"环境变量存储区
1、命令详细信息存储结构体
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_LONGHELPchar *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 };typedef struct cmd_tbl_s cmd_tbl_t;
2、把命令的详细信息安排在".u_boot_cmd"存储区
(1)相关声明
#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}
## 代表字符串连接符
# 代表转换为字符串
(2)实例说明
int do_hello (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) {}U_BOOT_CMD( md, 3, 1, do_hello, "md - memory display\n", "[.b, .w, .l] address [# of objects]\n - memory display\n" );
U_BOOT_CMD( hello, 3, 1, do_hello, "md - memory display\n", "[.b, .w, .l] address [# of objects]\n - memory display\n" );展开后为:
cmd_tbl_t __u_boot_cmd_hello __attribute__ ((unused,section (".u_boot_cmd"))) ={"hello", 3, 1, do_hello,"md - memory display\n","[.b, .w, .l] address [# of objects]\n - memory display\n" };
可见,实际上就是定义了一个cmd_tbl_t类型的变量"__u_boot_cmd_hello",并且强制性的将其存储在".u_boot_cmd"段,等号后边的就是该变量的初始值。
三、具体分析find_cmd函数
函数功能:查找命令是否存在,如果存在就将命令结构体地址返回
/***************************************************************************
* find command table entry for a command
*/
cmd_tbl_t *find_cmd (const char *cmd)
{
cmd_tbl_t *cmdtp;
cmd_tbl_t *cmdtp_temp = &__u_boot_cmd_start; /*Init value */
const char *p;
int len;
int n_found = 0;
/*
* Some commands allow length modifiers (like "cp.b");
* compare command name only until first dot.
*/
len = ((p = strchr(cmd, '.')) == NULL) ? strlen (cmd) : (p - cmd);
//获取命令的长度,因为uboot支持命令的简写,但是以'.'为分隔符
//下边的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++;
}
}
if (n_found == 1) { /* exactly one match */ //如果简写命令只有一个匹配,那么说明就是要找的命令
//但是,倘若超过一个就不知道所谓的简写是哪一个命令了
return cmdtp_temp;
}
return NULL; /* not found or ambiguous command */
}
参考资料:U-Boot启动第二阶段代码分析
find_cmd函数分析相关推荐
- linux C函数之strdup函数分析【转】
本文转载自:http://blog.csdn.net/tigerjibo/article/details/12784823 linux C函数之strdup函数分析 一.函数分析 1.函数原型: [c ...
- 【Android 逆向】Dalvik 函数抽取加壳 ( 类加载流程分析 | Class.cpp#findClassNoInit 函数 | DexFile.cpp#dexFindClass 函数分析 )
文章目录 前言 一.Class.cpp#dvmDefineClass 函数分析 二.Class.cpp#findClassNoInit 函数分析 三.DexFile.cpp#dexFindClass ...
- 【Android 逆向】Dalvik 函数抽取加壳 ( 类加载流程分析 | DexPathList#findClass 函数分析 | DexFile#loadClassBinaryName 函数 )
文章目录 前言 一.DexPathList.java#findClass 类加载函数源码分析 二.DexFile.java#loadClassBinaryName 函数源码分析 前言 上一篇博客 [A ...
- 【Android 逆向】整体加固脱壳 ( DexClassLoader 加载 dex 流程分析 | DexPathList 构造函数分析 | makeDexElements 函数分析 )
文章目录 前言 一.DexPathList 构造函数分析 二.DexPathList.makeDexElements 函数分析 三.Element 类分析 前言 上一篇博客 [Android 逆向]整 ...
- 【Android 逆向】Android 逆向通用工具开发 ( adb forward 网络端口重定向命令 | PC 端逆向程序主函数分析 )
文章目录 前言 一.adb forward 网络端口重定向命令 二.PC 端逆向程序主函数分析 前言 本篇博客重点分析 PC 端 hacktool 模块 ; 一.adb forward 网络端口重定向 ...
- 【Android 逆向】Android 进程注入工具开发 ( 注入代码分析 | 注入工具的 main 函数分析 )
文章目录 一.注入流程 二.注入工具的 main 函数分析 一.注入流程 开始分析 [Android 逆向]Android 进程注入工具开发 ( 编译注入工具 | 编译结果文件说明 | 注入过程说明 ...
- 继承关系中的拷贝构造函数和赋值操作重载函数分析
文章目录 1 继承关系中的拷贝构造函数和赋值操作重载函数分析 1 继承关系中的拷贝构造函数和赋值操作重载函数分析 在继承关系中,如果子类未实现拷贝构造函数,那么在子类进行拷贝构造操作时,会直接调用父类 ...
- Windows事件等待学习笔记(三)—— WaitForSingleObject函数分析
Windows事件等待学习笔记(三)-- WaitForSingleObject函数分析 要点回顾 WaitForSingleObject NtWaitForSingleObject KeWaitFo ...
- fprintf/fscanf函数分析
fprintf/fscanf函数分析 宗旨:技术的学习是有限的,分享的精神是无限的. fprintf/fscanf函数与printf/scanf区别:printf/scanf专门针对标准输入输出流,f ...
最新文章
- tensorflow2.0中valid_data的作用是在训练的过程对对比训练数据与测试数据的准确率 损失率,便于判断模型的训练效果:是过拟合还是欠拟合(过拟合)
- [译] NSCollectionView 入门教程
- jzoj3059-雕塑【容斥,数论】
- java报错找不到对象,使用Spring源码报错java:找不到类 InstrumentationSavingAgent的问题...
- 远程计算机用户端口,电脑怎么开远程端口
- Java学习之——泛型
- 11.GitLab webhooks
- python实现游戏同步翻译字幕
- c lua语言教程,Lua教程(十九):C调用Lua
- Android版添加phonegap--融云即时通讯插件教程
- vue + iview + less 定制主题色
- 从冯诺伊曼结构看AI
- 多股票投资组合+马科维茨计算组合
- UG/NX二次开发 单位化向量 UF_VEC3_unitize
- h5页面分享朋友,朋友圈设置缩略图,自定义标题,描述!
- 解码方法( dfs | dp )
- Python入门学习笔记1-Python基础
- 北京大学计算机研究生怎么样,北京大学计算机专业在职研究生怎么样?
- win10 路由表配置
- oracle 把结果加上百分号_用一条sql语句显示数据百分比并加百分号
热门文章
- BestCoder Round #67 (div.2) 1001——N bulbs
- 557. 反转字符串中的单词 III golang 数组和字符串反转
- 28. 实现 strStr() golang
- PyCharm怎么关闭端口,解决端口占用问题
- Effective C++学习第二天
- c语言深入浅出(一)strcpy和memcpy的区别
- Micrium/UCOS官网账号密码重新改问题
- IA-32 Architecture: the function of segment regitster(CS DS SS ES)
- C/C++中NULL指针
- Redis灵魂14问?真香