【提问】CPLD固件生效冲突解决逻辑的条件是否存在设计缺陷?

【提问】CPLD固件生效冲突解决逻辑的条件 self.objs[fw_conflict_t[ps.FirmwareId]] ~= nil 是否存在设计缺陷?

背景

在分析一个CPLD升级未生效的问题时,发现 firmware_mgmt 组件 active_info.lua 的 check_reg_param_valid 函数中,CPLD ActiveMode 冲突解决逻辑似乎从未被触发。想请教社区这个判断条件的设计意图,以及是否存在缺陷。

问题场景

当同一BMC管理多个CPLD,且各CPLD的生效动作不同时,如:

  1. CLU CPLD(风扇板):active_mode = ResetAC(需要AC下电循环生效)
  2. 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 日志。

想请教的问题

  1. 条件③的设计意图:self.objs[fw_conflict_t[ps.FirmwareId]] ~= nil 这个条件是为了解决什么场景?是否预期存在某种代码路径会同时注册 CPLD 和 CPLD_ResetAC 两个条目?

  2. 历史背景:fw_conflict_t 这个双向映射从初始开源版本(63cac5c,2026-09-09)就存在。当时 general_hardware 全部用 CPLD_ResetAC 注册,self.objs['CPLD'] 永远为nil,冲突逻辑同样不会触发。这个逻辑是否从引入时就是死代码?还是说早期有一个同时使用两个FirmwareId的版本?

  3. 是否为已知缺陷:这个冲突解决逻辑失效的问题是否已经被识别?如果条件③的本意就是"同FirmwareId已存在即触发优先级比较",那么直接移除条件③(只保留①②④)是否是正确的修复方向?

  4. 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特性”)

是否预期存在某种代码路径会同时注册 CPLD 和 CPLD_ResetAC 两个条目
这里解决的一个场景是 用老版本bmc升级了CPLD 但没生效 再去升级新版本的bmc,会存在兼容性问题

那是不是应该用or呢,存在老板本或新版注册的CLPD固件任意一个,就应该进入这个逻辑,比较哪个生效方式优先级更高

看这个代码感觉也不会有兼容性问题

function active_powercycle:get_final_active_mode()
    local active_mode_tbl = {}
    active_mode_tbl.active_mode = common.active_mode.Reset_NONE
    local fw_active_objs = active_info.get_instance():get_fw_active_info()
    for _, fw_active_obj in pairs(fw_active_objs) do
        if fw_active_obj.ActiveCondition ~= POWER_CYCLE and fw_active_obj.ActiveCondition ~= POWER_OFF then
            goto continue
        end
        active_comm.get_final_active_mode(fw_active_obj.ActiveMode, active_mode_tbl)  -- 传入ResetBMC
        ::continue::
    end
    return active_mode_tbl.active_mode 
end

CPLD 和 CPLD_ResetAC分属不同的fw_active_objs,在这里找最终的active mode的时候会找到优先级最高的active mode才对,如果有理解的不对的地方,望指正