问题
This is the function in u-boot's bootm.c from where the kernel is launched:
/* Subcommand: GO */
static void boot_jump_linux(bootm_headers_t *images, int flag)
{
#ifdef CONFIG_ARM64
void (*kernel_entry)(void *fdt_addr);
int fake = (flag & BOOTM_STATE_OS_FAKE_GO);
kernel_entry = (void (*)(void *fdt_addr))images->ep;
debug("## Transferring control to Linux (at address %lx)...\n",
(ulong) kernel_entry);
bootstage_mark(BOOTSTAGE_ID_RUN_OS);
announce_and_cleanup(fake);
if (!fake)
kernel_entry(images->ft_addr);
#else
unsigned long machid = gd->bd->bi_arch_number;
char *s;
void (*kernel_entry)(int zero, int arch, uint params);
unsigned long r2;
int fake = (flag & BOOTM_STATE_OS_FAKE_GO);
kernel_entry = (void (*)(int, int, uint))images->ep;
s = getenv("machid");
if (s) {
strict_strtoul(s, 16, &machid);
printf("Using machid 0x%lx from environment\n", machid);
}
debug("## Transferring control to Linux (at address %08lx)" \
"...\n", (ulong) kernel_entry);
bootstage_mark(BOOTSTAGE_ID_RUN_OS);
announce_and_cleanup(fake);
if (IMAGE_ENABLE_OF_LIBFDT && images->ft_len)
r2 = (unsigned long)images->ft_addr;
else
r2 = gd->bd->bi_boot_params;
if (!fake)
kernel_entry(0, machid, r2);
#endif
}
I am facing difficulty in understanding how kernel_entry
is working here. Especially in the second-last line it is being used as:
kernel_entry(0, machid, r2);
So where is the definition of kernel_entry()
? I failed to find in entire u-boot and kernel source code.
Update
I am rephrasing my question here:
Suppose kernel_entry
is a pointer to a function and is being defined as:
bootm_headers_t *images
kernel_entry = (void (*)(int, int, uint))images->ep;
Then somewhere in the program it is being called as:
kernel_entry(0, machid, r2);
I understand being a pointer, kernel_entry
should store an address of a function. But I want to understand what operations will be performed on the three arguments. Why do we have those arguments?
回答1:
The declaration of kernel_entry
variable and its type, which is a pointer to a function taking int
, int
, uint
and returning void
(probably the most confusing part), is here:
void (*kernel_entry)(int zero, int arch, uint params);
Assignment, images->ep
is cast into desired signature function pointer and put into the variable:
kernel_entry = (void (*)(int, int, uint))images->ep;
Finally, the function is called:
kernel_entry(0, machid, r2);
Please note that if CONFIG_ARM64 is defined, then the function kernel_entry
points to has different signature:
void (*kernel_entry)(void *fdt_addr); //takes one void* param and returns void
回答2:
U-Boot has the kernel image in its addressable memory space, reads an address contained in that image (at images->ep), and branches to that entry point address.
The "definition of kernel_entry()" is actually in kernel source code, the label "start" at arch/arm/boot/compressed/head.S is what you are looking for.
To understand the kernel boot process, IMO the definitive tutorial is chapter 5 of Hallinan "Embedded Linux Primer".
来源:https://stackoverflow.com/questions/24409821/trying-to-understand-the-usage-of-function-pointer