Trying to understand the usage of function pointer

走远了吗. 提交于 2019-12-23 04:05:40

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!