NXP i.MX8M secure boot流程
Uboot链接脚本分析述
Uboot启动分析–start.S启动分析(1)
Uboot启动分析–start.S启动分析(2)
Uboot启动分析–start.S启动分析(3)
Uboot启动分析–__main分析(1)
Uboot启动分析–__main分析(2)
Uboot启动分析–启动kernel
Uboot分析–SPL跳转过程分析
Uboot中lpddr4的初始化(i.MX8M)
使用U_BOOT_CMD()自定义uboot命令
首先引入command相关的头文件:
#include <common.h>
#include <command.h>
如果要添加自己的uboot命令必须要使用U_BOOT_CMD()这个宏。以hdmi检测功能为例:
U_BOOT_CMD(hdmidet, 1, 1, do_hdmidet,
"detect HDMI monitor",
""
);
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
段中,并且即使该变量没有在代码中显式的使用编译器也不产生警告信息。
\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 之间查找
cmd_call 执行命令