这是u-boot的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()
的定义在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
应该存储一个函数的地址。 但是我想知道这三个参数将会被执行什么操作。 为什么我们有这些论点?
kernel_entry
变量及其类型的声明,它是一个指向int
, int
, uint
和返回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
U-Boot在其可寻址的内存空间中具有内核映像,读取该映像中包含的地址(在images-> ep),并分支到该入口点地址。
kernel_entry()的定义实际上是在内核源代码中,arch / arm / boot / compressed / head.S上的标签“start”就是你要找的东西。
为了理解内核启动过程,IMO定义的教程是Hallinan“Embedded Linux Primer”的第5章。