#yyds干货盘点#使用U_BOOT_CMD()自定义uboot命令

Posted MuggleZero

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了#yyds干货盘点#使用U_BOOT_CMD()自定义uboot命令相关的知识,希望对你有一定的参考价值。

首先引入command相关的头文件:

#include 
#include

如果要添加自己的uboot命令必须要使用U_BOOT_CMD()这个宏。以hdmi检测功能为例:

U_BOOT_CMD(hdmidet, 1, 1, do_hdmidet,
"detect HDMI monitor",
""
);

U_BOOT_CMD()宏定义

typedef struct cmd_tbl_s  cmd_tbl_t;


#define U_BOOT_CMD(_name, _maxargs, _rep, _cmd, _usage, _help) \\
U_BOOT_CMD_COMPLETE(_name, _maxargs, _rep, _cmd, _usage, _help, NULL) \\


#define U_BOOT_CMD_COMPLETE(_name, _maxargs, _rep, _cmd, _usage, _help, _comp) \\
ll_entry_declare(cmd_tbl_t, _name, cmd) = U_BOOT_CMD_MKENT_COMPLETE(_name, _maxargs, _rep, _cmd, _usage, _help, _comp);


#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)
}


#define ll_entry_declare(_type, _name, _list) \\
_type _u_boot_list_2_##_list##_2_##_name __aligned(4) \\
__attribute__((unused,section(".u_boot_list_2_"#_list"_2_"#_name)))

_name:uboot中命令的名字 _maxargs:最多几个args _rep:是否自动重复(按Enter键是否会重复执行) _cmd:我们自己写的函数 _usage:函数的用途说明,比如“检测hdmi功能” _help:较详细的使用说明(字符串)

/**
* ll_entry_declare() - Declare linker-generated array entry
* @_type: Data type of the entry
* @_name: Name of the entry
* @_list: name of the list. Should contain only characters allowed
* in a C variable name!
*
* This macro declares a variable that is placed into a linker-generated
* array. This is a basic building block for more advanced use of linker-
* generated arrays. The user is expected to build their own macro wrapper
* around this one.
*
* A variable declared using this macro must be compile-time initialized.
*
* Special precaution must be made when using this macro:
*
* 1) The _type must not contain the "static" keyword, otherwise the
* entry is generated and can be iterated but is listed in the map
* file and cannot be retrieved by name.
*
* 2) In case a section is declared that contains some array elements AND
* a subsection of this section is declared and contains some elements,
* it is imperative that the elements are of the same type.
*
* 3) In case an outer section is declared that contains some array elements
* AND an inner subsection of this section is declared and contains some
* elements, then when traversing the outer section, even the elements of
* the inner sections are present in the array.
*
* Example:
*
* ::
*
* ll_entry_declare(struct my_sub_cmd, my_sub_cmd, cmd_sub) = {
* .x = 3,
* .y = 4,
* };
*/
#define ll_entry_declare(_type, _name, _list) \\
_type _u_boot_list_2_##_list##_2_##_name __aligned(4) \\
__attribute__((unused)) \\
__section(".u_boot_list_2_"#_list"_2_"#_name)

以fastboot为例

U_BOOT_CMD( 
fastboot,
CONFIG_SYS_MAXARGS,
1,
do_fastboot,
"run as a fastboot usb or udp device",
fastboot_help_text
);
U_BOOT_CMD(fastboot, CONFIG_SYS_MAXARGS, 1, do_fastboot,"run as a fastboot usb or udp device", fastboot_help_text);
====展开得到====>


U_BOOT_CMD_COMPLETE(fastboot, CONFIG_SYS_MAXARGS, 1, do_fastboot,"run as a fastboot usb or udp device", fastboot_help_text, NULL)
====展开得到====>


ll_entry_declare(cmd_tbl_t, fastboot, cmd) =
{
#fastboot,
64, // #define CONFIG_SYS_MAXARGS 64 /* max command args */
cmd_always_repeatable,
do_fastboot,
"run as a fastboot usb or udp device",
fastboot_help_text,
NULL
}
====展开得到====>


_type _u_boot_list_2_cmd_2_fastboot __aligned(4) __attribute__((unused, section(".u_boot_list_2_cmd_2_fastboot")))=
{
#fastboot,
64, // #define CONFIG_SYS_MAXARGS 64 /* max command args */
cmd_always_repeatable,
do_fastboot,
"run as a fastboot usb or udp device",
fastboot_help_text,
NULL
}

可以看出,通过​​U_BOOT_CMD​​宏控就生成了一个​​_u_boot_list_2_cmd_2_fastboot​​ 类型的结构体。凡是带有​


​attribute ((unused,section (“.u_boot_list”))​​属性声明的变量都将被存放在​​.u_boot_list​​段中,并且即使该变量没有在代码中显式的使用编译器也不产生警告信息。

asm
\\arch\\arm\\cpu\\u-boot.lds
. = .;


. = ALIGN(4);
.u_boot_list : {
KEEP(*(SORT(.u_boot_list*)));
}


. = ALIGN(4)

这表明,凡是以​​u_boot_list​​开头的都会被放在 ​​.u_boot_list​​段中。至此,我们就将 fastboot 命令相关信息在编译阶段就存储在了 ​​.u_boot_list​​ 段中。在编译中, ​


​.u_boot_list​​ 字段就会和 ​​.text . data​​ 一样被打包进uboot bin中。

# limit ourselves to the sections we want in the .bin.
ifdef CONFIG_ARM64
OBJCOPYFLAGS += -j .text -j .image -j .secure_text -j .secure_data -j .rodata -j .data \\
-j .u_boot_list -j .rela.dyn -j .got -j .got.plt \\
-j .binman_sym_table -j .text_rest
else
OBJCOPYFLAGS += -j .text -j .secure_text -j .image -j .secure_data -j .rodata -j .hash \\
-j .data -j .got -j .got.plt -j .u_boot_list -j .rel.dyn \\
-j .binman_sym_table -j .text_rest
endif

命令调用过程

un_command common/cli.c
cli_simple_run_command common/cli_simple.c
cli_simple_parse_line 分析参数
cmd_process common/command.c
find_cmd 根据name查找命令,在section .u_boot_list_2_cmd_1和.u_boot_list_2_cmd_3 #yyds干货盘点#自适应布局方案

小程序自定义配置顶部栏#yyds干货盘点#

#yyds干货盘点#hyperf自定义验证与格式化输出验证信息

Flutter 专题29 图解自定义底部状态栏 ACEBottomNavigationBar #yyds干货盘点#

#yyds干货盘点# Kubernetes 如何根据需求自定义你的 API?(26)

#yyds干货盘点#如何写好Dockerfile