【提问】CPLD固件生效冲突解决逻辑的条件 self.objs[fw_conflict_t[ps.FirmwareId]] ~= nil 是否存在设计缺陷?
背景
在分析一个CPLD升级未生效的问题时,发现 firmware_mgmt 组件 active_info.lua 的 check_reg_param_valid 函数中,CPLD ActiveMode 冲突解决逻辑似乎从未被触发。想请教社区这个判断条件的设计意图,以及是否存在缺陷。
问题场景
当同一BMC管理多个CPLD,且各CPLD的生效动作不同时,如:
- CLU CPLD(风扇板):active_mode = ResetAC(需要AC下电循环生效)
- IEU CPLD(管理板):active_mode = ResetBMC(只需BMC复位生效)
两个CPLD都用 FirmwareId='CPLD' 注册到同一BMC。由于冲突解决逻辑未触发,IEU后注册时直接覆盖了CLU的 ActiveMode:
04:13:33 CLU注册 → t_fw_active_objs: {CPLD: {ActiveMode=ResetAC}}
04:15:59 IEU注册 → t_fw_active_objs: {CPLD: {ActiveMode=ResetBMC}} ← 覆盖
下电生效时,最终生效动作被判定为 ResetBMC(仅BMC复位),而CLU CPLD需要的AC下电循环未被执行,导致风扇板CPLD升级成功但未生效。
问题代码
文件:firmware_mgmt/src/lualib/active/active_info.lua,函数 check_reg_param_valid:
local fw_conflict_t = {
CPLD = 'CPLD_ResetAC',
CPLD_ResetAC = 'CPLD',
}
if
self.objs[ps.FirmwareId] ~= nil -- ① 同FirmwareId已存在
and ps['FirmwareType'] ~= common.firmware_type.BMC -- ② 非BMC固件
and self.objs[fw_conflict_t[ps.FirmwareId]] ~= nil -- ③ ★存疑条件★
and ps['FirmwareType'] ~= common.firmware_type.SR -- ④ 非SR固件
then
-- ResetAC > ResetBMC > None 优先级比较
local priority_map = { ['ResetAC'] = 3, ['ResetBMC'] = 2, ['None'] = 1 }
local current_priority = priority_map[ps.ActiveMode] or 0
local existing_priority = priority_map[self.objs[ps.FirmwareId].ActiveMode] or 0
if current_priority > existing_priority then
log:notice('Use higher priority ActiveMode: %s (current)', ps.ActiveMode)
else
ps.ActiveMode = self.objs[ps.FirmwareId].ActiveMode -- 保留高优先级
end
log:notice('Already exists the same id:[%s]', ps.FirmwareId)
end
疑点
条件③要求 self.objs[fw_conflict_t[ps.FirmwareId]] 不为nil。fw_conflict_t 是一个双向映射:CPLD <-> CPLD_ResetAC。
也就是说,当注册 FirmwareId='CPLD' 时,条件③要求 self.objs['CPLD_ResetAC'] 已存在;当注册 FirmwareId='CPLD_ResetAC' 时,要求 self.objs['CPLD' 已存在。只有当这两个ID的条目同时存在时,优先级比较才会触发。
但从当前代码来看:
general_hardware 侧的注册行为
general_hardware/src/lualib/unit_manager/class/logic_fw/signal.lua 中,所有CPLD类型(Cpld / BP_Cpld / EXUCpld / BCUCpld / CLUCpld / SEUCpld / IEUCpld / DPUCpld)在注册生效动作时统一使用同一个FirmwareId:
-- signal.lua 第97行(9bb4a09 提交后)
param[#param+1] = {Key = 'FirmwareId', Value = 'CPLD'}
在此之前的旧代码中,则是统一使用 'CPLD_ResetAC':
-- 旧代码(9bb4a09 提交前)
register_fw_active_info('CPLD_ResetAC', signal.db, 'Idle')
无论旧代码还是新代码,都只使用单一FirmwareId,不会同时创建 CPLD 和 CPLD_ResetAC 两个条目。
推论
由于 CPLD 和 CPLD_ResetAC 永远不会同时出现在 self.objs 中,条件③永远为 false,整个冲突解决逻辑(ResetAC > ResetBMC 优先级比较)从未被触发过。
我在实际日志中也验证了这一点:整个CPLD升级和注册过程中,从未出现 Already exists the same id 或 Use higher priority ActiveMode 日志。
想请教的问题
-
条件③的设计意图:
self.objs[fw_conflict_t[ps.FirmwareId]] ~= nil这个条件是为了解决什么场景?是否预期存在某种代码路径会同时注册CPLD和CPLD_ResetAC两个条目? -
历史背景:
fw_conflict_t这个双向映射从初始开源版本(63cac5c,2026-09-09)就存在。当时 general_hardware 全部用CPLD_ResetAC注册,self.objs['CPLD']永远为nil,冲突逻辑同样不会触发。这个逻辑是否从引入时就是死代码?还是说早期有一个同时使用两个FirmwareId的版本? -
是否为已知缺陷:这个冲突解决逻辑失效的问题是否已经被识别?如果条件③的本意就是"同FirmwareId已存在即触发优先级比较",那么直接移除条件③(只保留①②④)是否是正确的修复方向?
-
9bb4a09 提交的影响:
general_hardware的 9bb4a09(“支持BMC平滑重启生效CPLD特性”,2025-11-22)将FirmwareId从CPLD_ResetAC改为CPLD。这个改动是否考虑到了firmware_mgmt侧fw_conflict_t的依赖关系?
我的理解
优先级比较逻辑本身(ResetAC > ResetBMC > None)是合理的——AC下电循环是BMC复位的超集,执行AC可以同时满足两种CPLD的生效需求。问题出在触发条件③上,它阻断了这个逻辑的执行。
想确认我的理解是否正确,以及社区对这个问题的修复方向有什么建议。
环境
- 硬件平台:Kunpeng950
- firmware_mgmt 初始开源版本:63cac5c(2026-09-09)
- general_hardware 相关提交:9bb4a09(2025-11-22,“支持BMC平滑重启生效CPLD特性”)