SRK
SRK

Reputation: 328

How ll_entry_declare() works in U-Boot?

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?

Upvotes: 0

Views: 950

Answers (1)

Xypron
Xypron

Reputation: 2483

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" : "");
} 

Upvotes: 0

Related Questions