Reputation: 143
I am reading over the code from the kernel that loads the boot config. In main.c the following code is executed.
err = parse_args("bootconfig", tmp_cmdline, NULL, 0, 0, 0, NULL,
bootconfig_params);
on line 428. I open up parse_args, which, intern calls parse_one (both in kernel/params.c) and it looks like since const struct kernel_param *params
is NULL it will never iterate over any parameters in parse_one
.
I know there must be something I am missing here. The rest of the function past lines 431 and 432 in static void __init setup_boot_config(void)
are never executed as far as I can see. The boot config must be parsed.
In init/main.c
https://elixir.bootlin.com/linux/v6.13.1/source/init/main.c
static void __init setup_boot_config(void)
In kernel/params.c
https://elixir.bootlin.com/linux/v6.13.1/source/kernel/params.c
parse_one(..)
parse_args(..)
setup_boot_config(void) >> parse_args(..) >> parse_one(..)
returns ENOENT
setup_boot_config(void)
checks
if (IS_ERR(err) || !(bootconfig_found || IS_ENABLED(CONFIG_BOOT_CONFIG_FORCE)))
and returns. The xbc_init(..)
is never called. There is something missing here.
Upvotes: 2
Views: 6
Reputation: 274
At the entry to parse_args()
, the function parameters are:
doing = "bootconfig"
args = tmp_cmdline
params = NULL
num_params = 0
min_level = 0
max_level = 0
arg = NULL
unknown = &(bootconfig_params)()
Then, at the entry to parse_one()
:
param
= param
from parse_args()
val
= val
from parse_args()
doing = "bootconfig"
params = NULL
num_params = 0
min_level = 0
max_level = 0
arg = NULL
handle_unknown
= unknown
from parse_args()
= &(bootconfig_params()
Because num_params
is 0, the first for
loop in parse_one()
is skipped, and we reach this part:
if (handle_unknown) {
pr_debug("doing %s: %s='%s'\n", doing, param, val);
return handle_unknown(param, val, doing, arg);
}
And here is what you missed:
handle_unknown
is a valid function pointer to bootconfig_params()
, so it is not NULL. And so, the content of the if(handle_unknown)
will be executed, and because it contains an unconditional return
, it will dictate the result of parse_one()
.
So after resolving the function pointer, the return from parse_one()
will be whatever bootconfig_params(param, val, doing, arg)
will return.
And that is simply:
static int __init bootconfig_params(char *param, char *val,
const char *unused, void *arg)
{
if (strcmp(param, "bootconfig") == 0) {
bootconfig_found = true;
}
return 0;
}
So if param
is the exact string "bootconfig"
, then bootconfig_found
gets set to true
. But this function always returns 0... which means parse_one()
will also return 0... which sets ret
in parse_args()
to 0 instead of ENOENT
, so the switch(ret)
will go to continue
.
And so, the main while (*args) ...
loop in parse_args()
gets to iterate to the next parameter of tmp_cmdline
.
Upvotes: 2