Masami Hiramatsu | 7b9b816 | 2020-01-11 01:05:06 +0900 | [diff] [blame] | 1 | .. SPDX-License-Identifier: GPL-2.0 |
| 2 | |
Masami Hiramatsu | 4778194 | 2020-01-11 01:07:40 +0900 | [diff] [blame] | 3 | .. _bootconfig: |
| 4 | |
Masami Hiramatsu | 7b9b816 | 2020-01-11 01:05:06 +0900 | [diff] [blame] | 5 | ================== |
| 6 | Boot Configuration |
| 7 | ================== |
| 8 | |
| 9 | :Author: Masami Hiramatsu <mhiramat@kernel.org> |
| 10 | |
| 11 | Overview |
| 12 | ======== |
| 13 | |
Masami Hiramatsu | a4798eb | 2020-01-20 12:23:12 +0900 | [diff] [blame] | 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. |
Masami Hiramatsu | 7b9b816 | 2020-01-11 01:05:06 +0900 | [diff] [blame] | 17 | |
| 18 | Config File Syntax |
| 19 | ================== |
| 20 | |
| 21 | The boot config syntax is a simple structured key-value. Each key consists |
Masami Hiramatsu | a4798eb | 2020-01-20 12:23:12 +0900 | [diff] [blame] | 22 | of dot-connected-words, and key and value are connected by ``=``. The value |
Masami Hiramatsu | 7b9b816 | 2020-01-11 01:05:06 +0900 | [diff] [blame] | 23 | has to be terminated by semi-colon (``;``) or newline (``\n``). |
| 24 | For array value, array entries are separated by comma (``,``). :: |
| 25 | |
Randy Dunlap | 2e5b188 | 2020-02-09 19:53:17 -0800 | [diff] [blame] | 26 | KEY[.WORD[...]] = VALUE[, VALUE2[...]][;] |
Masami Hiramatsu | 7b9b816 | 2020-01-11 01:05:06 +0900 | [diff] [blame] | 27 | |
Masami Hiramatsu | a4798eb | 2020-01-20 12:23:12 +0900 | [diff] [blame] | 28 | Unlike the kernel command line syntax, spaces are OK around the comma and ``=``. |
| 29 | |
Masami Hiramatsu | 7b9b816 | 2020-01-11 01:05:06 +0900 | [diff] [blame] | 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 |
Masami Hiramatsu | a4798eb | 2020-01-20 12:23:12 +0900 | [diff] [blame] | 40 | are used for checking if the key exists or not (like a boolean). |
Masami Hiramatsu | 7b9b816 | 2020-01-11 01:05:06 +0900 | [diff] [blame] | 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 | |
Masami Hiramatsu | 4e4694d | 2020-02-21 17:13:42 +0900 | [diff] [blame] | 65 | Same-key Values |
| 66 | --------------- |
| 67 | |
| 68 | It is prohibited that two or more values or arrays share a same-key. |
| 69 | For example,:: |
| 70 | |
| 71 | foo = bar, baz |
| 72 | foo = qux # !ERROR! we can not re-define same key |
| 73 | |
Masami Hiramatsu | c58b46c | 2020-07-16 01:00:47 +0900 | [diff] [blame] | 74 | If you want to update the value, you must use the override operator |
| 75 | ``:=`` explicitly. For example:: |
| 76 | |
| 77 | foo = bar, baz |
| 78 | foo := qux |
| 79 | |
| 80 | then, the ``qux`` is assigned to ``foo`` key. This is useful for |
| 81 | overriding the default value by adding (partial) custom bootconfigs |
| 82 | without parsing the default bootconfig. |
| 83 | |
Masami Hiramatsu | 5f811c5 | 2020-02-21 17:13:52 +0900 | [diff] [blame] | 84 | If you want to append the value to existing key as an array member, |
| 85 | you can use ``+=`` operator. For example:: |
| 86 | |
| 87 | foo = bar, baz |
| 88 | foo += qux |
| 89 | |
| 90 | In this case, the key ``foo`` has ``bar``, ``baz`` and ``qux``. |
| 91 | |
Masami Hiramatsu | 0ff2bb7 | 2021-06-02 17:19:25 +0900 | [diff] [blame] | 92 | Moreover, sub-keys and a value can coexist under a parent key. |
| 93 | For example, following config is allowed.:: |
Masami Hiramatsu | a24d286 | 2020-02-20 21:19:12 +0900 | [diff] [blame] | 94 | |
| 95 | foo = value1 |
Masami Hiramatsu | 0ff2bb7 | 2021-06-02 17:19:25 +0900 | [diff] [blame] | 96 | foo.bar = value2 |
| 97 | foo := value3 # This will update foo's value. |
Masami Hiramatsu | a24d286 | 2020-02-20 21:19:12 +0900 | [diff] [blame] | 98 | |
Masami Hiramatsu | 0ff2bb7 | 2021-06-02 17:19:25 +0900 | [diff] [blame] | 99 | Note, since there is no syntax to put a raw value directly under a |
| 100 | structured key, you have to define it outside of the brace. For example:: |
| 101 | |
| 102 | foo { |
| 103 | bar = value1 |
| 104 | bar { |
| 105 | baz = value2 |
| 106 | qux = value3 |
| 107 | } |
| 108 | } |
| 109 | |
| 110 | Also, the order of the value node under a key is fixed. If there |
| 111 | are a value and subkeys, the value is always the first child node |
| 112 | of the key. Thus if user specifies subkeys first, e.g.:: |
| 113 | |
| 114 | foo.bar = value1 |
| 115 | foo = value2 |
| 116 | |
| 117 | In the program (and /proc/bootconfig), it will be shown as below:: |
| 118 | |
| 119 | foo = value2 |
| 120 | foo.bar = value1 |
Masami Hiramatsu | a24d286 | 2020-02-20 21:19:12 +0900 | [diff] [blame] | 121 | |
Masami Hiramatsu | 7b9b816 | 2020-01-11 01:05:06 +0900 | [diff] [blame] | 122 | Comments |
| 123 | -------- |
| 124 | |
Masami Hiramatsu | a4798eb | 2020-01-20 12:23:12 +0900 | [diff] [blame] | 125 | The config syntax accepts shell-script style comments. The comments starting |
Masami Hiramatsu | 7b9b816 | 2020-01-11 01:05:06 +0900 | [diff] [blame] | 126 | with hash ("#") until newline ("\n") will be ignored. |
| 127 | |
| 128 | :: |
| 129 | |
| 130 | # comment line |
| 131 | foo = value # value is set to foo. |
| 132 | bar = 1, # 1st element |
| 133 | 2, # 2nd element |
| 134 | 3 # 3rd element |
| 135 | |
| 136 | This is parsed as below:: |
| 137 | |
| 138 | foo = value |
| 139 | bar = 1, 2, 3 |
| 140 | |
| 141 | Note that you can not put a comment between value and delimiter(``,`` or |
| 142 | ``;``). This means following config has a syntax error :: |
| 143 | |
| 144 | key = 1 # comment |
| 145 | ,2 |
| 146 | |
| 147 | |
| 148 | /proc/bootconfig |
| 149 | ================ |
| 150 | |
| 151 | /proc/bootconfig is a user-space interface of the boot config. |
| 152 | Unlike /proc/cmdline, this file shows the key-value style list. |
| 153 | Each key-value pair is shown in each line with following style:: |
| 154 | |
| 155 | KEY[.WORDS...] = "[VALUE]"[,"VALUE2"...] |
| 156 | |
| 157 | |
| 158 | Boot Kernel With a Boot Config |
| 159 | ============================== |
| 160 | |
| 161 | Since the boot configuration file is loaded with initrd, it will be added |
Masami Hiramatsu | fbc6e1c | 2020-11-19 14:53:49 +0900 | [diff] [blame] | 162 | to the end of the initrd (initramfs) image file with padding, size, |
| 163 | checksum and 12-byte magic word as below. |
Masami Hiramatsu | 85c46b7 | 2020-02-20 21:18:42 +0900 | [diff] [blame] | 164 | |
Masami Hiramatsu | 0522749 | 2020-11-20 11:29:22 +0900 | [diff] [blame] | 165 | [initrd][bootconfig][padding][size(le32)][checksum(le32)][#BOOTCONFIG\n] |
| 166 | |
| 167 | The size and checksum fields are unsigned 32bit little endian value. |
Masami Hiramatsu | fbc6e1c | 2020-11-19 14:53:49 +0900 | [diff] [blame] | 168 | |
| 169 | When the boot configuration is added to the initrd image, the total |
| 170 | file size is aligned to 4 bytes. To fill the gap, null characters |
| 171 | (``\0``) will be added. Thus the ``size`` is the length of the bootconfig |
| 172 | file + padding bytes. |
Masami Hiramatsu | 85c46b7 | 2020-02-20 21:18:42 +0900 | [diff] [blame] | 173 | |
| 174 | The Linux kernel decodes the last part of the initrd image in memory to |
| 175 | get the boot configuration data. |
Masami Hiramatsu | 7b9b816 | 2020-01-11 01:05:06 +0900 | [diff] [blame] | 176 | Because of this "piggyback" method, there is no need to change or |
Masami Hiramatsu | fbc6e1c | 2020-11-19 14:53:49 +0900 | [diff] [blame] | 177 | update the boot loader and the kernel image itself as long as the boot |
| 178 | loader passes the correct initrd file size. If by any chance, the boot |
Bhaskar Chowdhury | 9d54ee7 | 2021-01-07 18:26:10 +0530 | [diff] [blame] | 179 | loader passes a longer size, the kernel fails to find the bootconfig data. |
Masami Hiramatsu | 7b9b816 | 2020-01-11 01:05:06 +0900 | [diff] [blame] | 180 | |
Masami Hiramatsu | 26c9c72 | 2021-09-05 00:54:24 +0900 | [diff] [blame] | 181 | To do this operation, Linux kernel provides ``bootconfig`` command under |
Masami Hiramatsu | 7b9b816 | 2020-01-11 01:05:06 +0900 | [diff] [blame] | 182 | tools/bootconfig, which allows admin to apply or delete the config file |
Masami Hiramatsu | a4798eb | 2020-01-20 12:23:12 +0900 | [diff] [blame] | 183 | to/from initrd image. You can build it by the following command:: |
Masami Hiramatsu | 7b9b816 | 2020-01-11 01:05:06 +0900 | [diff] [blame] | 184 | |
| 185 | # make -C tools/bootconfig |
| 186 | |
| 187 | To add your boot config file to initrd image, run bootconfig as below |
| 188 | (Old data is removed automatically if exists):: |
| 189 | |
| 190 | # tools/bootconfig/bootconfig -a your-config /boot/initrd.img-X.Y.Z |
| 191 | |
| 192 | To remove the config from the image, you can use -d option as below:: |
| 193 | |
| 194 | # tools/bootconfig/bootconfig -d /boot/initrd.img-X.Y.Z |
| 195 | |
Steven Rostedt (VMware) | 7495e09 | 2020-02-04 07:33:53 -0500 | [diff] [blame] | 196 | Then add "bootconfig" on the normal kernel command line to tell the |
| 197 | kernel to look for the bootconfig at the end of the initrd file. |
Masami Hiramatsu | 7b9b816 | 2020-01-11 01:05:06 +0900 | [diff] [blame] | 198 | |
Masami Hiramatsu | 26c9c72 | 2021-09-05 00:54:24 +0900 | [diff] [blame] | 199 | |
| 200 | Kernel parameters via Boot Config |
| 201 | ================================= |
| 202 | |
| 203 | In addition to the kernel command line, the boot config can be used for |
| 204 | passing the kernel parameters. All the key-value pairs under ``kernel`` |
| 205 | key will be passed to kernel cmdline directly. Moreover, the key-value |
| 206 | pairs under ``init`` will be passed to init process via the cmdline. |
| 207 | The parameters are concatinated with user-given kernel cmdline string |
| 208 | as the following order, so that the command line parameter can override |
| 209 | bootconfig parameters (this depends on how the subsystem handles parameters |
| 210 | but in general, earlier parameter will be overwritten by later one.):: |
| 211 | |
| 212 | [bootconfig params][cmdline params] -- [bootconfig init params][cmdline init params] |
| 213 | |
| 214 | Here is an example of the bootconfig file for kernel/init parameters.:: |
| 215 | |
| 216 | kernel { |
| 217 | root = 01234567-89ab-cdef-0123-456789abcd |
| 218 | } |
| 219 | init { |
| 220 | splash |
| 221 | } |
| 222 | |
| 223 | This will be copied into the kernel cmdline string as the following:: |
| 224 | |
| 225 | root="01234567-89ab-cdef-0123-456789abcd" -- splash |
| 226 | |
| 227 | If user gives some other command line like,:: |
| 228 | |
| 229 | ro bootconfig -- quiet |
| 230 | |
| 231 | The final kernel cmdline will be the following:: |
| 232 | |
| 233 | root="01234567-89ab-cdef-0123-456789abcd" ro bootconfig -- splash quiet |
| 234 | |
| 235 | |
Masami Hiramatsu | a4798eb | 2020-01-20 12:23:12 +0900 | [diff] [blame] | 236 | Config File Limitation |
Masami Hiramatsu | 7b9b816 | 2020-01-11 01:05:06 +0900 | [diff] [blame] | 237 | ====================== |
| 238 | |
| 239 | Currently the maximum config size size is 32KB and the total key-words (not |
| 240 | key-value entries) must be under 1024 nodes. |
| 241 | Note: this is not the number of entries but nodes, an entry must consume |
| 242 | more than 2 nodes (a key-word and a value). So theoretically, it will be |
| 243 | up to 512 key-value pairs. If keys contains 3 words in average, it can |
| 244 | contain 256 key-value pairs. In most cases, the number of config items |
| 245 | will be under 100 entries and smaller than 8KB, so it would be enough. |
| 246 | If the node number exceeds 1024, parser returns an error even if the file |
Masami Hiramatsu | fbc6e1c | 2020-11-19 14:53:49 +0900 | [diff] [blame] | 247 | size is smaller than 32KB. (Note that this maximum size is not including |
| 248 | the padding null characters.) |
Masami Hiramatsu | 7b9b816 | 2020-01-11 01:05:06 +0900 | [diff] [blame] | 249 | Anyway, since bootconfig command verifies it when appending a boot config |
| 250 | to initrd image, user can notice it before boot. |
| 251 | |
| 252 | |
| 253 | Bootconfig APIs |
| 254 | =============== |
| 255 | |
| 256 | User can query or loop on key-value pairs, also it is possible to find |
| 257 | a root (prefix) key node and find key-values under that node. |
| 258 | |
| 259 | If you have a key string, you can query the value directly with the key |
Masami Hiramatsu | a4798eb | 2020-01-20 12:23:12 +0900 | [diff] [blame] | 260 | using xbc_find_value(). If you want to know what keys exist in the boot |
| 261 | config, you can use xbc_for_each_key_value() to iterate key-value pairs. |
Masami Hiramatsu | 7b9b816 | 2020-01-11 01:05:06 +0900 | [diff] [blame] | 262 | Note that you need to use xbc_array_for_each_value() for accessing |
Masami Hiramatsu | a4798eb | 2020-01-20 12:23:12 +0900 | [diff] [blame] | 263 | each array's value, e.g.:: |
Masami Hiramatsu | 7b9b816 | 2020-01-11 01:05:06 +0900 | [diff] [blame] | 264 | |
| 265 | vnode = NULL; |
| 266 | xbc_find_value("key.word", &vnode); |
| 267 | if (vnode && xbc_node_is_array(vnode)) |
| 268 | xbc_array_for_each_value(vnode, value) { |
| 269 | printk("%s ", value); |
| 270 | } |
| 271 | |
Masami Hiramatsu | a4798eb | 2020-01-20 12:23:12 +0900 | [diff] [blame] | 272 | If you want to focus on keys which have a prefix string, you can use |
| 273 | xbc_find_node() to find a node by the prefix string, and iterate |
Masami Hiramatsu | 7b9b816 | 2020-01-11 01:05:06 +0900 | [diff] [blame] | 274 | keys under the prefix node with xbc_node_for_each_key_value(). |
| 275 | |
| 276 | But the most typical usage is to get the named value under prefix |
| 277 | or get the named array under prefix as below:: |
| 278 | |
| 279 | root = xbc_find_node("key.prefix"); |
| 280 | value = xbc_node_find_value(root, "option", &vnode); |
| 281 | ... |
| 282 | xbc_node_for_each_array_value(root, "array-option", value, anode) { |
| 283 | ... |
| 284 | } |
| 285 | |
| 286 | This accesses a value of "key.prefix.option" and an array of |
| 287 | "key.prefix.array-option". |
| 288 | |
Masami Hiramatsu | a4798eb | 2020-01-20 12:23:12 +0900 | [diff] [blame] | 289 | Locking is not needed, since after initialization, the config becomes |
| 290 | read-only. All data and keys must be copied if you need to modify it. |
Masami Hiramatsu | 7b9b816 | 2020-01-11 01:05:06 +0900 | [diff] [blame] | 291 | |
| 292 | |
| 293 | Functions and structures |
| 294 | ======================== |
| 295 | |
| 296 | .. kernel-doc:: include/linux/bootconfig.h |
| 297 | .. kernel-doc:: lib/bootconfig.c |
| 298 | |