initrd shenanigans
If you are using initrd or initramfs, keep in mind the following:
rdinit= is used instead of init=
if rdinit= is not given, the attempted default paths are: /sbin/init, /etc/init, /bin/init and /bin/sh but not /init
When not using initrd, /init is the first path tried, followed by the others.
v4.15 RTFS: everything is contained inside the https://github.com/torvalds/linux/blob/v4.15/init/main.c file.
First we learn that:
execute_comand is whatever is passed to: init=
ramdisk_execute_command is whatever is passed to: rdinit=
as can be seen from:
static int __init init_setup(char *str)
{
unsigned int i;
execute_command = str;
/*
* In case LILO is going to boot us with default command line,
* it prepends "auto" before the whole cmdline which makes
* the shell think it should execute a script with such name.
* So we ignore all arguments entered _before_ init=... [MJ]
*/
for (i = 1; i < MAX_INIT_ARGS; i++)
argv_init[i] = NULL;
return 1;
}
__setup("init=", init_setup);
static int __init rdinit_setup(char *str)
{
unsigned int i;
ramdisk_execute_command = str;
/* See "auto" comment in init_setup */
for (i = 1; i < MAX_INIT_ARGS; i++)
argv_init[i] = NULL;
return 1;
}
__setup("rdinit=", rdinit_setup);
where __setup is a magic way of handling up command line parameters.
start_kernel, the kernel "entry point", calls rest_init, which "calls" kernel_init on a thread:
pid = kernel_thread(kernel_init, NULL, CLONE_FS);
Then, kernel_init does:
static int __ref kernel_init(void *unused)
{
int ret;
kernel_init_freeable();
[...]
if (ramdisk_execute_command) {
ret = run_init_process(ramdisk_execute_command);
if (!ret)
return 0;
pr_err("Failed to execute %s (error %d)\n",
ramdisk_execute_command, ret);
}
[...]
if (execute_command) {
ret = run_init_process(execute_command);
if (!ret)
return 0;
panic("Requested init %s failed (error %d).",
execute_command, ret);
}
if (!try_to_run_init_process("/sbin/init") ||
!try_to_run_init_process("/etc/init") ||
!try_to_run_init_process("/bin/init") ||
!try_to_run_init_process("/bin/sh"))
return 0;
panic("No working init found. Try passing init= option to kernel. "
"See Linux Documentation/admin-guide/init.rst for guidance.");
}
and kernel_init_freeable does:
static noinline void __init kernel_init_freeable(void)
{
[...]
if (!ramdisk_execute_command)
ramdisk_execute_command = "/init";
if (sys_access((const char __user *) ramdisk_execute_command, 0) != 0) {
ramdisk_execute_command = NULL;
prepare_namespace();
}
TODO: understand sys_access.
Also note that there are further differences between ram inits and non-ram inits, e.g. console handling: Difference in execution of init with embedded vs. external initramfs?
init? They may simply be ignoring the command line... you may want to examine the initrd and see what the scripts are actually doing. – Aaron D. Marasco Jan 31 '12 at 02:17