当U-boot shell想要从linker_list中找到命令时,它会调用以下函数 -
cmd_tbl_t *find_cmd(const char *cmd)
{
cmd_tbl_t *start = ll_entry_start(cmd_tbl_t, cmd);
const int len = ll_entry_count(cmd_tbl_t, cmd);
return find_cmd_tbl(cmd, start, len);
}
要获取指向struct cmd_tbl_t的指针,该指针包含此命令的所有细节,将调用ll_entry_start()。
#define ll_entry_start(_type, _list)
({
static char start[0] __aligned(4) __attribute__((unused,
section(".u_boot_list_2_"#_list"_1")));
(_type *)&start;
})
ll_entry_start返回指向持有命令的struct cmd_tbl_t的开头的指针。
我们无法预测传递给find_cmd()的字符串是什么。
#(stringizing)运算符是一个预处理器指令。它无法在运行时从令牌名称生成字符串。编译器如何为_list可以承担的所有可能的字符串值生成代码?
答案 0 :(得分:0)
通过使用U_BOOT_CMD宏指定命令来填充命令的链接器生成列表。这是cmd / bootefi.c的一个例子。
U_BOOT_CMD(
bootefi, 3, 0, do_bootefi,
"Boots an EFI payload from memory",
bootefi_help_text
);
链接器为每个命令在u-boot二进制文件中创建一个部分,例如:对于bootefi:.u_boot_list_2_cmd_2_bootefi
您可以使用ll_entry_start和ll_entry_next迭代链接器生成的列表。以下是从lib / efi_selftest / efi_selftest.c获取的示例:
for (test = ll_entry_start(struct efi_unit_test, efi_unit_test);
test < ll_entry_end(struct efi_unit_test, efi_unit_test); ++test) {
efi_st_printf("'%s'%s\n", test->name,
test->on_request ? " - on request" : "");
}