在bios_qemu_tz_arm/bios/entry.s文件中,当执行完OP-TEE OS的启动之后,会调用main_init_ns函数来完成linux kernel的启动,该函数的主要内容和相关注释如下:
void main_init_ns(void)
{
call_kernel(kernel_entry, dtb_addr, rootfs_start, rootfs_end);
}
该函数将直接调用call_kernel函数来启动Linux kernel,调用时传入的参数解释如下:
kernel_entry:linux kernel在RAM中的entry地址,该值在main_init_sec函数中通过调用copy_ns_images函数来进行赋值
dtb_addr:device tree存放的位置,该值在main_init_sec函数中通过调用copy_ns_images函数来进行赋值
rootfs_start: 拷贝到RAM中的rootfs的其实地址,该值在main_init_sec函数中被赋值
rootfs_end: 拷贝到RAM中的rootfs的末端地址,该值在main_init_sec函数中被赋值
而call_kernel函数同样定义在bios_qemu_tz_arm/bios/main.c文件中,该函数的主要内容和相关注释如下:
typedef void (*kernel_ep_func)(uint32_t a0, uint32_t a1, uint32_t a2);
static void call_kernel(uint32_t entry, uint32_t dtb,
uint32_t initrd, uint32_t initrd_end)
{
/* 定义指向linux kernel入口地址的函数指针,并将函数指针的地址指向带入的参数entry的位置 */
kernel_ep_func ep = (kernel_ep_func)entry;
void *fdt = (void *)dtb; //定义device tree的地址,并赋值
const char cmdline[] = COMMAND_LINE; //定义存放commond line的变量,并进行赋值
int r;
const uint32_t a0 = 0;
/*MACH_VEXPRESS see linux/arch/arm/tools/mach-types*/
const uint32_t a1 = 2272;
/* 获取device tree的信息 */
r = fdt_open_into(fdt, fdt, DTB_MAX_SIZE);
CHECK(r < 0);
/* 设置device tree中的相关节点的中,initrd的起始地址,initrd的末端地址,bootargs */
setprop_cell(fdt, "/chosen", "linux,initrd-start", initrd);
setprop_cell(fdt, "/chosen", "linux,initrd-end", initrd_end);
setprop_string(fdt, "/chosen", "bootargs", cmdline);
r = fdt_pack(fdt);
CHECK(r < 0);
/* 打印相关信息 */
msg("kernel command line: \"%s\"\n", cmdline);
msg("Entering kernel at 0x%x with r0=0x%x r1=0x%x r2=0x%x\n",
(uintptr_t)ep, a0, a1, dtb);
/* 带入device tree信息和其他相关参数,调用linux kernel的入口函数,进而执行linux kernel的启动 */
ep(a0, a1, dtb);
}
函数最后会调用ep(a0, a1,dtb)进入linux kernel的启动。启动linux kernel的log和界面如下: