Linuxの新しい起動オプション設定機能 Bootconfigの話

#カーネル起動オプション
Linuxカーネルには、起動オプション設定方法としてkernel command lineというのがあります。Grub.confなどでCMDLINE=で書き込むあれです。
カーネルをコマンドに見立ててコマンドラインオプションを渡せる機能ですが、最近この機能に加えて、もう少し読みやすく書きやすいオプション設定方法として[Extra boot configuration](https://www.kernel.org/doc/html/latest/admin-guide/bootconfig.html)通称bootconfigが追加されました。

#Extra Boot Configuration
Extra Boot Configuration（通称bootconfig）は、カーネルの起動オプションをsysctl.confに似た設定ファイルとしてカーネルに与えることが出来る機能です。

## Extra boot configurationの有効化
Extra boot configurationはLinuxカーネル v5.6以降でサポートされていますが、念の為出来るだけ新しいカーネルを使うことをお勧めします。(v5.9以降を推奨）以下のオプションを有効にしたカーネルをビルドしてインストールしておきましょう。

*CONFIG_BOOT_CONFIG=y* 

## 使い方

Kernel command line はgrub.confなどブートローダを経由して設定するか、カーネルビルドの際に指定していました。
Extra Boot Configurationは、カーネル付属のbootconfigコマンドを使い、オプションを書いたファイルをinitrd(initramfs)イメージに追記して使います。

### bootconfigコマンド
bootconfigコマンドはLinuxカーネルのtools/bootconfigにあるのでまずはビルドしましょう。

```shell
$ cd tools/bootconfig
$ make
$ ./bootconfig
Error: No initrd is specified.
Usage: bootconfig [OPTIONS] <INITRD>
Or     bootconfig <CONFIG>
 Apply, delete or show boot config to initrd.
 Options:
		-a <config>: Apply boot config to initrd
		-d : Delete boot config file from initrd
		-l : list boot config in initrd or file

 If no option is given, show the bootconfig in the given file.

```
後は-aオプションを使い、initrd(initramfs)イメージに設定ファイルを適用して、更にカーネルのブートオプションに"**bootconfig**"を指定してブートすれば適用されます。

```shell
$ echo "test.option = 1" > test.bconf
$ ./bootconfig -a test.bconf /boot/initrd-...
$ vi /etc/default/grub
....
GRUB_CMDLINE_LINUX_DEFAULT="... bootconfig"
$ sudo update-grub2
```
2回目以降は設定ファイルを更新したら、bootconfigコマンドでinitrdイメージを更新するだけでOKです。
再起動して**/proc/bootconfig**を見ると、設定した値が表示されるはずです。

```shell
$ cat /proc/bootconfig
test.option = 1
```

## Extra Boot Configurationの書き方

bootconfigではsysctl.confと同じように、

```shell
key.word.foo = value1
```

という形で与えたいオプションと値を設定します。複数の設定のキーの一部が被る場合、中括弧を使って、

```shell
key.word {
   foo = value1
   bar = value2
}
```

という風に、重複する部分を省略することが出来ます。

### キーワードに使える文字

キーワードとして使える文字はASCII文字で英数字及び"-"（マイナス）と"_"（アンダースコア）になっています。

### 値なしオプション

以下のように値を省略することで値のないオプションも表現できます。

```
key.word.non_value_param
```
### 値

オプションに設定する値は基本的に文字列として扱われます。値はダブルクオーテーションもしくはシングルクオーテーションで囲むことが出来ます。

また一つのオプションは複数の値を配列として取ることも出来ます。

```
key = "value" , 'value2'
```

値の割当は ```=```ですが、```:=```を使うと以前に定義されたオプションの値を上書きできます。また```+=```を使うと、値を配列の要素として追加することが可能です。


### コメントと改行

シェルスクリプトと同様、#から改行までの間はコメントとして扱われます。
オプションとオプションの間は改行で区切りますが、代わりにセミコロン(;)も使用できます。

```shell
key { word1; word2 = 2; word3 = foo } # shorten version
```

## 実用的な使い方

じゃあ実際の所、Extra boot configurationで何が出来るのというところですが、カーネルパラメータの記述を拡張することが出来ます。

### "kernel" オプション

bootconfigに書くキーワードで、"kernel"から始まるものは、そのままkernel command line（の先頭）に渡されます。例えば

```shell
kernel {
    console = ttyS0,9800n1
    root = /dev/sda1
    i915.modeset = 1
}
```
とか書くと、起動後はカーネルコマンドラインに以下のように反映されます。

```
$ cat /proc/cmdline
console=ttyS0,9800n1 root=/dev/sda1 i915.modeset=1 ...
```

### "init"オプション
また、systemdなど大量のオプションを/proc/cmdlineから取得するようなプログラムに対しては "user"オプションが利用できます。
bootconfigに"init"から始まるオプションを書けば、そのままkenrel command lineの末尾に``--``と共に追加されます。

```shell
init {
    quiet
    systemd {
        crash_reboot = yes
        dump_core = yes
        journald.forward_to_console = yes
    }
}
```
これは以下のようになります。

```shell
$ cat /proc/cmdline
... -- quiet systemd.crash_reboot=yes systemd.dump_core=yes systemd.journald.forward_to_console=yes
```

#まとめ

というわけで、新しくLinuxカーネルに追加された起動オプションの指定方法であるExtra Boot Configurationについてざっくりと紹介しました。
次はbootconfigのカーネルオプション以外の利用法である kernel boot time tracingについても紹介したいと思います。