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

胸怀万里世界, 放眼无限未来。这篇文章主要讲述#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_scmd_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_MAXARGS64/* 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_MAXARGS64/* 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?? 类型的结构体。凡是带有?


【#yyds干货盘点#使用U_BOOT_CMD()自定义uboot命令】?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_commandcommon/cli_simple.c
cli_simple_parse_line分析参数
cmd_processcommon/command.c
find_cmd根据name查找命令,在section .u_boot_list_2_cmd_1和.u_boot_list_2_cmd_3

    推荐阅读