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。

备注

并非必须创建内核类型 SCC。BSP 文件可通过 define KTYPE myktype 隐式定义,见 “BSP 描述”。

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 分支应用补丁。