When the U-boot shell wants to find a command from the linker_list, it invokes the following function -
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);
}
To get a pointer to the struct cmd_tbl_t which holds all the specifics of this command, ll_entry_start() is invoked.
#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 gives back pointer to the start of the struct cmd_tbl_t holding the command.
We cannot predict what is the string passed to find_cmd().
The #(stringizing) operator is a pre-processor directive. It cannot generate a string from a token name in runtime. How does the compiler generate code for all the possible string values that _list can take in this?
The linker generated list for the commands is filled by specifying the commands with the U_BOOT_CMD macro. Here is an example from cmd/bootefi.c
U_BOOT_CMD(
bootefi, 3, 0, do_bootefi,
"Boots an EFI payload from memory",
bootefi_help_text
);
The linker creates a section in the u-boot binary for each command, e.g. for bootefi: .u_boot_list_2_cmd_2_bootefi
You can iterate over linker generated lists using ll_entry_start and ll_entry_next. Below is an example taken from 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" : "");
}