Skip to content

Commit 99c0c25

Browse files
committed
Fix incorrect assumption that -- is needed in kernel CLI
1 parent ddeb36d commit 99c0c25

File tree

2 files changed

+59
-30
lines changed

2 files changed

+59
-30
lines changed

README.adoc

Lines changed: 56 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3256,6 +3256,12 @@ The most direct way to replace `init` with our own is to just use the `init=` <<
32563256

32573257
This just counts every second forever and does not give you a shell.
32583258

3259+
And to pass command line arguments to the program, you can use `--kernel-cli-after-dash`:
3260+
3261+
....
3262+
./run --kernel-cli 'init=/bin/sh' --kernel-cli-after-dash '-c "echo asdf; pwd; ls"'
3263+
....
3264+
32593265
This method is not very flexible however, as it is hard to reliably pass multiple commands and command line arguments to the init with it, as explained at: xref:init-environment[xrefstyle=full].
32603266

32613267
For this reason, we have created a more robust helper method with the `--eval` option:
@@ -3435,55 +3441,66 @@ at the very end of the boot logs.
34353441

34363442
=== Init environment
34373443

3438-
Documented at https://www.kernel.org/doc/html/latest/admin-guide/kernel-parameters.html[]:
3444+
Documented at https://www.kernel.org/doc/html/v5.9/admin-guide/kernel-parameters.html[]:
34393445

34403446
____
34413447
The kernel parses parameters from the kernel command line up to "--"; if it doesn't recognize a parameter and it doesn't contain a '.', the parameter gets passed to init: parameters with '=' go into init's environment, others are passed as command line arguments to init. Everything after "--" is passed as an argument to init.
34423448
____
34433449

3444-
And you can try it out with:
3450+
And you can try it out with our link:userland/linux/init_env_poweroff.c[] program:
34453451

34463452
....
3447-
./run --kernel-cli 'init=/lkmc/linux/init_env_poweroff.out' --kernel-cli-after-dash 'asdf=qwer zxcv'
3453+
./run --kernel-cli 'init=/lkmc/linux/init_env_poweroff.out loglevel=8 go_in_env=val1 with_dot.before=val2' \
3454+
--kernel-cli-after-dash 'go_in_arg=val3 with_dot.after=val4 zxcv'
34483455
....
34493456

3450-
From the <<dry-run,generated QEMU command>>, we see that the kernel CLI at LKMC 69f5745d3df11d5c741551009df86ea6c61a09cf now contains:
3457+
From the <<dry-run,generated QEMU command>>, we see that the kernel CLI at LKMC 69f5745d3df11d5c741551009df86ea6c61a09cf now contains (or at least would if it weren't for https://github.com/cirosantilli/linux-kernel-module-cheat/issues/110 oh God), manually indented for readability:
34513458

34523459
....
3453-
init=/lkmc/linux/init_env_poweroff.out console=ttyS0 -- lkmc_home=/lkmc asdf=qwer zxcv
3460+
<6>[ 0.000000] Command line: root=/dev/vda nopat console_msg_format=syslog nokaslr norandmaps panic=-1 printk.devkmsg=on printk.time=y rw
3461+
init=/lkmc/linux/init_env_poweroff.out loglevel=8 go_in_env=val1 with_dot.before=val2 -- go_in_arg=val3 with_dot.after=val4 zxcv
34543462
....
34553463

34563464
and the init program outputs:
34573465

34583466
....
3459-
args:
3460-
/lkmc/linux/init_env_poweroff.out
3461-
lkmc_home=/lkmc
3462-
asdf=qwer
3463-
zxcv
3464-
3465-
env:
3466-
HOME=/
3467-
TERM=linux
3467+
<6>[ 2.728992] Run /lkmc/linux/init_env_poweroff.out as init process
3468+
<7>[ 2.729587] with arguments:
3469+
<7>[ 2.729820] /lkmc/linux/init_env_poweroff.out
3470+
<7>[ 2.730085] lkmc_home=/lkmc
3471+
<7>[ 2.730259] go_in_arg=val3
3472+
<7>[ 2.730432] with_dot.after=val4
3473+
<7>[ 2.730623] zxcv
3474+
<7>[ 2.730767] with environment:
3475+
<7>[ 2.730960] HOME=/
3476+
<7>[ 2.731115] TERM=linux
3477+
<7>[ 2.731267] go_in_env=val
34683478
....
34693479

3470-
Source: link:userland/linux/init_env_poweroff.c[].
3471-
3472-
As of the Linux kernel v5.7 (possibly earlier, I've skipped a few releases), boot also shows the init arguments and environment very clearly, which is a great addition:
3480+
Tested as of the Linux kernel v5.7 and possibly earlier, boot also shows the init arguments and environment very clearly when using <<printk>> at `loglevel=8`, which is a great addition:
34733481

34743482
....
3475-
<6>[ 0.309984] Run /sbin/init as init process
3476-
<7>[ 0.309991] with arguments:
3477-
<7>[ 0.309997] /sbin/init
3478-
<7>[ 0.310004] nokaslr
3479-
<7>[ 0.310010] -
3480-
<7>[ 0.310016] with environment:
3481-
<7>[ 0.310022] HOME=/
3482-
<7>[ 0.310028] TERM=linux
3483-
<7>[ 0.310035] earlyprintk=pl011,0x1c090000
3484-
<7>[ 0.310041] lkmc_home=/lkmc
3483+
<6>[ 2.777265] Run /lkmc/linux/init_env_poweroff.out as init process
3484+
<7>[ 2.777729] with arguments:
3485+
<7>[ 2.777953] /lkmc/linux/init_env_poweroff.out
3486+
<7>[ 2.778212] lkmc_home=/lkmc
3487+
<7>[ 2.778391] go_in_arg=val2
3488+
<7>[ 2.778554] zxcv
3489+
<7>[ 2.778705] with environment:
3490+
<7>[ 2.778901] HOME=/
3491+
<7>[ 2.779065] TERM=linux
3492+
<7>[ 2.779223] go_in_env=val1
34853493
....
34863494

3495+
As we can see, the passing of environment variables to init is a bit wonky:
3496+
3497+
* `init` and `loglevel` didn't go because they were recognized
3498+
* `go_in_env` went because it wasn't
3499+
3500+
so things can always break in future kernel releases... The only way to guard from this a bit is to use some unique prefix and hope the kernel never decides to use it. We of course use `lkmc_*` for our variables.
3501+
3502+
And it is also impossible to pass environment variables that contain dots in them: our `with_dot.before` is simply gone. Not a common use case, but still, quite insane.
3503+
34873504
==== init arguments
34883505

34893506
The annoying dash `-` gets passed as a parameter to `init`, which makes it impossible to use this method for most non custom executables.
@@ -6088,7 +6105,7 @@ See also:
60886105
* https://unix.stackexchange.com/questions/48601/how-to-display-the-linux-kernel-command-line-parameters-given-for-the-current-bo
60896106
* https://askubuntu.com/questions/32654/how-do-i-find-the-boot-parameters-used-by-the-running-kernel
60906107

6091-
The arguments are documented in the kernel documentation: https://www.kernel.org/doc/html/latest/admin-guide/kernel-parameters.html
6108+
The arguments are documented in the kernel documentation: https://www.kernel.org/doc/html/v5.9/admin-guide/kernel-parameters.html
60926109

60936110
When dealing with real boards, extra command line options are provided on some magic bootloader configuration file, e.g.:
60946111

@@ -7667,6 +7684,17 @@ No, there no official documentation: https://stackoverflow.com/questions/1521393
76677684
[[seq-file]]
76687685
==== seq_file
76697686

7687+
TODO these examples broke in kernel 5.0 and we didn't notice because they just added a flimsy warning and nothing else:
7688+
7689+
* https://stackoverflow.com/questions/25399112/how-to-use-a-seq-file-in-linux-kernel-modules/45100058
7690+
* https://stackoverflow.com/questions/60570242/seq-file-not-working-properly-after-next-returns-null
7691+
7692+
Fix with ifdef for kernel 4/5. The error message is:
7693+
7694+
....
7695+
seq_file: buggy .next function next [module-name] did not update position index
7696+
....
7697+
76707698
Writing trivial read <<file-operations>> is repetitive and error prone. The `seq_file` API makes the process much easier for those trivial cases:
76717699

76727700
....

rootfs_overlay/lkmc/gem5_exit.sh

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#!/bin/sh
2-
# To be able to do init=/gem5_exit.sh, since kernel CLI argument passing is too messy:
3-
# https://cirosantilli.com/linux-kernel-module-cheat#init-arguments
2+
# This should not be needed anymore after we learned that it should be -- instead of -.
3+
# You should be instead able to just use something init=/bin/sh -- -c 'm5 exit'
4+
# https://github.com/cirosantilli/linux-kernel-module-cheat/pull/226
45
m5 exit

0 commit comments

Comments
 (0)