为什么要单独建一层
把板级改动直接写进 meta-phosphor 或 meta-phytium 是最省事的做法,代价是基线一升级就全部冲突。正确姿势是新建一个自己的层,把"这款板子特有的东西"全部收在里面:设备树、传感器阈值、风扇曲线、GPIO 定义、LED 配置、网络配置、签名密钥与升级脚本。这样上游层始终是干净的,升级时只需要处理自己那一层。
判断某个改动该不该放进自己的层,就问一句:换一款板子它还需要吗? 不需要,就属于板级定制。
一个机型层的最小结构
meta-机型名/
bash
├── conf/
│ ├── layer.conf # 层入口,必须有
│ ├── machine/机型名.conf # 机型定义:设备树、串口、镜像格式
│ ├── bblayers.conf.sample # 可选:给 setup 脚本用的模板
│ └── local.conf.sample # 可选:构建参数模板
└── recipes-*/ # 按功能分组的配方与 bbappend
其中 conf/layer.conf 与 conf/machine/机型名.conf 是不可省的两个文件,其余都是"有定制才加"。
以 meta-e2000s 为例:一个真实机型层的构成
实际的 meta-e2000s 层一共 37 个文件,可以按职责分成下面几类。做新型号时照着这张表逐项确认,基本不会漏:
|-----------|----------------------------------------------------------------------|----------------------------------------------|
| 分类 | 典型路径 | 说明 |
| 层与机型定义 | conf/layer.conf、conf/machine/e2000s.conf | 层入口、机型变量(设备树、串口、镜像格式) |
| 内核设备树 | recipes-kernel/linux/linux-phytium/.../phytium-bmc-e2000s.dts | 板级 dts,配 KERNEL_DEVICETREE 使用 |
| 传感器与实体管理 | recipes-phosphor/configuration/entity-manager/ | PS23 平台 JSON、FRU bin、黑白名单 |
| 风扇控制 | recipes-phosphor/fans/phosphor-fan-control-events-config/events.yaml | 调速事件与阈值 |
| IPMB 通道 | recipes-phosphor/ipmi/phosphor-ipmi-ipmb/ipmb-channels.json | 双 BMC / ME 通道映射 |
| LED 与定位灯 | recipes-phosphor/leds/e2000s-led-manager-config/ | led.yaml + 一个 native 配方在编译期生成配置 |
| 网络 | recipes-phosphor/network/phosphor-network/ipconfig/ | systemd-networkd 的网口配置 |
| 虚拟传感器 | recipes-phosphor/sensors/phosphor-virtual-sensor/ | 按公式合成的传感器(如整机功耗) |
| GPIO | recipes-phytium/gpio/gpio-manager/gpio_defs.json | 物理引脚与逻辑名映射 |
| 固件升级辅助 | recipes-phosphor/flash/phosphor-software-manager/ | update-mcu.sh、update-cpld.sh、cpld-version.sh |
| 签名密钥与 FRU | recipes-phytium/configure/phytium-configs-signing-key/ | 固件签名用的 common.pem |
可以看到,一个机型层里真正写"代码"的地方很少,绝大多数是数据文件(JSON / YAML / dts / 脚本),这正符合"配置驱动"的设计------上层 phosphor 服务负责逻辑,机型层只喂数据。
layer.conf 怎么写
bash
BBPATH .= ":${LAYERDIR}"
BBFILES += "${LAYERDIR}/recipes-*/*/*.bb ${LAYERDIR}/recipes-*/*/*.bbappend"
BBFILE_COLLECTIONS += "机型层标识"
BBFILE_PATTERN_机型层标识 := "^${LAYERDIR}/"
BBFILE_PRIORITY_机型层标识 = "10"
LAYERSERIES_COMPAT_机型层标识 = "honister"
四点注意:BBFILES 的通配要能覆盖到你的 recipes 目录深度;BBFILE_PATTERN 用来把该目录下的配方归到这个层;BBFILE_PRIORITY 决定同名文件谁覆盖谁;LAYERSERIES_COMPAT 必须与 Yocto 版本代号一致,写错会导致整层被静默跳过,症状是配方明明存在却 BB 报 not found。
注册到 bblayers.conf 与优先级
层要生效必须在 build/机型名/conf/bblayers.conf 的 BBLAYERS 里列出来。顺序即优先级的一部分:越靠后优先级越高(在 BBFILE_PRIORITY 相同时起作用)。机型层应该排在 meta-phytium、meta-phosphor 之后。
BBLAYERS += "${TOPDIR}/../meta-phytium-openbmc/meta-e2000s"
加完层之后不要忘记重新进入构建环境(或直接执行 bitbake -r conf/bblayers.conf),否则当前 shell 里的解析结果还是旧的。
复制一个机型层是最快的起步方式
做新型号时不必从零写:复制一个结构完整的老机型层,然后做三件事------改目录名、把文件名里的机型名替换掉、把文件内容里的机型名替换掉;替换时注意 dts 里的 compatible 字符串、machine conf 里的 KERNEL_DEVICETREE 与 UBOOT_MACHINE 也要一起改,否则会出现"编出来的固件还是老机型"的情况。
建完怎么验证
bash
bitbake-layers show-layers # 确认层已加载,优先级正确
bitbake-layers show-appends | grep 你的包名 # 确认 bbappend 被匹配到
bitbake -e 你的包名 | grep -E '^(SRC_URI|FILESEXTRAPATHS)=' # 确认文件真的进了 SRC_URI
bitbake 你的包名 -c unpack && ls tmp/work/... # 确认文件落到了源码树
最容易被忽略的是第三步:bbappend 写得看起来没问题,但 FILESEXTRAPATHS 指错了目录,file:// 就永远找不到文件,报错还会伪装成"补丁不存在"。
常见坑
- 层目录下没有 conf/layer.conf:层不会被识别;devtool finish 指到这个目录也会直接报错;
- LAYERSERIES_COMPAT 与当前 Yocto 代号不一致:整层静默失效;
- BBFILES 深度写死(如只写 recipes-*/*/*.bb),配方放在更深或更浅一层目录时找不到;
- 同名 bbappend 在多个层里都存在:按优先级只生效一个,排查时用 show-appends 确认到底是哪个在起作用;
- 把板级文件放到上游层里"图方便":下次升级基线必然冲突,且很难回忆起当时改了哪些。