I am trying to boot ARMv8 Linux totally manually, which means there is NO bootloader at all in hand. I can load the kernel image, initrd and fdt to memory, then 'jump' to the kernel entry point to boot it.
But I don't know how to tell the kernel where is the initrd or dtb, and what is the kernel command line.. :-(.
So the question on ARMv8 Linux is what is the way to pass info of initrd, dtb and command line to the kernel, without using bootloader ?
The uboot code of bootm for ARM is as follows (arch/arm/lib/bootm.c),
if (CONFIG_IS_ENABLED(OF_LIBFDT) && images->ft_len)
r2 = (unsigned long)images->ft_addr;
else
r2 = gd->bd->bi_boot_params;
if (!fake) {
#ifdef CONFIG_ARMV7_NONSEC
if (armv7_boot_nonsec()) {
armv7_init_nonsec();
secure_ram_addr(_do_nonsec_entry)(kernel_entry,
0, machid, r2);
} else
#endif
kernel_entry(0, machid, r2);
}
#endif
With fdt loaded into memory, the r2 is fdt memory address.
The entry point of Linux kernel (5.19.9) of ARM64 is as follows (arch/arm64/kernel/head.S),
/*
* Preserve the arguments passed by the bootloader in x0 .. x3
*/
SYM_CODE_START_LOCAL(preserve_boot_args)
mov x21, x0 // x21=FDT
adr_l x0, boot_args // record the contents of
stp x21, x1, [x0] // x0 .. x3 at kernel entry
stp x2, x3, [x0, #16]
dmb sy // needed before dc ivac with
// MMU off
add x1, x0, #0x20 // 4 x 8 bytes
b dcache_inval_poc // tail call
SYM_CODE_END(preserve_boot_args)
It seemd that kernel thinks X0 is the address of fdt (or boot args).
So what register is used to pass FDT to kernel in the bootup ?