☰
coreboot 集成 Cavium BDK 实战指南:DRAM/PCIe 初始化、自研 Devicetree 与调试配置
2026/10/15 3:03:32 网站建设 项目流程
  • 固件
  • 嵌入式
  • 操作系统
  • 驱动开发

【免费下载链接】coreboot

Read-only mirror of https://review.coreboot.org/coreboot.git. Synced every hour. We don't handle Pull Requests.

项目地址:https://gitcode.com/gh_mirrors/co/coreboot
点击查看免费下载

本文聚焦 coreboot 仓库中针对 Cavium(现 Marvell)OcteonTX 系列 SoC 集成的 BDK(Board Development Kit)模块。你将从本文掌握:BDK 在 coreboot 启动流程中承担了哪些初始化职责(romstage 的 DRAM 初始化、ramstage 的 PCIe/QLM/PHY/BGX/SATA 等外设初始化)、它为何使用一套独立于 coreboot 的 devicetree 机制(key-value 存储与bdk_config_set_fdt()通告方式)、如何用devicetree_convert.py把 DTB 转换成静态 C 数组,以及在 menuconfig 中如何开启分阶段 verbose 日志辅助调试。

BDK 在 coreboot 中的角色与源码结构

根据 Documentation/vendorcode/cavium/bdk.md 的说明,Cavium BDK 的一部分被移植进 coreboot 的 vendorcode,位于 src/vendorcode/cavium/bdk 目录。它按启动阶段承担两类截然不同的初始化工作:

  • romstage:DRAM 初始化——内存训练、SPD 读取、DLL 调优等都由 BDK 的libbdk-dram与libdram子库完成;
  • ramstage:外设初始化——PCIe、QLM(Quad Lane Module,四通道串行收发模块)、SLI(System Level Interface)、PHY、BGX(以太网端口组)、SATA 等高速外设的初始化由libbdk-hal与libbdk-boot子库完成。

从 src/vendorcode/cavium/Makefile.mk 的编译清单可以印证这一点:romstage-y只挂载了libbdk-arch(CSR 寄存器、CPU 型号、NUMA)、libbdk-dram(bdk-dram-config.c、bdk-dram-size.c、bdk-dram-test*.c)以及libdram下的一整套 DDR3 初始化与调优文件(dram-init-ddr3.c、dram-tune-ddr3.c、dram-spd.c、libdram-config-load.c等);而ramstage-y则挂载了bdk-qlm*.c、bdk-pcie*.c、bdk-sata.c、bdk-usb.c、bdk-ecam*.c、bdk-boot*.c、bdk-if-phy*.c等外设初始化代码,两者泾渭分明。

仓库中的 BDK 目录按功能划分为以下几个库:

子库主要职责典型文件
libbdk-arch架构抽象、CSR 访问、CPU 型号识别bdk-csr.c、bdk-model.c、bdk-numa.c
libbdk-boot启动阶段的 QLM/PCIe/USB/GPIO 引导初始化bdk-boot-qlm.c、bdk-boot-pcie.c、bdk-boot.c
libbdk-dramDRAM 配置、地址映射、尺寸探测与测试bdk-dram-config.c、bdk-dram-size.c、bdk-dram-test-*.c
libbdk-hal硬件抽象层:PCIe、QLM、SATA、USB、PHY、时钟、GPIObdk-pcie-cn8xxx.c、bdk-qlm.c、bdk-nic.c、bdk-config.c
libbdk-osBDK 自身初始化入口bdk-init.c
libbdk-trust可信启动支持bdk-trust.c
libdramDDR3 底层初始化与调优算法dram-init-ddr3.c、dram-tune-ddr3.c、dram-spd.c

此外,bdk/lame_string.c(字符串解析辅助)同时被 romstage 和 ramstage 引用,Makefile.mk 中用# FIXME: Get rid of lame_string.c标注了未来移除的意图。

BDK 为何使用自己的 devicetree

文档明确指出:BDK 使用它自己的一套 devicetree,因为与 coreboot 的 devicetree 不兼容。coreboot 自身的 devicetree 采用.cb文件 + 设备树语言(devicetree.cb)描述芯片组与板载设备的静态拓扑,而 BDK 的 devicetree 是纯粹的key-value 对存储——键与值都以字符串形式保存,用于描述板级制造信息、DRAM 配置、QLM/PCIe/USB/GPIO 等运行参数。

key-value 对的数据结构定义在 src/vendorcode/cavium/include/bdk/bdk-devicetree.h 中,极其精简:

struct bdk_devicetree_key_value { const char *key; const char *value; };

数组以{0, 0}作为结束标志(即 key 为 NULL 表示表尾),这与 src/mainboard/cavium/cn8100_sff_evb/bdk_devicetree.c 末尾的{0, 0},终止行完全对应。

通告机制:bdk_config_set_fdt()

文档要求这些 key-value 对必须在 romstage 和 ramstage 中分别通告,使用的是bdk_config_set_fdt()方法。其声明位于 src/vendorcode/cavium/include/bdk/libbdk-hal/bdk-config.h:

int bdk_config_set_fdt(const struct bdk_devicetree_key_value *fdt);

该函数的实现位于 src/vendorcode/cavium/bdk/libbdk-hal/bdk-config.c。从源码可以看出两个关键行为:

  1. 堆与无堆环境的差异处理:在ENV_HAS_HEAP_SECTION(ramstage 等有堆环境)下,传入的 fdt 会被bdk_config_duplicate()完整复制一份,此后配置表归 BDK 所有;在没有堆的早期阶段(如部分 romstage 场景),则直接保存传入的指针。
  2. 运行期可改:bdk_config_set_int()会以"0x%016llx"格式把整数写回配置表(通过set_value()),但注释明确说明这只修改内存中的配置,不会写入持久化存储。

实际的主板代码印证了“两阶段通告”的用法。以仓库内唯一的 Cavium 参考板cn8100_sff_evb为例:

  • 在 src/mainboard/cavium/cn8100_sff_evb/romstage.c 中,platform_romstage_main()先调用bdk_config_set_fdt(devtree),再调用sdram_init()执行 BDK 的 DRAM 初始化;
  • 在 src/mainboard/cavium/cn8100_sff_evb/mainboard.c 中,ramstage 的mainboard_enable()再次调用bdk_config_set_fdt(devtree),随后进行 TWSI(I2C)总线、IO 扩展器、SFP+ 光模块 PHY 等板级硬件配置。

两个阶段引用的是同一个extern const struct bdk_devicetree_key_value devtree[],它定义在bdk_devicetree.c中,并且该文件同时被 romstage 与 ramstage 编译(见 src/mainboard/cavium/cn8100_sff_evb/Makefile.mk)。

配置项的命名与取值规则

BDK 的配置项种类由bdk_config_t枚举定义(见 bdk-config.h),覆盖板级制造数据、网络端口与 PHY 布线、BDK 运行参数、芯片特性、QLM、DRAM、USB、SGPIO、VRM 温控、可信启动等全部领域。每一项的实际 key 字符串、类型、默认值、取值范围都集中登记在config_info[]表中(bdk-config.c)。以下是从该表摘出的部分代表性配置项:

配置项枚举key 格式类型/默认值说明
BDK_CONFIG_BOARD_MODELBOARD-MODEL字符串,默认unknown板卡型号
BDK_CONFIG_BOARD_REVISIONBOARD-REVISION字符串,默认unknown板卡版本
BDK_CONFIG_DDR_SPEEDDDR-SPEED.N%d整数,0–2400(MT/s),默认 0DRAM 速率档位,0 表示由 SPD 自动决定
BDK_CONFIG_QLM_MODEQLM-MODE.N%d.QLM%d字符串QLM 工作模式(如 PCIe/网络)
BDK_CONFIG_QLM_FREQQLM-FREQ.N%d.QLM%d整数,0–10312(MHz)QLM 频率
BDK_CONFIG_PHY_ADDRESSPHY-ADDRESS.N%d.BGX%d.P%d整数,默认 -1网口 PHY 的地址,-1 表示无 PHY
BDK_CONFIG_BGX_ENABLEBGX-ENABLE.N%d.BGX%d.P%d整数,0/1,默认 1是否启用某 BGX 端口
BDK_CONFIG_NUM_PACKET_BUFFERSBDK-NUM-PACKET-BUFFERS整数,0–1000000数据包缓冲数量
BDK_CONFIG_PACKET_BUFFER_SIZEBDK-PACKET-BUFFER-SIZE整数,128–32768,默认 1024数据包缓冲字节数
BDK_CONFIG_BOOT_MENU_TIMEOUTBDK-BOOT-MENU-TIMEOUT整数,0–300 秒,默认 10启动菜单超时
BDK_CONFIG_MULTI_NODEMULTI-NODE整数,0–2,默认 2(自动)多节点模式
BDK_CONFIG_USB_PWR_GPIOUSB-PWR-GPIO.N%d.PORT%d整数,默认 -1USB 电源控制 GPIO,-1 表示无
BDK_CONFIG_DRAM_SCRAMBLEDDR-CONFIG-SCRAMBLE整数,0/1/2,默认 2内存加扰:0 关、1 开、2 仅信任启动开启

参数化 key 中的N%d(节点)、QLM%d、BGX%d、LMC%d(内存控制器)、RANK%d、DIMM%d、PORT%d、LANE%d等占位符,由bdk_config_get_int()/bdk_config_get_str()的变参通过vsnprintf()按config_info[].format展开,例如PHY-ADDRESS.N0.BGX0.P0。

从实现细节看,bdk_config_get_int()(bdk-config.c)的取值过程很有参考价值:

  1. 若配置表未设置(config_fdt为空),直接返回该项默认值;
  2. 用vsnprintf按 format 生成完整 key 并查找;get_value()还支持逐级去掉最后一段(按.切分)回退匹配的机制,例如查不到DDR-CONFIG-CUSTOM-OFFSET.UDIMM.LMC0.N0时依次回退尝试更短前缀;
  3. 解析时对0x前缀走str_to_hex(),否则走str_to_int();
  4. 解析失败或超出min_value/max_value范围时,打印BIOS_WARNING并回退到默认值。

使用 devicetree_convert.py 转换 DTB

文档提到的转换工具是 util/cavium/devicetree_convert.py,其用途是把编译好的 DTB(devicetree blob)转换成静态 C 文件。需要说明的是,该脚本以 Python 2 编写并依赖pyfdt库(from pyfdt.pyfdt import FdtBlobParse),在当前仓库中属于辅助转换工具,需在具备相应 Python 环境的机器上运行。

命令行参数如下:

参数含义
--indtb待解析的已编译 devicetree blob(DTB)路径
--out输出 C 文件的写入路径
--verbose开启详细输出,打印每个 key-value 对

脚本的核心行为(对照 devicetree_convert.py 的实现):

  • 解析 DTB 后,遍历根节点下cavium,bdk节点的所有子节点;
  • 节点路径中的/会被去除,作为配置 key;
  • 每个节点的值必须是单一字符串(脚本中检查type(i) is not unicode时报警跳过);若一个节点下挂多个值(数组/多值),脚本会打印Arrays aren't supported并不予转换——这是该工具的一个重要限制;
  • 输出文件自动生成文件头注释// This file is automatically generated.、// DO NOT EDIT BY HAND.,并#include <bdk-devicetree.h>,随后逐项输出{"key", "value"},,最后以{0, 0},终止整个数组。

转换产物即上文提到的devtree[]数组。仓库中 src/mainboard/cavium/cn8100_sff_evb/bdk_devicetree.c 正是该工具风格的输出,文件头同样标注了“automatically generated / DO NOT EDIT BY HAND”。它的输入源头是 src/mainboard/cavium/cn8100_sff_evb/ddr4-common.dtsi 等 DTS 片段(其中以/ { cavium,bdk { ... } }组织节点),配合 sff8104-linux.dts 由dtc编译(见 Makefile.mk)。

针对 coreboot 的本地化修改

文档“Modifications”一节列出的四项修改,均能在仓库源码中找到对应证据:

  1. 适配 coreboot 工具链编译:全部 BDK 源文件直接以romstage-y/ramstage-y的形式加入 src/vendorcode/cavium/Makefile.mk,由 coreboot 的标准构建系统编译,并在CPPFLAGS_common中追加-Isrc/vendorcode/cavium/include/bdk头文件搜索路径;
  2. 移除 FDT devicetree 支持:coreboot 移植版仅保留上述纯 key-value 的bdk_devicetree.h结构,不再携带完整 FDT 解析栈(bdk_config_set_fdt()的参数类型也从原版 FDT 指针改成了struct bdk_devicetree_key_value指针);
  3. 裁剪与 SoC 启动无关的文件:vendorcode 目录下仅保留libbdk-*与libdram中与 bringup 直接相关的子库,未纳入完整 SDK 中的其他组件;
  4. 新增 Kconfig 调试选项:见下文“调试”一节。

此外可以观察到,部分源文件保留了 Cavium 原版 BSD-3-Clause 或修改后的版权注释(如bdk-config.c注明 “This file consists of data imported from bdk-config.c”,主板的mainboard.c注明 “Derived from Cavium's BSD-3 Clause OCTEONTX-SDK-6.2.0”),说明这些代码是从 Cavium SDK 定向导入并本地化后的产物。

调试:menuconfig 中的 verbose 开关

文档给出的调试入口是 menuconfig 的Chipset → BDK菜单,可为一个或多个阶段开启 verbose 控制台输出。这些选项对应 src/vendorcode/cavium/Kconfig 中if CAVIUM_BDK下的menu "BDK"配置块:

Kconfig 选项作用备注
CAVIUM_BDK在 romstage 中构建 BDK(总开关)def_bool n,并select HAVE_DEBUG_RAM_SETUP
CAVIUM_BDK_VERBOSE_INIT输出 BDK 初始化过程的详细日志
CAVIUM_BDK_VERBOSE_DRAM输出 DRAM 初始化的详细日志default y if DEBUG_RAM_SETUP,即开启 coreboot 通用 DRAM 调试开关时默认随动打开
CAVIUM_BDK_VERBOSE_DRAM_TEST输出 DRAM 测试(raminit tests)详细日志
CAVIUM_BDK_VERBOSE_QLM输出 QLM 初始化详细日志
CAVIUM_BDK_VERBOSE_PCIE_CONFIG输出 PCIe 配置阶段详细日志
CAVIUM_BDK_VERBOSE_PCIE输出 PCIe 初始化阶段详细日志
CAVIUM_BDK_VERBOSE_PHY输出 PHY 初始化详细日志

除调试开关外,同一菜单下还提供了三项 DRAM 自动调优选项,供内存稳定性调试时调整:

  • CAVIUM_BDK_DDR_TUNE_HW_OFFSETS:硬件辅助的 DLL 读偏移调优(默认关闭,开启时同时调优 ECC 字节);
  • CAVIUM_BDK_DDR_TUNE_WRITE_OFFSETS:自动调优数据字节的 DLL 写偏移;
  • CAVIUM_BDK_DDR_TUNE_ECC_ENABLE:自动调优 ECC 字节的 DLL 读偏移。

这些开关之所以能生效,是因为 BDK 的 DRAM 初始化代码内部通过BDK_CONFIG_DRAM_VERBOSE(DDR-VERBOSE,取值 0–255)等运行时配置项决定日志输出的详细程度,Kconfig 开关在构建期把这些 verbose 行为编译进对应阶段。

实战示例:cn8100_sff_evb 参考板的完整链路

仓库内实际使用 BDK 的主板为 src/mainboard/cavium/cn8100_sff_evb,对应BOARD_CAVIUM_CN8100_SFF_EVB(Kconfig 中select SOC_CAVIUM_CN81XX,Kconfig)。它在启动各阶段的 BDK 使用方式如下:

  1. bootblock(bootblock.c):完成串口控制台与 SPI flash(EM100 Pro 上验证)初始化,为后续阶段铺路;
  2. romstage(romstage.c):bdk_config_set_fdt(devtree)通告配置 →sdram_init()执行 BDK 的 DRAM 初始化 →soc_mmu_init()建页表,全程以watchdog_poke(0)喂狗防超时复位;
  3. ramstage(mainboard.c):mainboard_enable()再次通告配置,随后完成 TWSI/IO 扩展器、SFP+ 发射器、VSC7224 重定时器(FSYNC、DFE、EQ 等寄存器配置)、PHY 复位 GPIO 等板级初始化,最后打印 trusted boot、boot method、REF/IO/CORE 时钟、CPU 核数与内存容量等信息。

而承载全部 BDK 配置的devtree[](bdk_devicetree.c)中可以看到实际生效的配置形态,例如:

const struct bdk_devicetree_key_value devtree[] = { {"DDR-TEST-BOOT", "1"}, {"DDR-CONFIG-WODT-MASK.RANKS2.DIMMS2", "0xc0c0303"}, {"DDR-CONFIG-MODE1-RTT-WR.RANKS2.DIMMS1.RANK0", "0x2"}, {"DDR-CONFIG-MODE2-VREF-VALUE.RANKS2.DIMMS1.RANK0", "0x19"}, {"DDR-CONFIG-CUSTOM-MIN-RTT-NOM-IDX", "0x1"}, {"PHY-ADDRESS.N0.BGX0.P0", "0xff000010"}, {"BGX-ENABLE.N0.BGX0.P0", "1"}, {"BDK-NUM-PACKET-BUFFERS", "0x1000"}, {"BDK-PACKET-BUFFER-SIZE", "0x400"}, {"MULTI-NODE", "0"}, {"QLM-DIP-AUTO-CONFIG", "1"}, {"DDR-CONFIG-SPD-ADDR.DIMM0.LMC0", "0x1050"}, {"USB-PWR-GPIO.N0.PORT0", "12"}, {0, 0}, };

可以看到,DDR 的 RTT/ODT/VREF 等时序参数均按RANKS/DIMMS/RANK/LMC维度细分键控,PHY 地址与 BGX 使能按N/BGX/P维度描述,运行参数(包缓冲、多节点、QLM 自动配置)以全局键表达——这正是 BDK devicetree 以“可寻址字符串键 + 字符串值”承载复杂板级配置的典型形态,也是理解 BDK 配置体系的最佳入门素材。

总结

Cavium BDK 在 coreboot 中的集成遵循“vendorcode 托管 + 板级通告”的模式:BDK 提供 romstage 的 DRAM 初始化与 ramstage 的高速外设初始化能力,通过一套自有的字符串 key-value devicetree(结构见 bdk-devicetree.h、实现见 bdk-config.c)驱动配置,配置在 romstage 与 ramstage 中通过bdk_config_set_fdt()两次注入;DTB 到 C 数组的转换由 devicetree_convert.py 完成;调试时则在 menuconfig 的 Chipset → BDK 菜单下按阶段打开 verbose 输出(Kconfig 定义见 src/vendorcode/cavium/Kconfig)。对需要在新 Cavium OcteonTX 平台上做 bringup 的开发者而言,以cn8100_sff_evb为模板、按上述链路复用 BDK 是最直接的起步路径。

  • 固件
  • 嵌入式
  • 操作系统
  • 驱动开发

【免费下载链接】coreboot

Read-only mirror of https://review.coreboot.org/coreboot.git. Synced every hour. We don't handle Pull Requests.

项目地址:https://gitcode.com/gh_mirrors/co/coreboot
点击查看免费下载
上一篇:Decepticon RoE 机器强制执行:machine_enforcement 配置、双执行点防护与审计闭环
下一篇:SMUDebugTool终极指南:免费解锁Ryzen处理器性能潜力的完整教程

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询