栏目介绍:“玩转OurBMC” 是OurBMC社区开创的知识分享类栏目,主要聚焦于社区和BMC全栈技术相关基础知识的分享,全方位涵盖了从理论原理到实践操作的知识传递。OurBMC社区将通过 “玩转OurBMC” 栏目,帮助开发者们深入了解到社区文化、理念及特色,增进开发者对BMC全栈技术的理解。
欢迎各位关注 “玩转OurBMC” 栏目,共同探索OurBMC社区的精彩世界。同时,我们诚挚地邀请各位开发者向 “玩转OurBMC” 栏目投稿,共同学习进步,将栏目打造成为汇聚智慧、激发创意的知识园地。
在上期内容中,我们深入剖析了OpenBMC完成固件更新的底层机制:无论是BMC自身的单分区或A/B分区更新,还是通过接管SPI、JTAG总线对BIOS、CPLD进行的烧录,其本质都是直接执行底层的更新命令。然而,在生产环境中,管理员并不会手动执行这些底层命令。取而代之的,是通过Web界面或Redfish接口发起的远程升级流程。
本期我们将聚焦于phosphor-bmc-code-mgmt 软件栈,系统性解析从用户发起更新操作到固件最终写入芯片的完整软件协作流程,展示 OpenBMC 如何通过分层、事件驱动的架构,将高风险的固件更新流程封装为安全、可控、可审计的标准化服务。
01核心架构:分层与事件驱动的设计
OpenBMC的固件更新系统采用基于D-Bus通信的松耦合分层架构,其设计可明确划分为以下四个层级:
- 协议与策略层 (bmcweb):负责实现 Redfish 标准接口,将 HTTP 请求转换为 D-Bus 操作,并决定更新的执行策略(如“立即激活”)。
- 管理层(phosphor-software-manager,内部核心协调组件:ItemUpdater):作为核心守护进程,负责软件对象的生命周期管理、全局状态维护以及系统级策略的执行。
- 业务逻辑层 (Activation):作为自主状态机,封装了从校验到写入的完整业务流程。执行层 (Systemd Services):服务中调用脚本,脚本中封装与具体固件类型相关的更新命令,是软件与硬件交互的最终边界。
一次典型的更新流程,由一系列事件驱动的模块交互构成。各模块通过发布与订阅D-Bus信号、设置与监听属性变化来协同工作,形成一个松耦合但衔接紧密的自动化工作流。下图以 OpenBMC 默认的“上传后立即激活”策略为例,重点展示控制流与事件触发关系,而非所有异常分支。

流程关键点解析如下:
- 自动激活策略:步骤5和6是默认行为的关键。bmcweb 在监听到新 Activation 对象创建的信号后,其 softwareInterfaceAdded 回调函数会自动调用 activateImage() 来触发激活。该策略通过事件驱动机制,将用户的单次上传操作自动衔接至激活流程,实现”上传-激活”的无缝衔接。
- 架构的灵活性:上述“自动激活”策略并非强制。产品可以通过修改 bmcweb 的回调逻辑,将其变为“手动激活”,即在界面上提供独立的激活按钮。这验证了架构的松耦合特性——只要最终通过标准 D-Bus 接口设置 Activation 的属性,就能驱动整个流程。
- 状态机的自主性:从步骤7开始,Activation 对象进入完全自主的状态流转,它根据需要调用 ItemUpdater 提供的策略工具,并最终驱动 Systemd 服务,是执行业务流程的核心实体。
02模块深度解析:各司其职的精密协作
bmcweb:Redfish协议实现与更新请求的转换层
作为 Redfish 协议的服务端实现,bmcweb 是远程更新流程的入口。它负责接收标准化的HTTP(S)请求,并将其翻译为对底层 D-Bus 服务的调用。
它提供两种主要的镜像上传接口:
- 简单上传:接收二进制镜像文件(如tar.gz)。
- 多功能上传:支持在请求中嵌入结构化参数(如目标固件类型 Targets、更新生效时间 ApplyTime)。
其核心策略逻辑体现在 softwareInterfaceAdded 函数中。该函数通过 D-Bus 信号监听新 Activation 对象的创建,一旦发现,便根据产品预设的策略决定是否立即激活。这正是 “上传后是否自动激活”这一产品行为的策略执行点,充分体现了 bmcweb 作为协议层与产品策略执行层的角色。
在OurBMC社区中,采用的是HTTP Push,但引入了BMC更新生效时间 ApplyTime参数,使得管理员在网页更新BMC固件时,可以选择是否勾选该参数,从而在全部流程以后走完后自动重启或者下次手动重启。
ImageManager :镜像入库管理
ImageManager 负责将原始固件包转化为系统可管理的对象。它本身不主动扫描,而是由内置的 Watch 模块通过 Linux inotify 监听上传目录(/tmp/images)。当文件完全写入后,Watch 触发 ImageManager::processImage(),依次执行解包、解析 MANIFEST 文件(获取固件用途 purpose、版本 version 等)、机型校验,最终在 D-Bus 上创建一个状态为 Ready 的 Version 对象,并发出 InterfacesAdded 信号,完成“入库”。
ItemUpdater:全局状态管理与策略执行
ItemUpdater 是更新系统的核心管理组件,但它不直接驱动更新流程。它的核心职责包括:
- 对象生命周期管理:监听 ImageManager 的信号,为每个新 Version 创建并关联对应的 Activation 对象,维护全局的对象映射表。
- 维护系统状态关联:通过 D-Bus Association 机制,管理 functional(当前运行的版本)和 active(下次启动的版本)等关键关系。BMC管理界面基于此来查询运行中固件和备用固件的状态。
- 执行系统级策略:它提供的 freeSpace()(清理空间)、savePriority()(保存启动优先级)等方法,并非更新流程的发起者,而是被 Activation 状态机在运行过程中回调使用的“策略工具”。
ImageManager 的职责在 Version 对象创建完成后即告结束,它不参与任何激活或刷写逻辑。
Activation:自主运行的状态机
每个 Activation 对象都是一个自包含的有限状态机(Ready -> Activating -> Active/Failed)。它是更新流程的真正执行核心,其设计精髓在于自主性:
- 由属性触发:当 bmcweb 或其他授权服务设置 RequestedActivation 属性后,Activation 状态机开始按既定逻辑流转。
- 自主决策与协调:在 Activating 状态中,它自主进行安全校验(签名验证、最小版本限制 MSL),并根据自身的 purpose 属性,决定调用哪个底层 systemd 刷写服务。在此过程中,它会根据需要调用 ItemUpdater 的策略工具。
- 自主完成:监听 systemd 服务的回调,并自主更新最终状态,再通知 ItemUpdater 刷新全局关联。
至此,Activation 的职责边界结束,后续执行完全由 systemd 服务及其脚本接管。
Systemd 服务:硬件操作的最终执行层
这是与上篇硬件操作对接的最后一环。Activation 通过封装好的 D-Bus 接口触发对应的 systemd 服务(如 obmc-flash-bios@.service)。该过程并非直接执行底层刷写命令,而是由 systemd 单元负责启动脚本,脚本中再封装与具体固件类型相关的更新命令,从而实现上层状态机与具体刷写实现细节之间的清晰隔离。
03总结
通过对完整流程的剖析,我们可以看到 OpenBMC 固件更新架构呈现出的清晰层次:

这种架构的优势在于高度的模块化与解耦,任意一层只要遵循约定接口,便可独立替换或升级。例如,改变 bmcweb 的信号处理逻辑即可将“自动激活”改为“手动确认”;增加新的 systemd 服务便能支持新的固件类型,而整个核心状态机和管理框架无需改动。
最终,这一套从用户界面到固件刷写命令的协同机制,将复杂且高风险的固件更新操作,转化为一个安全、可观测、可审计的标准化服务。正是这种模块化、事件驱动的架构设计,使 OpenBMC 能够在保证系统安全性的前提下,将固件更新纳入大规模数据中心的自动化运维体系之中。
</div>