|
| 1 | +.. SPDX-License-Identifier: GPL-2.0 |
| 2 | +
|
| 3 | +.. _bootconfig: |
| 4 | + |
| 5 | +================== |
| 6 | +Boot Configuration |
| 7 | +================== |
| 8 | + |
| 9 | +:Author: Masami Hiramatsu < [email protected]> |
| 10 | + |
| 11 | +Overview |
| 12 | +======== |
| 13 | + |
| 14 | +The boot configuration expands the current kernel command line to support |
| 15 | +additional key-value data when booting the kernel in an efficient way. |
| 16 | +This allows administrators to pass a structured-Key config file. |
| 17 | + |
| 18 | +Config File Syntax |
| 19 | +================== |
| 20 | + |
| 21 | +The boot config syntax is a simple structured key-value. Each key consists |
| 22 | +of dot-connected-words, and key and value are connected by ``=``. The value |
| 23 | +has to be terminated by semi-colon (``;``) or newline (``\n``). |
| 24 | +For array value, array entries are separated by comma (``,``). :: |
| 25 | + |
| 26 | +KEY[.WORD[...]] = VALUE[, VALUE2[...]][;] |
| 27 | + |
| 28 | +Unlike the kernel command line syntax, spaces are OK around the comma and ``=``. |
| 29 | + |
| 30 | +Each key word must contain only alphabets, numbers, dash (``-``) or underscore |
| 31 | +(``_``). And each value only contains printable characters or spaces except |
| 32 | +for delimiters such as semi-colon (``;``), new-line (``\n``), comma (``,``), |
| 33 | +hash (``#``) and closing brace (``}``). |
| 34 | + |
| 35 | +If you want to use those delimiters in a value, you can use either double- |
| 36 | +quotes (``"VALUE"``) or single-quotes (``'VALUE'``) to quote it. Note that |
| 37 | +you can not escape these quotes. |
| 38 | + |
| 39 | +There can be a key which doesn't have value or has an empty value. Those keys |
| 40 | +are used for checking if the key exists or not (like a boolean). |
| 41 | + |
| 42 | +Key-Value Syntax |
| 43 | +---------------- |
| 44 | + |
| 45 | +The boot config file syntax allows user to merge partially same word keys |
| 46 | +by brace. For example:: |
| 47 | + |
| 48 | + foo.bar.baz = value1 |
| 49 | + foo.bar.qux.quux = value2 |
| 50 | + |
| 51 | +These can be written also in:: |
| 52 | + |
| 53 | + foo.bar { |
| 54 | + baz = value1 |
| 55 | + qux.quux = value2 |
| 56 | + } |
| 57 | + |
| 58 | +Or more shorter, written as following:: |
| 59 | + |
| 60 | + foo.bar { baz = value1; qux.quux = value2 } |
| 61 | + |
| 62 | +In both styles, same key words are automatically merged when parsing it |
| 63 | +at boot time. So you can append similar trees or key-values. |
| 64 | + |
| 65 | +Comments |
| 66 | +-------- |
| 67 | + |
| 68 | +The config syntax accepts shell-script style comments. The comments starting |
| 69 | +with hash ("#") until newline ("\n") will be ignored. |
| 70 | + |
| 71 | +:: |
| 72 | + |
| 73 | + # comment line |
| 74 | + foo = value # value is set to foo. |
| 75 | + bar = 1, # 1st element |
| 76 | + 2, # 2nd element |
| 77 | + 3 # 3rd element |
| 78 | + |
| 79 | +This is parsed as below:: |
| 80 | + |
| 81 | + foo = value |
| 82 | + bar = 1, 2, 3 |
| 83 | + |
| 84 | +Note that you can not put a comment between value and delimiter(``,`` or |
| 85 | +``;``). This means following config has a syntax error :: |
| 86 | + |
| 87 | + key = 1 # comment |
| 88 | + ,2 |
| 89 | + |
| 90 | + |
| 91 | +/proc/bootconfig |
| 92 | +================ |
| 93 | + |
| 94 | +/proc/bootconfig is a user-space interface of the boot config. |
| 95 | +Unlike /proc/cmdline, this file shows the key-value style list. |
| 96 | +Each key-value pair is shown in each line with following style:: |
| 97 | + |
| 98 | + KEY[.WORDS...] = "[VALUE]"[,"VALUE2"...] |
| 99 | + |
| 100 | + |
| 101 | +Boot Kernel With a Boot Config |
| 102 | +============================== |
| 103 | + |
| 104 | +Since the boot configuration file is loaded with initrd, it will be added |
| 105 | +to the end of the initrd (initramfs) image file. The Linux kernel decodes |
| 106 | +the last part of the initrd image in memory to get the boot configuration |
| 107 | +data. |
| 108 | +Because of this "piggyback" method, there is no need to change or |
| 109 | +update the boot loader and the kernel image itself. |
| 110 | + |
| 111 | +To do this operation, Linux kernel provides "bootconfig" command under |
| 112 | +tools/bootconfig, which allows admin to apply or delete the config file |
| 113 | +to/from initrd image. You can build it by the following command:: |
| 114 | + |
| 115 | + # make -C tools/bootconfig |
| 116 | + |
| 117 | +To add your boot config file to initrd image, run bootconfig as below |
| 118 | +(Old data is removed automatically if exists):: |
| 119 | + |
| 120 | + # tools/bootconfig/bootconfig -a your-config /boot/initrd.img-X.Y.Z |
| 121 | + |
| 122 | +To remove the config from the image, you can use -d option as below:: |
| 123 | + |
| 124 | + # tools/bootconfig/bootconfig -d /boot/initrd.img-X.Y.Z |
| 125 | + |
| 126 | +Then add "bootconfig" on the normal kernel command line to tell the |
| 127 | +kernel to look for the bootconfig at the end of the initrd file. |
| 128 | + |
| 129 | +Config File Limitation |
| 130 | +====================== |
| 131 | + |
| 132 | +Currently the maximum config size size is 32KB and the total key-words (not |
| 133 | +key-value entries) must be under 1024 nodes. |
| 134 | +Note: this is not the number of entries but nodes, an entry must consume |
| 135 | +more than 2 nodes (a key-word and a value). So theoretically, it will be |
| 136 | +up to 512 key-value pairs. If keys contains 3 words in average, it can |
| 137 | +contain 256 key-value pairs. In most cases, the number of config items |
| 138 | +will be under 100 entries and smaller than 8KB, so it would be enough. |
| 139 | +If the node number exceeds 1024, parser returns an error even if the file |
| 140 | +size is smaller than 32KB. |
| 141 | +Anyway, since bootconfig command verifies it when appending a boot config |
| 142 | +to initrd image, user can notice it before boot. |
| 143 | + |
| 144 | + |
| 145 | +Bootconfig APIs |
| 146 | +=============== |
| 147 | + |
| 148 | +User can query or loop on key-value pairs, also it is possible to find |
| 149 | +a root (prefix) key node and find key-values under that node. |
| 150 | + |
| 151 | +If you have a key string, you can query the value directly with the key |
| 152 | +using xbc_find_value(). If you want to know what keys exist in the boot |
| 153 | +config, you can use xbc_for_each_key_value() to iterate key-value pairs. |
| 154 | +Note that you need to use xbc_array_for_each_value() for accessing |
| 155 | +each array's value, e.g.:: |
| 156 | + |
| 157 | + vnode = NULL; |
| 158 | + xbc_find_value("key.word", &vnode); |
| 159 | + if (vnode && xbc_node_is_array(vnode)) |
| 160 | + xbc_array_for_each_value(vnode, value) { |
| 161 | + printk("%s ", value); |
| 162 | + } |
| 163 | + |
| 164 | +If you want to focus on keys which have a prefix string, you can use |
| 165 | +xbc_find_node() to find a node by the prefix string, and iterate |
| 166 | +keys under the prefix node with xbc_node_for_each_key_value(). |
| 167 | + |
| 168 | +But the most typical usage is to get the named value under prefix |
| 169 | +or get the named array under prefix as below:: |
| 170 | + |
| 171 | + root = xbc_find_node("key.prefix"); |
| 172 | + value = xbc_node_find_value(root, "option", &vnode); |
| 173 | + ... |
| 174 | + xbc_node_for_each_array_value(root, "array-option", value, anode) { |
| 175 | + ... |
| 176 | + } |
| 177 | + |
| 178 | +This accesses a value of "key.prefix.option" and an array of |
| 179 | +"key.prefix.array-option". |
| 180 | + |
| 181 | +Locking is not needed, since after initialization, the config becomes |
| 182 | +read-only. All data and keys must be copied if you need to modify it. |
| 183 | + |
| 184 | + |
| 185 | +Functions and structures |
| 186 | +======================== |
| 187 | + |
| 188 | +.. kernel-doc:: include/linux/bootconfig.h |
| 189 | +.. kernel-doc:: lib/bootconfig.c |
| 190 | + |
0 commit comments