试图了解函数指针的用法

时间:2014-06-25 13:17:46

标签: c linux u-boot

这是启动内核的u-boot's bootm.c中的函数:

/* 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
}

我很难理解kernel_entry如何在这里工作。特别是在倒数第二行,它被用作:

   kernel_entry(0, machid, r2);

那么kernel_entry()的定义在哪里?我没能找到整个u-boot和内核源代码。

更新

我在这里重新提出我的问题:

假设kernel_entry是指向函数的指针,并被定义为:

bootm_headers_t *images
kernel_entry = (void (*)(int, int, uint))images->ep;

然后程序中的某个地方被称为:

 kernel_entry(0, machid, r2);

我理解作为指针,kernel_entry应该存储函数的地址。但我想了解将对这三个参数执行哪些操作。为什么我们有这些论点?

2 个答案:

答案 0 :(得分:2)

kernel_entry变量及其类型的声明,它是指向intintuint和返回void的函数的指针(可能最令人困惑的部分),在这里:

void (*kernel_entry)(int zero, int arch, uint params);

赋值,images->ep被转换为所需的签名函数指针并放入变量:

kernel_entry = (void (*)(int, int, uint))images->ep;

最后,该函数被调用:

kernel_entry(0, machid, r2);

请注意,如果定义了CONFIG_ARM64,则函数kernel_entry指向具有不同的签名:

void (*kernel_entry)(void *fdt_addr); //takes one void* param and returns void

答案 1 :(得分:1)

U-Boot在其可寻址存储空间中具有内核映像,读取该映像中包含的地址(在images-> ep),并分支到该入口点地址。

kernel_entry()""定义实际上是在内核源代码中,标签" start"在arch / arm / boot / compressed / head.S是您正在寻找的。

要了解内核启动过程,IMO的权威教程是Hallinan" Embedded Linux Primer"的第5章。