3 使用高级元数据(yocto-kernel-cache)
3 概述
除配置片段和补丁外,Yocto Project 内核工具还支持丰富的 Metadata, 用于定义复杂策略和 BSP。元数据及其管理工具帮助控制支持多个 BSP、多个内核 类型时的配置和源码复杂度。
内核元数据分布在多处。其中一个位置是
Yocto Project 源码仓库
中的 yocto-kernel-cache Git 仓库,位于
Yocto Project 源码仓库 的 "Yocto Linux Kernel" 分组。
同一分组下的 yocto-kernel-tools 提供内核开发工具 kern-tools,其配方
位于 OpenEmbedded-Core (OE-Core) 的
recipes-kernel/kern-tools/kern-tools-native_git.bb。
3 在配方中使用内核元数据
yocto-kernel-cache 中的元数据定义 BSP,与 linux-yocto 配方中的相应
定义对应。BSP 由内核策略及启用的硬件功能组合而成,可从配方中调整。
备注
包含内核元数据的 Linux 内核配方,例如使用 linux-yocto.inc,称为
“linux-yocto 风格”配方。
这种配方必须定义 KMACHINE,通常与 BitBake 的 MACHINE 相同,也可能指向机器底层平台。
多个 BSP 若使用同一 BSP 描述,可以复用 KMACHINE,例如多个 Corei7 BSP 共用 "intel-corei7-64"。KMACHINE 只用于内核映射,而 MACHINE 是 BSP 层中的机器类型;两者虽有区别,值仍可相同。详见 “BSP 描述”。
配方还必须通过 KBRANCH 指定构建内核所用的源码仓库分支。
备注
通常可用机器覆盖选择其他分支,以下来自 meta-yocto-bsp:
KBRANCH:beaglebone-yocto = "standard/beaglebone"
还可选定义:
LINUX_KERNEL_TYPE 指定组装配置所用内核类型,默认 "standard"。 它与 KMACHINE 一起作为搜索条件,查找元数据中适当描述,生成源码和 配置。配方提供 "standard"、"tiny"、"preempt-rt",详见 “内核类型”。
构建时,kern-tools 搜索最匹配的 BSP 描述,使用首个同时匹配 KMACHINE 和 LINUX_KERNEL_TYPE 的文件,找不到则警告。
工具先匹配 KMACHINE,再匹配类型。如果连部分匹配都找不到,则使用 KBRANCH 源码及 SRC_URI 指定的配置。
KERNEL_FEATURES 可加入上述组合尚未包含的配置、补丁或两者。例如, 加入 "features/netfilter/netfilter.scc":
KERNEL_FEATURES += "features/netfilter/netfilter.scc"
仅为 qemux86 加入 "cfg/sound.scc":
KERNEL_FEATURES:append:qemux86 = " cfg/sound.scc"
条目路径取决于元数据位置。这里来自 yocto-kernel-cache,各分支顶层有
features 和 cfg。详见 “内核元数据语法”。
3 内核元数据语法
主要有三种文件:scc [1] 描述、配置片段和补丁。SCC 定义变量,并包含
或引用三类文件,将它们组合为面向特定机器的 Linux 内核源码和配置描述。
SCC 用于定义两种基本元数据:
功能
板级支持包(BSP)
功能把补丁和配置片段封装为可复用模块,可表示纯配置、简单补丁、复杂功能 以及 内核类型。内核类型定义 BSP 可复用的 通用功能和策略。
BSP 定义硬件功能,并与内核类型结合,形成最终组装和构建描述。
语法不强制区分配置、补丁、功能及类型,但建议按逻辑组织,目录结构如下:
base/
bsp/
cfg/
features/
ktypes/
patches/
bsp 保存 BSP 描述,其余均为功能。
这样分隔有助于理解用途。
SCC 文件位置建议:
只有配置片段:放在
cfg。只有源码修复:放在
patches。封装主要功能,常同时包含源码和配置:放在
features。汇集非硬件配置和补丁,定义多个 BSP 共用的基础策略或主要内核类型: 放在
ktypes。
随着树外功能逐渐进入上游,这些区别可能模糊。目录只是逻辑组织,不影响功能,
因为在工具看来,cfg、features、patches、ktypes 都是功能。
路径基准取决于位置:配方空间 中以 FILESEXTRAPATHS 为基准; 配方空间之外的元数据 则以 yocto-kernel-cache 顶层为基准。
3 配置
最简单的元数据是仅配置功能:.cfg 包含一个或多个内核参数,.scc
描述该片段。
例如,linux-yocto-4.12 在配方空间外的 SMP 功能由 smp.scc 和
smp.cfg 组成,位于 yocto-kernel-cache 的 yocto-4.12 分支
cfg 目录:
cfg/smp.scc:
define KFEATURE_DESCRIPTION "Enable SMP for 32 bit builds"
define KFEATURE_COMPATIBILITY all
kconf hardware smp.cfg
cfg/smp.cfg:
CONFIG_SMP=y
CONFIG_SCHED_SMT=y
# Increase default NR_CPUS from 8 to 64 so that platform with
# more than 8 processors can be all activated at boot time
CONFIG_NR_CPUS=64
# The following is needed when setting NR_CPUS to something
# greater than 8 on x86 architectures, it should be automatically
# disregarded by Kconfig when using a different arch
CONFIG_X86_BIGSMP=y
配置片段的一般说明见 “创建配置片段”。
smp.scc 中的 KFEATURE_DESCRIPTION 提供简短描述,供高级工具使用。
kconf 引入实际配置片段;"hardware" 表示硬件启用配置,而一般策略使用
"non-hardware"。验证工具利用这一区别,在硬件片段覆盖非硬件策略时警告。
备注
可包含多个 kconf,每条对应一个片段。
按 “验证配置” 所述,可运行审计:
$ bitbake linux-yocto -c kernel_configcheck -f
3 补丁
补丁描述与配置描述类似,但处理的是 .patch 而非 .cfg。
典型补丁包含描述文件和补丁本身。例如,linux-yocto-4.12 的构建补丁
位于 yocto-kernel-cache 的 yocto-4.12 分支 patches/build,
包含 build.scc 和多个补丁。
以下为描述文件及 modpost-mask-trivial-warnings.patch 的部分内容:
patches/build/build.scc:
patch arm-serialize-build-targets.patch
patch powerpc-serialize-image-targets.patch
patch kbuild-exclude-meta-directory-from-distclean-processi.patch
# applied by kgit
# patch kbuild-add-meta-files-to-the-ignore-li.patch
patch modpost-mask-trivial-warnings.patch
patch menuconfig-check-lxdiaglog.sh-Allow-specification-of.patch
patches/build/modpost-mask-trivial-warnings.patch:
From bd48931bc142bdd104668f3a062a1f22600aae61 Mon Sep 17 00:00:00 2001
From: Paul Gortmaker <paul.gortmaker@windriver.com>
Date: Sun, 25 Jan 2009 17:58:09 -0500
Subject: [PATCH] modpost: mask trivial warnings
Newer HOSTCC will complain about various stdio fcns because
.
.
.
char *dump_write = NULL, *files_source = NULL;
int opt;
--
2.10.1
generated by cgit v0.10.2 at 2017-09-28 15:23:23 (GMT)
描述可包含多条 patch,每条处理一个补丁。上例有五条,对应目录中五个补丁。
可用 diff -Nurp 或 git format-patch 创建补丁,见
“使用 devtool 修补内核” 和
“使用传统内核开发流程修补内核”。
3 功能
功能是更复杂的元数据,包含配置片段、补丁及可能的其他功能描述,例如:
features/myfeature.scc
define KFEATURE_DESCRIPTION "Enable myfeature"
patch 0001-myfeature-core.patch
patch 0002-myfeature-interface.patch
include cfg/myfeature_dependency.scc
kconf non-hardware myfeature.cfg
此例展示 patch、kconf,以及通过 include 引入另一功能描述。
功能通常比配置片段粒度更大,更适合直接放在内核配方的 KERNEL_FEATURES,见 “在配方中使用内核元数据”。
3 内核类型
内核类型结合非硬件配置和补丁,为实时内核等特定类型定义高级策略,语法与
功能 相同。配方用 LINUX_KERNEL_TYPE
选择。例如,meta/recipes-kernel/linux 中的 linux-yocto_4.12.bb
通过 require
引入 linux-yocto.inc,默认类型如下:
LINUX_KERNEL_TYPE ??= "standard"
实时配方 linux-yocto-rt_4.12.bb 则直接设置:
LINUX_KERNEL_TYPE = "preempt-rt"
备注
内核配方位于源码仓库的 meta/recipes-kernel/linux。另见
Yocto Project 源码仓库
和 “在配方中使用内核元数据”。
支持三种类型:
"standard":通用 Linux 策略,包括文件系统、网络、核心功能及调试跟踪选项。
"preempt-rt":继承 standard,应用
PREEMPT_RT补丁和实时内核所需配置。"tiny":为极小内核提供最小基础配置,独立于 standard。目前不含源码 修改,但未来可能包含。
每个类型由 SCC 定义。以下是 yocto-kernel-cache/ktypes/standard 中
standard.scc 的部分内容:
# Include this kernel type fragment to get the standard features and
# configuration values.
# Note: if only the features are desired, but not the configuration
# then this should be included as:
# include ktypes/standard/standard.scc nocfg
# if no chained configuration is desired, include it as:
# include ktypes/standard/standard.scc nocfg inherit
include ktypes/base/base.scc
branch standard
kconf non-hardware standard.cfg
include features/kgdb/kgdb.scc
.
.
.
include cfg/net/ip6_nf.scc
include cfg/net/bridge.scc
include cfg/systemd.scc
include features/rfkill/rfkill.scc
与其他 SCC 一样,可用 include 汇集描述,也可直接用 kconf 和 patch。
3 BSP 描述
BSP SCC 将内核类型与硬件功能结合。硬件元数据通常独立定义在 BSP 层,再与 各受支持内核类型组合。
备注
项目支持的 BSP 描述位于
Yocto Project 源码仓库 中 yocto-kernel-cache 的 bsp。
本节介绍结构、组合方式,并以 BeagleBone 为例。完整 BSP 层目录结构见 Yocto Project 板级支持包(BSP)手册。
3 描述概览
以 BeagleBone 顶层描述为例,为保持一致性,名称采用:
bsp_root_name-kernel_type.scc
实际文件名示例:
beaglebone-standard.scc
beaglebone-preempt-rt.scc
均以 BSP 根名称 "beaglebone" 加内核类型组成。
查看 beaglebone-standard.scc:
define KMACHINE beaglebone
define KTYPE standard
define KARCH arm
include ktypes/standard/standard.scc
branch beaglebone
include beaglebone.scc
# default policy for standard kernels
include features/latencytop/latencytop.scc
include features/profiling/profiling.scc
每个顶层描述都应定义 KMACHINE、KTYPE 和 KARCH, 让构建系统判断是否匹配配方。本例为 beaglebone、standard、arm。
KTYPE 与内核类型描述文件没有硬性关联。如果元数据未像本例那样定义类型, 只需保证配方 LINUX_KERNEL_TYPE 与 BSP 的 KTYPE 一致。
为分离内核策略和硬件配置,包含 standard 等类型。上例为:
include ktypes/standard/standard.scc
该文件汇集标准策略的配置、补丁和功能,见 内核类型。
为 mybsp 汇集公共配置与内核功能:
include mybsp.scc
BeagleBone 中对应为:
include beaglebone.scc
如何将完整 .config 拆成片段,见
“创建配置片段”。
未放在 SCC 中的硬件配置也可直接包含:
kconf hardware mybsp-extra.cfg
BeagleBone 没有这种配置,但 Malta 32 位板("mti-malta32")有,例如
mti-malta32-le-standard.scc:
define KMACHINE mti-malta32-le
define KMACHINE qemumipsel
define KTYPE standard
define KARCH mips
include ktypes/standard/standard.scc
branch mti-malta32
include mti-malta32.scc
kconf hardware mti-malta32-le.cfg
3 示例
实际案例通常更复杂。BSP 描述同样可以组合功能,例如 linux-yocto-4.4
分支的 yocto-kernel-cache/bsp/minnow/minnow.scc:
include cfg/x86.scc
include features/eg20t/eg20t.scc
include cfg/dmaengine.scc
include features/power/intel.scc
include cfg/efi.scc
include features/usb/ehci-hcd.scc
include features/usb/ohci-hcd.scc
include features/usb/usb-gadgets.scc
include features/usb/touchscreen-composite.scc
include cfg/timer/hpet.scc
include features/leds/leds.scc
include features/spi/spidev.scc
include features/i2c/i2cdev.scc
include features/mei/mei-txe.scc
# Earlyprintk and port debug requires 8250
kconf hardware cfg/8250.cfg
kconf hardware minnow.cfg
kconf hardware minnow-dev.cfg
备注
Minnow BSP 已不使用,但元数据仍保留,此处仅作示例。
minnow.scc 包含专用 minnow.cfg,以及启用板载硬件的通用片段和功能,
再由 standard、preempt-rt、tiny 三种描述引用。例如 minnow-standard.scc:
define KMACHINE minnow
define KTYPE standard
define KARCH i386
include ktypes/standard
include minnow.scc
# Extra minnow configs above the minimal defined in minnow.scc
include cfg/efi-ext.scc
include features/media/media-all.scc
include features/sound/snd_hda_intel.scc
# The following should really be in standard.scc
# USB live-image support
include cfg/usb-mass-storage.scc
include cfg/boot-live.scc
# Basic profiling
include features/latencytop/latencytop.scc
include features/profiling/profiling.scc
# Requested drivers that don't have an existing scc
kconf hardware minnow-drivers-extra.cfg
中间的 include 引入所有内核类型共用的硬件定义,大幅减少重复。
再看 minnow-tiny.scc:
define KMACHINE minnow
define KTYPE tiny
define KARCH i386
include ktypes/tiny
include minnow.scc
tiny 包含更少内容,只有 tiny 类型定义的最小策略,以及基础 minnow 描述 中启动机器和提供基本功能所需的硬件配置。
三个关键变量 KMACHINE、KTYPE、KARCH 中,仅 KTYPE 改为 tiny。
3 内核元数据位置
元数据始终位于内核树之外,可放在配方空间或独立仓库。选择取决于用途和工作 方式,语法相同。
不熟悉内核,只想应用配置和少量别人提供的补丁时,推荐配方空间。源码不受 自己控制,或不想维护内核 Git 仓库时也适合。见 “修改已有配方”。
如果积极开发内核且已维护自己的 Git 仓库,独立元数据可能更方便,有助于在 BitBake 环境外高效迭代。
3 配方空间元数据
文件位于 FILESEXTRAPATHS 下。linux-yocto 配方,或复制并修改
meta-skeleton/recipes-kernel/linux/linux-yocto-custom.bb
生成的配方,通常设为 ${THISDIR}/${PN}。
见 “修改已有配方”。
BSP 层中的简单元数据树示例:
meta-my_bsp_layer/
`-- recipes-kernel
`-- linux
`-- linux-yocto
|-- bsp-standard.scc
|-- bsp.cfg
`-- standard.cfg
需确保 BitBake 能判断要获取哪些文件、何时重新获取。只需在 SRC_URI 列出 SCC,工具会解析并获取 include、patch、kconf 引用的文件。因此,修改 未显式列在 SRC_URI 的文件时,必须递增配方 PR。
BSP 描述不能简单作为单个 SCC 列入 SRC_URI,内核追加文件应采用:
SRC_URI:append:myplatform = " \
file://myplatform;type=kmeta;destsuffix=myplatform \
"
type=kmeta 很关键:将目录加入工具搜索范围,以发现匹配 KMACHINE 和
LINUX_KERNEL_TYPE 的 BSP。直接列出的 file://myplatform.scc 则被视为
配置片段,在配置和补丁阶段都处理。其直接或间接引用的 patch,包括 arch
或 bsp 描述中的补丁,会再次应用到源码;若分支已含这些提交,就会失败。
原因见 “BSP 描述的补丁应用”。
3 配方空间之外的元数据
独立元数据位于另一仓库,通过 SRC_URI 的 "type=kmeta" 引入。
例如 linux-yocto_5.15.bb:
SRC_URI = "https://git.yoctoproject.org/linux-yocto.git;name=machine;branch=${KBRANCH};protocol=https \
https://git.yoctoproject.org/yocto-kernel-cache;type=kmeta;name=meta;branch=yocto-5.15;destsuffix=${KMETA};protocol=https"
${KMETA} 只用于命名 Git 获取器存放元数据的目录,与普通多仓库 SRC_URI
没有区别。
也可以使用包含配置片段的 kernel-cache 目录,同样通过 type=kmeta 在配置 阶段提供元数据。
修改后必须更新内核配方 SRCREV,特别是 SRCREV_meta,使其指向
KMETA 分支所需提交。只修改仓库而不更新修订,会继续获取旧内容。
3 BSP 描述的补丁应用
工具搜索首个同时匹配 KMACHINE 和 LINUX_KERNEL_TYPE 的描述,称为 发现的 BSP 描述。
对于这种描述,工具有意 不应用 直接或经 include 引用的 patch,因为 假定 KBRANCH 历史已包含这些提交,重复应用会失败。但 kconf 始终 应用。因此,发现的 BSP 提供配置,不重新提供补丁。
这也是配方空间 BSP 必须以 type=kmeta 目录,而非单个 file://*.scc 交付
的原因。把描述放进相应目录,并设置 KMACHINE:
KMACHINE:myplatform ?= "myplatform"
SRC_URI:append:myplatform = " \
file://myplatform;type=kmeta;destsuffix=myplatform \
"
myplatform 目录包含例如 myplatform-standard.scc,以
define KMACHINE myplatform 和 define KTYPE standard 开头。
由于它是发现的描述,其自身及 include 引入内容的 patch 都被抑制,配置仍应用。
如果 BSP 确实不在源码历史中,即分支尚无这些提交、必须应用补丁,可以在 描述中显式加入:
define KMETA_EXTERNAL_BSP 1
这样发现的 BSP 也会进入补丁阶段并应用 patch。
3 组织源码
许多基于 linux-yocto-custom.bb 的配方使用单分支内核仓库,适合单机器、
单架构的线性开发。支持多板、多架构时,多分支更有效。例如某板启动所需补丁
尚在开发中或设计不合理,但暂不可缺,不应将它们放入所有内核共用的默认分支。
为最大化复用、减少重复并合理组织变更,可以:
将补丁封装为功能,只在适用 BSP 描述中包含。
创建机器分支,仅在那里应用补丁。
创建功能分支,需要时合并到 BSP。
具体选择取决于开发模式。
3 封装补丁
复用外部静态补丁且不继续开发时,功能封装很合适,无需新增源码分支,只需 将补丁加入功能描述,再从 BSP 引入。方法见 “补丁” 和 “BSP 描述”。
3 机器分支
支持多机器、架构或持续开发板级支持时,按机器建分支更有效。公共源码留在 开发分支,机器专用内容放入对应分支,避免不断重新将补丁整理为功能。
新分支可在配方中通过 KBRANCH 指定:
KBRANCH = "mynewbranch"
或在 BSP 描述中使用 branch:
mybsp.scc:
define KMACHINE mybsp
define KTYPE standard
define KARCH i386
include standard.scc
branch mynewbranch
include mybsp-hw.scc
分支多时,可采用类似 Yocto 内核仓库的层次命名:
common/kernel_type/machine
假设有 standard、small 两类型,三台机器,公共目录 mydir,可能为:
mydir/base
mydir/standard/base
mydir/standard/machine_a
mydir/standard/machine_b
mydir/standard/machine_c
mydir/small/base
mydir/small/machine_a
这样关系清晰:mydir/standard/machine_a 包含 mydir/base 与
mydir/standard/base 的全部内容。standard 和 small 再加入不适合其他
类型的专用源码。
备注
base 分支名源自 Git 内部文件系统限制:不能同时使用 mydir/standard
和 mydir/standard/machine_a,否则 standard 既要是文件又要是目录。
3 功能分支
积极开发新功能时,分支比需要不断更新的一组补丁更高效。工具支持 git merge, 在所有 branch 命令之后加入合并:
mybsp.scc:
define KMACHINE mybsp
define KTYPE standard
define KARCH i386
include standard.scc
branch mynewbranch
git merge myfeature
include mybsp-hw.scc
3 SCC 描述文件参考
SCC 可用命令简表:
branch [ref]:相对于当前分支(通常为${KTYPE})创建分支,基于 当前检出分支,或显式指定的 ref。define:定义 KMACHINE、KTYPE、KARCH 和 KFEATURE_DESCRIPTION 等变量。include SCC_FILE:包含另一 SCC,如同将内容直接插入当前位置解析。kconf [hardware|non-hardware] CFG_FILE:将片段排入队列,合并到最终 Linux.config。git merge GIT_BRANCH:合并功能分支到当前分支。patch PATCH_FILE:向当前 Git 分支应用补丁。