超微服务器主板x11ssh-f的OpenBMC移植 (WIP) March 15, 2024 | 6 最小读取

超微服务器主板x11ssh-f的OpenBMC移植 (WIP)

移植 OpenBMC 到 x11ssh-f 的尝试

BMC 和 OpenBMC 简介

BMC 全称基板管理控制器(baseboard management controller),是一个嵌入某些计算机(通常是服务器)主板的特制微控制器,拥有自己的固件、内存和网络连接(通过自己的独立网卡或网络控制器旁路接口 NC-SI 共享宿主的网卡)。它是承载智能平台管理接口(Intelligent Platform Management Interface,IPMI)的硬件,通过一个扩展自 I²C 的基板管理控制总线/桥(Intelligent Platform Management Bus/Bridge,IPMB)与分布于各个不同系统模块中的卫星控制器相连,可以独立于操作系统监视这些系统模块的工作状态并进行管理,如开关机、感知组件温度并调整风扇转速,甚至可以作为远程控制台,获取屏幕显示并作为键盘鼠标与操作系统交互,甚至模拟外存储器以远程安装操作系统。

BMC 之所以能做到如此深度的管理,是因为 BMC 深度连接到宿主系统的总线之中。BMC 经常是取代了一般 x86 计算机系统的 SuperIO 芯片,通过 LPC、SMBUS 总线连接到宿主,并对宿主提供相应功能(如串口、风扇管理等)。为了实现远程控制台和外存储器模拟,BMC 还与宿主的 PCI(E) 总线相连并表现为显卡,作为从设备与宿主的 USB 总线相连以表现为输入设备和外存储器。

虽然大部分 BMC 的原厂固件使用了 Linux 内核,但一般用的是十分老旧的版本,且其用户态程序一般不是自由软件,因此私有的 BMC 固件正在被逐步视为安全隐患。为此,和 Linux 基金会合作的 OpenBMC 项目面世了,它是一个面向 BMC 的 GNU/Linux 发行版,提供了可以从源代码编译而出的自由 BMC 软件栈,它使用 Yocto 计划作为编译和发行版生成系统,可以生成能直接刷入 BMC 的 rom 芯片的固件镜像。在其内部,OpenBMC 使用 D-Bus 进行进程间通信,并提供一个 web 应用程序使用户能够与 BMC 软件栈交互。

alter-text

x11ssh-f 和 AST2400 简介

硬件规格见 https://www.supermicro.com/en/products/motherboard/X11SSH-F,其宿主系统的固件可以替换为 coreboot,详见 https://doc.coreboot.org/mainboard/supermicro/x11-lga1151-series/x11ssh-f/x11ssh-f.html

x11ssh-f 的 BMC 使用了 ASPEED AST2400,配备了 32MiB 的 SPI NOR 闪存、128MiB 的内存和独立网卡,取代了宿主的 SuperIO 并连接了宿主的 PCI-E 和 USB ,也作为宿主机的显卡。

ASPEED AST2400 是专门用作 BMC 的系统单芯片,集成了 armv5 处理器、两个千兆以太网卡的 MAC 部分、作为显卡的 PCI-E 从设备、USB 1 和 2 的从设备(HUB)各一、USB 2 主控、LPC 控制器、5 个 UART 串口、和 216 个 GPIO,详见 https://www.datasheetcafe.com/ast2400-datasheet-server-management-processor/

BMC 的原厂固件可在断电时用 SPI flash 编程器,如用 stm32 开发板刷 https://github.com/dword1511/stm32-vserprog 做成的编程器直接读取。用 binwalk 分析可知,它使用了老旧的 Linux 2.6.28 版内核,即便是从 https://www.supermicro.com/en/support/resources/downloadcenter/firmware/MBD-X11SSH-F/BMC 获取的最新版 BMC 固件依然如此。

移植过程

首先使用 https://github.com/mine260309/openbmc-intro/blob/master/Porting_Guide.md 中的方法为 x11ssh 建立描述该目标的配置文件。

OpenBMC 使用的 Linux 内核版本十分新,因此与使用 2.6.28 版内核的原厂固件不同,硬件信息需要用平坦设备树(Flattened Device Tree,FDT)格式描述,而非以 mach 文件的形式编译为内核的一部分。虽然 OpenBMC 已经支持了不少使用 ASPEED AST2400 的主板,但 Linux 内核对它们的支持均已被上游版本库接受,因此这些主板的设备树源(dts)文件已存在于 Linux 源代码的 arch/arm/boot/dts/aspeed/ 目录下,但我们现在要做的正是为 OpenBMC 添加对 x11ssh 的支持,因此 Linux 源代码并不包含 x11ssh 的 dts 文件。

所幸,笔者在另一个 BMC 项目 u-bmc 的一个下游分支中找到了该项目用于支持 x11ssh 的 dts 文件,故能以此为基础,参考其他已经支持的使用 ASPEED AST2400 的主板的 dts 编写适应 OpenBMC 的 dts 文件。

然而,该文件毕竟不存在于 Linux 内核的源码树中。按一般流程,应当把适配 x11ssh 的 dts 文件加入内核源码树并修改必要的 Makefile 以便在编译过程中生成相应的 FDT 文件,再让 OpenBMC 的编译系统使用这份修改过的内核。然而对 OpenBMC 的编译系统而言,Linux 内核是 OpenBMC 需要使用的第三方项目之一,这种情况下编译系统一般不允许直接使用带有改动的第三方项目,但往往支持在编译过程中自动对第三方项目打补丁。所以我们需要先将上述改动表示为对 Linux 内核的补丁——将这份 dts 文件加入本地的 Linux 内核版本库(如果没有就 clone 一个),并修改 Makefile,提交之后,再将这些修改作为 diff 文件导出(可使用 git show 或 git format-patch )并裁剪,放到 OpenBMC 版本库的 meta-aspeed/recipes-kernel/linux/files/0001-add-aspeed-bmc-supermicro-x11ssh-dts.patch ,并添加一个 meta-aspeed/recipes-kernel/linux/linux-aspeed_git.bbappend 文件作为 linux-aspeed_git.bb 的补充,指示编译系统在编译内核之前打上这个补丁

FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
SRC_URI += "file://0001-add-aspeed-bmc-supermicro-x11ssh-dts.patch"

为了调试,需要至少有一个串口用于控制台以输出日志并登录开发中的 OpenBMC 系统。在 OpenBMC 和 u-bmc 中均默认使用 uart5 作为控制台,但在 x11ssh 上 uart5 并未被引出为便于连接的形式。所幸 ASPEED AST2400 提供了一个寄存器用于重映射各个串口的顺序,可以利用该功能将 uart5 重映射到已引出的串口上。

https://github.com/osresearch/u-bmc/commit/8b7d1ae02a33bbfda7487b6a2162a3317a355f00 中包含了在 u-bmc 自身的 bootloader 中写入该寄存器以实现将 uart5 映射到 COM2 的代码,我们需要将这些代码移植到 OpenBMC 使用的 u-boot 上,并同样表示为补丁的形式,放在 meta-aspeed/recipes-bsp/u-boot/files/0002-u-boot-console-com1.patch ,并增加 meta-aspeed/recipes-bsp/u-boot/u-boot-aspeed_2016.07.bbappend 以便在编译过程中自动打上:

+FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
+SRC_URI += "file://0002-u-boot-console-com1.patch"

部分用于电源管理的 GPIO 引脚定义则可在 https://github.com/osresearch/u-bmc/blob/kf/x11/platform/supermicro-x11ssh-f/pkg/gpio/platform.go 中找到,需要改写成 OpenBMC 需要的形式,放到 meta-supermicro/meta-x11ssh/recipes-phosphor/skeleton/obmc-libobmc-intf/gpio_defs.json

至此,已可在 OpenBMC 版本库根目录下运行 source setup x11ssh 再运行 bitbake obmc-phosphor-image 来编译 OpenBMC 的镜像。如部分第三方组件的源码不方便直接下载,可在运行第二条命令时利用 ${https_proxy}${HTTPS_PROXY} 设置 http 代理服务器,最好两个环境变量都要设置,如 https_proxy=http://192.168.3.3:8080 HTTPS_PROXY=$https_proxy bitbake obmc-phosphor-image。镜像会生成于 build/x11ssh/tmp/deploy/images/x11ssh/,其中的 obmc-phosphor-image-x11ssh.static.mtd 即可刷写到 x11ssh-f 用于存储 OpenBMC 固件的 SOIC-16 封装的 32MiB SPI NOR flash 芯片中,夹子接法见 https://trmm.net/SPI_flash/ 。开始调试前,务必先备份原厂固件。

刷入后开机,从 COM2 的确可以收到日志:

alter-text

但日志却显示 OpenBMC 启动后不久便停止运行。经调查发现是已知问题 https://github.com/openbmc/openbmc/issues/3969,两个互相冲突的服务占用同一 D-bus 接口所致,需要禁用其中之一。故在目标配置文件 meta-supermicro/meta-x11ssh/conf/machine/x11ssh.conf 中加入

VIRTUAL-RUNTIME_obmc-host-state-manager = "x86-power-control"
VIRTUAL-RUNTIME_obmc-chassis-state-manager = "x86-power-control"
VIRTUAL-RUNTIME_obmc-discover-system-state = "x86-power-control"

以解除冲突。

重新编译镜像并刷入后,即可通过 COM2 以用户名 root,密码 0penBmc (注意密码第一个字符是阿拉伯数字零)登录。

当前进展与展望

至此,移植到 x11ssh-f 上的 OpenBMC 已可启动,并通过串口与之交互,但目前很多重要守护进程,如 systemd-journaldsystemd-udevd 均会因为段错误被杀死,

[   40.519097] systemd[1]: systemd-journald.service: Main process exited, code=killed, status=11/SEGV
[   40.549488] systemd[1]: systemd-journald.service: Failed with result 'signal'.
...
[   44.773066] systemd[1]: systemd-udevd.service: Main process exited, code=killed, status=11/SEGV
[   44.790901] systemd[1]: systemd-udevd.service: Failed with result 'signal'.

而网卡也因 systemd-udevd 被杀死而未被初始化而使得 web 界面无法访问,虽然被内核正常识别但尚不能从闪存中读取并设置正确的 MAC 地址,而只有随机的临时 MAC 地址。

今后的工作主要包含两方面:一是从原厂固件和 supermicro 提供的 2.6.28 版内核源码,尤其是其 mach 文件中提取完整的 GPIO 引脚定义。另一方面则是和 OpenBMC 上游一同解决重要守护进程崩溃的问题,最终得到一个可用的 BMC 固件实现。