162306a36Sopenharmony_ci.. SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci 362306a36Sopenharmony_ci.. _bootconfig: 462306a36Sopenharmony_ci 562306a36Sopenharmony_ci================== 662306a36Sopenharmony_ciBoot Configuration 762306a36Sopenharmony_ci================== 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci:Author: Masami Hiramatsu <mhiramat@kernel.org> 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ciOverview 1262306a36Sopenharmony_ci======== 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ciThe boot configuration expands the current kernel command line to support 1562306a36Sopenharmony_ciadditional key-value data when booting the kernel in an efficient way. 1662306a36Sopenharmony_ciThis allows administrators to pass a structured-Key config file. 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ciConfig File Syntax 1962306a36Sopenharmony_ci================== 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ciThe boot config syntax is a simple structured key-value. Each key consists 2262306a36Sopenharmony_ciof dot-connected-words, and key and value are connected by ``=``. The value 2362306a36Sopenharmony_cihas to be terminated by semi-colon (``;``) or newline (``\n``). 2462306a36Sopenharmony_ciFor array value, array entries are separated by comma (``,``). :: 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci KEY[.WORD[...]] = VALUE[, VALUE2[...]][;] 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ciUnlike the kernel command line syntax, spaces are OK around the comma and ``=``. 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ciEach key word must contain only alphabets, numbers, dash (``-``) or underscore 3162306a36Sopenharmony_ci(``_``). And each value only contains printable characters or spaces except 3262306a36Sopenharmony_cifor delimiters such as semi-colon (``;``), new-line (``\n``), comma (``,``), 3362306a36Sopenharmony_cihash (``#``) and closing brace (``}``). 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ciIf you want to use those delimiters in a value, you can use either double- 3662306a36Sopenharmony_ciquotes (``"VALUE"``) or single-quotes (``'VALUE'``) to quote it. Note that 3762306a36Sopenharmony_ciyou can not escape these quotes. 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ciThere can be a key which doesn't have value or has an empty value. Those keys 4062306a36Sopenharmony_ciare used for checking if the key exists or not (like a boolean). 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ciKey-Value Syntax 4362306a36Sopenharmony_ci---------------- 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ciThe boot config file syntax allows user to merge partially same word keys 4662306a36Sopenharmony_ciby brace. For example:: 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci foo.bar.baz = value1 4962306a36Sopenharmony_ci foo.bar.qux.quux = value2 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ciThese can be written also in:: 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci foo.bar { 5462306a36Sopenharmony_ci baz = value1 5562306a36Sopenharmony_ci qux.quux = value2 5662306a36Sopenharmony_ci } 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ciOr more shorter, written as following:: 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci foo.bar { baz = value1; qux.quux = value2 } 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ciIn both styles, same key words are automatically merged when parsing it 6362306a36Sopenharmony_ciat boot time. So you can append similar trees or key-values. 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ciSame-key Values 6662306a36Sopenharmony_ci--------------- 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ciIt is prohibited that two or more values or arrays share a same-key. 6962306a36Sopenharmony_ciFor example,:: 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci foo = bar, baz 7262306a36Sopenharmony_ci foo = qux # !ERROR! we can not re-define same key 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ciIf you want to update the value, you must use the override operator 7562306a36Sopenharmony_ci``:=`` explicitly. For example:: 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci foo = bar, baz 7862306a36Sopenharmony_ci foo := qux 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_cithen, the ``qux`` is assigned to ``foo`` key. This is useful for 8162306a36Sopenharmony_cioverriding the default value by adding (partial) custom bootconfigs 8262306a36Sopenharmony_ciwithout parsing the default bootconfig. 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ciIf you want to append the value to existing key as an array member, 8562306a36Sopenharmony_ciyou can use ``+=`` operator. For example:: 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci foo = bar, baz 8862306a36Sopenharmony_ci foo += qux 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ciIn this case, the key ``foo`` has ``bar``, ``baz`` and ``qux``. 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ciMoreover, sub-keys and a value can coexist under a parent key. 9362306a36Sopenharmony_ciFor example, following config is allowed.:: 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci foo = value1 9662306a36Sopenharmony_ci foo.bar = value2 9762306a36Sopenharmony_ci foo := value3 # This will update foo's value. 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ciNote, since there is no syntax to put a raw value directly under a 10062306a36Sopenharmony_cistructured key, you have to define it outside of the brace. For example:: 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci foo { 10362306a36Sopenharmony_ci bar = value1 10462306a36Sopenharmony_ci bar { 10562306a36Sopenharmony_ci baz = value2 10662306a36Sopenharmony_ci qux = value3 10762306a36Sopenharmony_ci } 10862306a36Sopenharmony_ci } 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ciAlso, the order of the value node under a key is fixed. If there 11162306a36Sopenharmony_ciare a value and subkeys, the value is always the first child node 11262306a36Sopenharmony_ciof the key. Thus if user specifies subkeys first, e.g.:: 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci foo.bar = value1 11562306a36Sopenharmony_ci foo = value2 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ciIn the program (and /proc/bootconfig), it will be shown as below:: 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci foo = value2 12062306a36Sopenharmony_ci foo.bar = value1 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ciComments 12362306a36Sopenharmony_ci-------- 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ciThe config syntax accepts shell-script style comments. The comments starting 12662306a36Sopenharmony_ciwith hash ("#") until newline ("\n") will be ignored. 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci:: 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci # comment line 13162306a36Sopenharmony_ci foo = value # value is set to foo. 13262306a36Sopenharmony_ci bar = 1, # 1st element 13362306a36Sopenharmony_ci 2, # 2nd element 13462306a36Sopenharmony_ci 3 # 3rd element 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ciThis is parsed as below:: 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci foo = value 13962306a36Sopenharmony_ci bar = 1, 2, 3 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ciNote that you can not put a comment between value and delimiter(``,`` or 14262306a36Sopenharmony_ci``;``). This means following config has a syntax error :: 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci key = 1 # comment 14562306a36Sopenharmony_ci ,2 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci/proc/bootconfig 14962306a36Sopenharmony_ci================ 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci/proc/bootconfig is a user-space interface of the boot config. 15262306a36Sopenharmony_ciUnlike /proc/cmdline, this file shows the key-value style list. 15362306a36Sopenharmony_ciEach key-value pair is shown in each line with following style:: 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci KEY[.WORDS...] = "[VALUE]"[,"VALUE2"...] 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ciBoot Kernel With a Boot Config 15962306a36Sopenharmony_ci============================== 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ciThere are two options to boot the kernel with bootconfig: attaching the 16262306a36Sopenharmony_cibootconfig to the initrd image or embedding it in the kernel itself. 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ciAttaching a Boot Config to Initrd 16562306a36Sopenharmony_ci--------------------------------- 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ciSince the boot configuration file is loaded with initrd by default, 16862306a36Sopenharmony_ciit will be added to the end of the initrd (initramfs) image file with 16962306a36Sopenharmony_cipadding, size, checksum and 12-byte magic word as below. 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci[initrd][bootconfig][padding][size(le32)][checksum(le32)][#BOOTCONFIG\n] 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ciThe size and checksum fields are unsigned 32bit little endian value. 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ciWhen the boot configuration is added to the initrd image, the total 17662306a36Sopenharmony_cifile size is aligned to 4 bytes. To fill the gap, null characters 17762306a36Sopenharmony_ci(``\0``) will be added. Thus the ``size`` is the length of the bootconfig 17862306a36Sopenharmony_cifile + padding bytes. 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ciThe Linux kernel decodes the last part of the initrd image in memory to 18162306a36Sopenharmony_ciget the boot configuration data. 18262306a36Sopenharmony_ciBecause of this "piggyback" method, there is no need to change or 18362306a36Sopenharmony_ciupdate the boot loader and the kernel image itself as long as the boot 18462306a36Sopenharmony_ciloader passes the correct initrd file size. If by any chance, the boot 18562306a36Sopenharmony_ciloader passes a longer size, the kernel fails to find the bootconfig data. 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ciTo do this operation, Linux kernel provides ``bootconfig`` command under 18862306a36Sopenharmony_citools/bootconfig, which allows admin to apply or delete the config file 18962306a36Sopenharmony_cito/from initrd image. You can build it by the following command:: 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci # make -C tools/bootconfig 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ciTo add your boot config file to initrd image, run bootconfig as below 19462306a36Sopenharmony_ci(Old data is removed automatically if exists):: 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci # tools/bootconfig/bootconfig -a your-config /boot/initrd.img-X.Y.Z 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ciTo remove the config from the image, you can use -d option as below:: 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci # tools/bootconfig/bootconfig -d /boot/initrd.img-X.Y.Z 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ciThen add "bootconfig" on the normal kernel command line to tell the 20362306a36Sopenharmony_cikernel to look for the bootconfig at the end of the initrd file. 20462306a36Sopenharmony_ciAlternatively, build your kernel with the ``CONFIG_BOOT_CONFIG_FORCE`` 20562306a36Sopenharmony_ciKconfig option selected. 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ciEmbedding a Boot Config into Kernel 20862306a36Sopenharmony_ci----------------------------------- 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ciIf you can not use initrd, you can also embed the bootconfig file in the 21162306a36Sopenharmony_cikernel by Kconfig options. In this case, you need to recompile the kernel 21262306a36Sopenharmony_ciwith the following configs:: 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci CONFIG_BOOT_CONFIG_EMBED=y 21562306a36Sopenharmony_ci CONFIG_BOOT_CONFIG_EMBED_FILE="/PATH/TO/BOOTCONFIG/FILE" 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci``CONFIG_BOOT_CONFIG_EMBED_FILE`` requires an absolute path or a relative 21862306a36Sopenharmony_cipath to the bootconfig file from source tree or object tree. 21962306a36Sopenharmony_ciThe kernel will embed it as the default bootconfig. 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ciJust as when attaching the bootconfig to the initrd, you need ``bootconfig`` 22262306a36Sopenharmony_cioption on the kernel command line to enable the embedded bootconfig, or, 22362306a36Sopenharmony_cialternatively, build your kernel with the ``CONFIG_BOOT_CONFIG_FORCE`` 22462306a36Sopenharmony_ciKconfig option selected. 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ciNote that even if you set this option, you can override the embedded 22762306a36Sopenharmony_cibootconfig by another bootconfig which attached to the initrd. 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ciKernel parameters via Boot Config 23062306a36Sopenharmony_ci================================= 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ciIn addition to the kernel command line, the boot config can be used for 23362306a36Sopenharmony_cipassing the kernel parameters. All the key-value pairs under ``kernel`` 23462306a36Sopenharmony_cikey will be passed to kernel cmdline directly. Moreover, the key-value 23562306a36Sopenharmony_cipairs under ``init`` will be passed to init process via the cmdline. 23662306a36Sopenharmony_ciThe parameters are concatenated with user-given kernel cmdline string 23762306a36Sopenharmony_cias the following order, so that the command line parameter can override 23862306a36Sopenharmony_cibootconfig parameters (this depends on how the subsystem handles parameters 23962306a36Sopenharmony_cibut in general, earlier parameter will be overwritten by later one.):: 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ci [bootconfig params][cmdline params] -- [bootconfig init params][cmdline init params] 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ciHere is an example of the bootconfig file for kernel/init parameters.:: 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci kernel { 24662306a36Sopenharmony_ci root = 01234567-89ab-cdef-0123-456789abcd 24762306a36Sopenharmony_ci } 24862306a36Sopenharmony_ci init { 24962306a36Sopenharmony_ci splash 25062306a36Sopenharmony_ci } 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ciThis will be copied into the kernel cmdline string as the following:: 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci root="01234567-89ab-cdef-0123-456789abcd" -- splash 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ciIf user gives some other command line like,:: 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci ro bootconfig -- quiet 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_ciThe final kernel cmdline will be the following:: 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci root="01234567-89ab-cdef-0123-456789abcd" ro bootconfig -- splash quiet 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ciConfig File Limitation 26662306a36Sopenharmony_ci====================== 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ciCurrently the maximum config size size is 32KB and the total key-words (not 26962306a36Sopenharmony_cikey-value entries) must be under 1024 nodes. 27062306a36Sopenharmony_ciNote: this is not the number of entries but nodes, an entry must consume 27162306a36Sopenharmony_cimore than 2 nodes (a key-word and a value). So theoretically, it will be 27262306a36Sopenharmony_ciup to 512 key-value pairs. If keys contains 3 words in average, it can 27362306a36Sopenharmony_cicontain 256 key-value pairs. In most cases, the number of config items 27462306a36Sopenharmony_ciwill be under 100 entries and smaller than 8KB, so it would be enough. 27562306a36Sopenharmony_ciIf the node number exceeds 1024, parser returns an error even if the file 27662306a36Sopenharmony_cisize is smaller than 32KB. (Note that this maximum size is not including 27762306a36Sopenharmony_cithe padding null characters.) 27862306a36Sopenharmony_ciAnyway, since bootconfig command verifies it when appending a boot config 27962306a36Sopenharmony_cito initrd image, user can notice it before boot. 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ciBootconfig APIs 28362306a36Sopenharmony_ci=============== 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ciUser can query or loop on key-value pairs, also it is possible to find 28662306a36Sopenharmony_cia root (prefix) key node and find key-values under that node. 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ciIf you have a key string, you can query the value directly with the key 28962306a36Sopenharmony_ciusing xbc_find_value(). If you want to know what keys exist in the boot 29062306a36Sopenharmony_ciconfig, you can use xbc_for_each_key_value() to iterate key-value pairs. 29162306a36Sopenharmony_ciNote that you need to use xbc_array_for_each_value() for accessing 29262306a36Sopenharmony_cieach array's value, e.g.:: 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci vnode = NULL; 29562306a36Sopenharmony_ci xbc_find_value("key.word", &vnode); 29662306a36Sopenharmony_ci if (vnode && xbc_node_is_array(vnode)) 29762306a36Sopenharmony_ci xbc_array_for_each_value(vnode, value) { 29862306a36Sopenharmony_ci printk("%s ", value); 29962306a36Sopenharmony_ci } 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ciIf you want to focus on keys which have a prefix string, you can use 30262306a36Sopenharmony_cixbc_find_node() to find a node by the prefix string, and iterate 30362306a36Sopenharmony_cikeys under the prefix node with xbc_node_for_each_key_value(). 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ciBut the most typical usage is to get the named value under prefix 30662306a36Sopenharmony_cior get the named array under prefix as below:: 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci root = xbc_find_node("key.prefix"); 30962306a36Sopenharmony_ci value = xbc_node_find_value(root, "option", &vnode); 31062306a36Sopenharmony_ci ... 31162306a36Sopenharmony_ci xbc_node_for_each_array_value(root, "array-option", value, anode) { 31262306a36Sopenharmony_ci ... 31362306a36Sopenharmony_ci } 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ciThis accesses a value of "key.prefix.option" and an array of 31662306a36Sopenharmony_ci"key.prefix.array-option". 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ciLocking is not needed, since after initialization, the config becomes 31962306a36Sopenharmony_ciread-only. All data and keys must be copied if you need to modify it. 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ciFunctions and structures 32362306a36Sopenharmony_ci======================== 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci.. kernel-doc:: include/linux/bootconfig.h 32662306a36Sopenharmony_ci.. kernel-doc:: lib/bootconfig.c 32762306a36Sopenharmony_ci 328