Documentation / translations / zh_TW / admin-guide / bootconfig.rst


Based on kernel version 6.12.4. Page generated on 2024-12-12 21:02 EST.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294
.. SPDX-License-Identifier: GPL-2.0

.. include:: ../disclaimer-zh_TW.rst

:Original: Documentation/admin-guide/bootconfig.rst

:譯者: 吳想成 Wu XiangCheng <bobwxc@email.cn>

========
引導配置
========

:作者: Masami Hiramatsu <mhiramat@kernel.org>

概述
====

引導配置擴展了現有的內核命令行,以一種更有效率的方式在引導內核時進一步支持
鍵值數據。這允許管理員傳遞一份結構化關鍵字的配置文件。

配置文件語法
============

引導配置文件的語法採用非常簡單的鍵值結構。每個關鍵字由點連接的單詞組成,鍵
和值由 ``=`` 連接。值以分號( ``;`` )或換行符( ``\n`` )結尾。數組值中每
個元素由逗號( ``,`` )分隔。::

  KEY[.WORD[...]] = VALUE[, VALUE2[...]][;]

與內核命令行語法不同,逗號和 ``=`` 周圍允許有空格。

關鍵字只允許包含字母、數字、連字符( ``-`` )和下劃線( ``_`` )。值可包含
可打印字符和空格,但分號( ``;`` )、換行符( ``\n`` )、逗號( ``,`` )、
井號( ``#`` )和右大括號( ``}`` )等分隔符除外。

如果你需要在值中使用這些分隔符,可以用雙引號( ``"VALUE"`` )或單引號
( ``'VALUE'`` )括起來。注意,引號無法轉義。

鍵的值可以爲空或不存在。這些鍵用於檢查該鍵是否存在(類似布爾值)。

鍵值語法
--------

引導配置文件語法允許用戶通過大括號合併鍵名部分相同的關鍵字。例如::

 foo.bar.baz = value1
 foo.bar.qux.quux = value2

也可以寫成::

 foo.bar {
    baz = value1
    qux.quux = value2
 }

或者更緊湊一些,寫成::

 foo.bar { baz = value1; qux.quux = value2 }

在這兩種樣式中,引導解析時相同的關鍵字都會自動合併。因此可以追加類似的樹或
鍵值。

相同關鍵字的值
--------------

禁止兩個或多個值或數組共享同一個關鍵字。例如::

 foo = bar, baz
 foo = qux  # !錯誤! 我們不可以重定義相同的關鍵字

如果你想要更新值,必須顯式使用覆蓋操作符 ``:=`` 。例如::

 foo = bar, baz
 foo := qux

這樣 ``foo`` 關鍵字的值就變成了 ``qux`` 。這對於通過添加(部分)自定義引導
配置來覆蓋默認值非常有用,免於解析默認引導配置。

如果你想對現有關鍵字追加值作爲數組成員,可以使用 ``+=`` 操作符。例如::

 foo = bar, baz
 foo += qux

這樣, ``foo`` 關鍵字就同時擁有了 ``bar`` , ``baz`` 和 ``qux`` 。

此外,父關鍵字下可同時存在值和子關鍵字。
例如,下列配置是可行的。::

 foo = value1
 foo.bar = value2
 foo := value3 # 這會更新foo的值。

注意,裸值不能直接放進結構化關鍵字中,必須在大括號外定義它。例如::

 foo {
     bar = value1
     bar {
         baz = value2
         qux = value3
     }
 }

同時,關鍵字下值節點的順序是固定的。如果值和子關鍵字同時存在,值永遠是該關
鍵字的第一個子節點。因此如果用戶先指定子關鍵字,如::

 foo.bar = value1
 foo = value2

則在程序(和/proc/bootconfig)中,它會按如下顯示::

 foo = value2
 foo.bar = value1

註釋
----

配置語法接受shell腳本風格的註釋。註釋以井號( ``#`` )開始,到換行符
( ``\n`` )結束。

::

 # comment line
 foo = value # value is set to foo.
 bar = 1, # 1st element
       2, # 2nd element
       3  # 3rd element

會被解析爲::

 foo = value
 bar = 1, 2, 3

注意你不能把註釋放在值和分隔符( ``,`` 或 ``;`` )之間。如下配置語法是錯誤的::

 key = 1 # comment
       ,2


/proc/bootconfig
================

/proc/bootconfig是引導配置的用戶空間接口。與/proc/cmdline不同,此文件內容以
鍵值列表樣式顯示。
每個鍵值對一行,樣式如下::

 KEY[.WORDS...] = "[VALUE]"[,"VALUE2"...]


用引導配置引導內核
==================

用引導配置引導內核有兩種方法:將引導配置附加到initrd鏡像或直接嵌入內核中。

*initrd: initial RAM disk,初始內存磁盤*

將引導配置附加到initrd
----------------------

由於默認情況下引導配置文件是用initrd加載的,因此它將被添加到initrd(initramfs)
鏡像文件的末尾,其中包含填充、大小、校驗值和12字節幻數,如下所示::

 [initrd][bootconfig][padding][size(le32)][checksum(le32)][#BOOTCONFIG\n]

大小和校驗值爲小端序存放的32位無符號值。

當引導配置被加到initrd鏡像時,整個文件大小會對齊到4字節。空字符( ``\0`` )
會填補對齊空隙。因此 ``size`` 就是引導配置文件的長度+填充的字節。

Linux內核在內存中解碼initrd鏡像的最後部分以獲取引導配置數據。由於這種“揹負式”
的方法,只要引導加載器傳遞了正確的initrd文件大小,就無需更改或更新引導加載器
和內核鏡像本身。如果引導加載器意外傳遞了更長的大小,內核將無法找到引導配置數
據。

Linux內核在tools/bootconfig下提供了 ``bootconfig`` 命令來完成此操作,管理員
可以用它從initrd鏡像中刪除或追加配置文件。你可以用以下命令來構建它::

 # make -C tools/bootconfig

要向initrd鏡像添加你的引導配置文件,請按如下命令操作(舊數據會自動移除)::

 # tools/bootconfig/bootconfig -a your-config /boot/initrd.img-X.Y.Z

要從鏡像中移除配置,可以使用-d選項::

 # tools/bootconfig/bootconfig -d /boot/initrd.img-X.Y.Z

然後在內核命令行上添加 ``bootconfig`` 告訴內核去initrd文件末尾尋找內核配置。

將引導配置嵌入內核
------------------

如果你不能使用initrd,也可以通過Kconfig選項將引導配置文件嵌入內核中。在此情
況下,你需要用以下選項重新編譯內核::

 CONFIG_BOOT_CONFIG_EMBED=y
 CONFIG_BOOT_CONFIG_EMBED_FILE="/引導配置/文件/的/路徑"

``CONFIG_BOOT_CONFIG_EMBED_FILE`` 需要從源碼樹或對象樹開始的引導配置文件的
絕對/相對路徑。內核會將其嵌入作爲默認引導配置。

與將引導配置附加到initrd一樣,你也需要在內核命令行上添加 ``bootconfig`` 告訴
內核去啓用內嵌的引導配置。

注意,即使你已經設置了此選項,仍可用附加到initrd的其他引導配置覆蓋內嵌的引導
配置。

通過引導配置傳遞內核參數
========================

除了內核命令行,引導配置也可以用於傳遞內核參數。所有 ``kernel`` 關鍵字下的鍵
值對都將直接傳遞給內核命令行。此外, ``init`` 下的鍵值對將通過命令行傳遞給
init進程。參數按以下順序與用戶給定的內核命令行字符串相連,因此命令行參數可以
覆蓋引導配置參數(這取決於子系統如何處理參數,但通常前面的參數將被後面的參數
覆蓋)::

 [bootconfig params][cmdline params] -- [bootconfig init params][cmdline init params]

如果引導配置文件給出的kernel/init參數是::

 kernel {
   root = 01234567-89ab-cdef-0123-456789abcd
 }
 init {
  splash
 }

這將被複制到內核命令行字符串中,如下所示::

 root="01234567-89ab-cdef-0123-456789abcd" -- splash

如果用戶給出的其他命令行是::

 ro bootconfig -- quiet

則最後的內核命令行如下::

 root="01234567-89ab-cdef-0123-456789abcd" ro bootconfig -- splash quiet


配置文件的限制
==============

當前最大的配置大小是32KB,關鍵字總數(不是鍵值條目)必須少於1024個節點。
注意:這不是條目數而是節點數,條目必須消耗超過2個節點(一個關鍵字和一個值)。
所以從理論上講最多512個鍵值對。如果關鍵字平均包含3個單詞,則可有256個鍵值對。
在大多數情況下,配置項的數量將少於100個條目,小於8KB,因此這應該足夠了。如果
節點數超過1024,解析器將返回錯誤,即使文件大小小於32KB。(請注意,此最大尺寸
不包括填充的空字符。)
無論如何,因爲 ``bootconfig`` 命令在附加啓動配置到initrd映像時會驗證它,用戶
可以在引導之前注意到它。


引導配置API
===========

用戶可以查詢或遍歷鍵值對,也可以查找(前綴)根關鍵字節點,並在查找該節點下的
鍵值。

如果您有一個關鍵字字符串,則可以直接使用 xbc_find_value() 查詢該鍵的值。如果
你想知道引導配置裏有哪些關鍵字,可以使用 xbc_for_each_key_value() 迭代鍵值對。
請注意,您需要使用 xbc_array_for_each_value() 訪問數組的值,例如::

 vnode = NULL;
 xbc_find_value("key.word", &vnode);
 if (vnode && xbc_node_is_array(vnode))
    xbc_array_for_each_value(vnode, value) {
      printk("%s ", value);
    }

如果您想查找具有前綴字符串的鍵,可以使用 xbc_find_node() 通過前綴字符串查找
節點,然後用 xbc_node_for_each_key_value() 迭代前綴節點下的鍵。

但最典型的用法是獲取前綴下的命名值或前綴下的命名數組,例如::

 root = xbc_find_node("key.prefix");
 value = xbc_node_find_value(root, "option", &vnode);
 ...
 xbc_node_for_each_array_value(root, "array-option", value, anode) {
    ...
 }

這將訪問值“key.prefix.option”的值和“key.prefix.array-option”的數組。

鎖是不需要的,因爲在初始化之後配置只讀。如果需要修改,必須複製所有數據和關鍵字。


函數與結構體
============

相關定義的kernel-doc參見:

 - include/linux/bootconfig.h
 - lib/bootconfig.c