.. SPDX-License-Identifier: GPL-2.0 .. include:: ../disclaimer-zh_CN.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