-- Copyright (c) 2025 Huawei Technologies Co., Ltd.
-- openUBMC is licensed under Mulan PSL v2.
-- You can use this software according to the terms and conditions of the Mulan PSL v2.
-- You may obtain a copy of Mulan PSL v2 at: http://license.coscl.org.cn/MulanPSL2
-- THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
-- EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
-- MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
-- See the Mulan PSL v2 for more details.

-- Description: PMBUS独立vrd升级

local log = require 'mc.logging'
local utils = require 'mc.utils'
local context = require 'mc.context'
local utils_core = require 'utils.core'
local vos = require 'utils.vos'
local fw_mgmt = require 'general_hardware.client'
local cmn = require 'common'
local parser_cfg = require 'mcu.upgrade.parser_cfg'
local ini_parser = require 'mc.v2_persistence'
local prog_stats = require 'progress_statistics'
local fructl = require 'mcu.upgrade.fructl_handler'
local defs = require 'independent_vrd.ind_vrd_defs'

local LOCK_FOREVER = 0xffff

local pmbus_vrd_upgrade = {}
pmbus_vrd_upgrade.__index = pmbus_vrd_upgrade

-- vrd_manager_collection: key为position, value为ind_vrd_manager对象
function pmbus_vrd_upgrade.new(bus, db, vrd_manager_collection)
    return setmetatable({
        bus = bus,
        db = db,
        is_activing = false,
        is_upgrading = false,
        vrd_manager_collection = vrd_manager_collection, -- VRD管理器集合
        cfg_path = '',
        hpm_path = '',
        before_upgrade_version = '',
        upgrade_vrd_manager = nil, -- 待升级的VRD管理器对象
        prog_stats_i = nil,        -- 进度统计对象
        power_state = '',          -- 电源状态
        poweron_locked = false,    -- 上电锁状态
        vrd_cached = false,        -- VRD缓存状态
        system_id = nil            -- 当前升级的system_id
    }, pmbus_vrd_upgrade)
end

-- 根据UID查找VRD管理器对象
local function find_vrd_manager_by_uid(vrd_manager_collection, uid)
    for _, manager in pairs(vrd_manager_collection) do
        if manager.UID == uid then
            return manager
        end
    end
    return nil
end

-- 更新电源状态
local function update_power_state(self, system_id)
    self.power_state = fructl.get_power_status(self.bus, system_id)
    log:debug('[PMBus_Vrd] System %d power state: %s', system_id, self.power_state)
end

-- VRD升级对下电的Host增加上电锁
local function vrd_upgrade_poweron_lock(self, system_id)
    -- VRD下电升级且还未加上电锁，需加上电锁
    if self.power_state == 'OFF' and not self.poweron_locked then
        log:notice('[PMBus_Vrd] Adding poweron lock for system %d', system_id)
        -- 上电锁两小时
        fructl.set_poweron_lock_until_success(self.bus, system_id, true, LOCK_FOREVER, 'Vrd')
        self.poweron_locked = true

        -- 加锁后再次检查电源状态
        local current_power_state = fructl.get_power_status(self.bus, system_id)
        if current_power_state ~= 'OFF' then
            -- 如果加了上电锁之后环境处于上电状态，则解锁；此次升级不写flash，改为缓存
            log:notice('[PMBus_Vrd] System %d powered on after lock, unlocking', system_id)
            fructl.set_poweron_lock_until_success(self.bus, system_id, false, LOCK_FOREVER, 'Vrd')
            self.poweron_locked = false
            self.power_state = current_power_state
        end
    end
end

-- 解除上电锁
local function poweron_unlock(self, system_id)
    if self.poweron_locked then
        log:notice('[PMBus_Vrd] Removing poweron lock for system %d', system_id)
        fructl.set_poweron_lock_until_success(self.bus, system_id, false, LOCK_FOREVER, 'Vrd')
        self.poweron_locked = false
    end
end

-- 缓存升级文件
local function cache_upgrade_file(hpm_path, system_id)
    if not hpm_path or not vos.get_file_accessible(hpm_path) then
        log:error('[PMBus_Vrd] cache_upgrade_file: hpm path is not accessible')
        return defs.RET.ERR
    end

    -- 创建缓存目录
    local cache_dir = defs.FW_VALID_FILE_DIR[defs.FIRMWARE_TYPE.UPGRADE]
    if not vos.get_file_accessible(cache_dir) then
        os.execute('mkdir -p ' .. cache_dir)
    end

    -- 目标文件名格式: HOST_<sys_id>_Independent_Vrd_PMBus.hpm
    local target_path = string.format('%sHOST_%s_%s.hpm', cache_dir, system_id, defs.FIRMWARE_TYPE.PMBUS_UPGRADE)
    local ok, err = pcall(utils.copy_file, hpm_path, target_path)
    if not ok then
        log:error('[PMBus_Vrd] Failed to cache system %d hpm file, err: %s', system_id, err)
        return defs.RET.ERR
    end

    log:notice('[PMBus_Vrd] Cached system %d hpm file successfully', system_id)
    return defs.RET.OK
end

-- 缓存VRD升级包（上电状态）
local function cache_vrd_if_needed(self, system_id)
    -- 如果是上电状态且还没缓存过，则缓存升级包
    if self.power_state ~= 'OFF' and not self.vrd_cached then
        log:notice('[PMBus_Vrd] System %d is powered on, caching upgrade file', system_id)
        cache_upgrade_file(self.hpm_path, system_id)
        self.vrd_cached = true
        return true
    end
    return false
end

-- 清理升级资源
local function clear_vrd_upgrade_resource(self)
    poweron_unlock(self, self.system_id)
    self.power_state = ''
    self.poweron_locked = false
    self.vrd_cached = false
end

-- 更新生效状态
local function update_active_status(firmware_id, firmware_type, status)
    log:notice('[PMBus_Vrd] Update active status: %s', status)
    local param = {}
    param[#param + 1] = { Key = 'FirmwareId', Value = firmware_id }
    param[#param + 1] = { Key = 'FirmwareType', Value = firmware_type }
    param[#param + 1] = { Key = 'ActiveStatus', Value = status }
    fw_mgmt:FirmwareActiveFirmwareActiveUpdateActiveStatus(context.new(), param)
end

-- 填充生效注册列表
local function fill_register_active_list()
    return {
        { Key = 'FirmwareId',      Value = defs.FIRMWARE_TYPE.ACTIVE },
        { Key = 'FirmwareType',    Value = defs.FIRMWARE_TYPE.ACTIVE },
        { Key = 'ActiveCondition', Value = 'PowerOff' },
        { Key = 'ActiveMode',      Value = 'None' },
        { Key = 'ActiveStatus',    Value = 'Idle' }
    }
end

-- 注册VRD生效任务
local function register_vrd_active_action()
    -- 判断是否存在VRD生效缓存文件
    local cache_dir = defs.FW_VALID_FILE_DIR[defs.FIRMWARE_TYPE.UPGRADE]
    if not vos.get_file_accessible(cache_dir) or not next(utils_core.dir(cache_dir)) then
        log:notice('[PMBus_Vrd] No cached vrd hpm found, dont register vrd active')
        return
    end

    local active_register_list = fill_register_active_list()
    fw_mgmt:FirmwareActiveFirmwareActiveRegisterActiveAction(context.new(), active_register_list)
    log:notice('[PMBus_Vrd] Register active action successfully, ActiveCondition = %s', 'PowerOff')
end

-- 保存升级cfg信息到数据库
local function save_db_cfg(self)
    if not self.cfg_path or self.cfg_path == '' then
        log:notice('[PMBus_Vrd] No cfg path recorded, skip saving cfg to DB')
        return
    end

    local _, cfgs = parser_cfg.get_cfgs(self.cfg_path)
    if not cfgs or not next(cfgs) then
        log:notice('[PMBus_Vrd] No cfg entries found, skip saving cfg to DB')
        return
    end

    local convert = defs.CONVERT_COMPONENT[defs.FIRMWARE_TYPE.UPGRADE]

    for _, cfg in pairs(cfgs) do
        if cfg and cfg.uid_list and next(cfg.uid_list) and convert and
            cfg.component_id == convert.id and cfg.component_idex == convert.idex then
            parser_cfg.save_cfg(self, cfg)
        end
    end

    log:notice('[PMBus_Vrd] Saved cfg info to DB')
end

-- 获取缓存目录中的Firmware文件列表
local function get_firmware_name(db, valid_path)
    local name_list = utils_core.dir(valid_path)
    local cfg_table = db.FwUpdateCfgTable
    for _, name in ipairs(name_list) do
        local records = db:select(cfg_table):where(cfg_table.Id:eq(name),
            cfg_table.ComponentId:eq(defs.CONVERT_COMPONENT[defs.FIRMWARE_TYPE.UPGRADE].id),
            cfg_table.ComponentIdex:eq(defs.CONVERT_COMPONENT[defs.FIRMWARE_TYPE.UPGRADE].idex)):all()
        if #records ~= 0 then
            return name
        end
    end
    return nil
end

-- 解析配置文件获取UID
local function parse_config_file(cfg_path)
    local data = ini_parser.load_file(cfg_path)
    if not data or not data.Firmware1 or not data.Firmware1.Uid then
        log:error('[PMBus_Vrd] Parse config file failed, path:%s', cfg_path)
        return nil
    end
    return data.Firmware1.Uid
end

-- 查找并设置待升级的VRD管理器
local function find_and_set_upgrade_manager(self, uid)
    self.upgrade_vrd_manager = find_vrd_manager_by_uid(self.vrd_manager_collection, uid)
    if not self.upgrade_vrd_manager then
        log:error('[PMBus_Vrd] Cannot find VRD manager with UID:%s', uid)
        return false
    end
    log:notice('[PMBus_Vrd] Found VRD manager to upgrade with UID:%s', uid)
    return true
end

-- 保存升级上下文信息
local function save_upgrade_context(self, cfg_path, hpm_path, system_id)
    self.cfg_path = cfg_path
    self.hpm_path = hpm_path
    self.system_id = system_id
    self.before_upgrade_version = self.upgrade_vrd_manager:get_all_version()
    log:notice('[PMBus_Vrd] Before upgrade version: %s', self.before_upgrade_version)
end

-- 升级准备阶段
local function pmbus_vrd_upgrade_prepare(self, system_id, firmware_type, cfg_path, hpm_path, parameters)
    log:notice('[PMBus_Vrd] Prepare upgrade start, firmware_type:%s, system_id:%s', firmware_type, system_id)

    -- 解析配置文件获取UID
    local uid = parse_config_file(cfg_path)
    if not uid then
        return defs.RET.ERR, ''
    end

    -- 查找并设置待升级的VRD管理器
    if not find_and_set_upgrade_manager(self, uid) then
        return defs.RET.ERR, ''
    end

    if parameters.ForceUpdate and parameters.ForceUpdate == 'false' and parameters.Version == self.upgrade_vrd_manager:get_all_version() then
        -- 如果入参有ForceUpdate参数为false，且版本号和待升级的固件版本号一致，则不执行升级动作，直接判断下一个固件
        log:warn('fw uid %s version is already %s', self.upgrade_vrd_manager.UID, self.upgrade_vrd_manager:get_all_version())
        return defs.RET.SAME_VERSION, self.upgrade_vrd_manager:get_all_version()
    end

    -- 保存升级上下文信息
    save_upgrade_context(self, cfg_path, hpm_path, system_id)

    -- 更新电源状态并加上电锁
    update_power_state(self, system_id)
    vrd_upgrade_poweron_lock(self, system_id)

    log:notice('[PMBus_Vrd] Prepare upgrade finish')
    return defs.RET.OK, self.before_upgrade_version
end

-- 解析并解压固件包
local function parse_and_unzip_firmware(file_path, system_id, firmware_type, parameters)
    log:notice('[PMBus_Vrd] Parsing and unzipping firmware')

    -- 解析出升级目录和文件名
    local dir, firmware_name = parser_cfg.parse_dir(file_path)

    -- 更新升级进度 - 解压开始(20%)
    fw_mgmt:UpdateServiceUpdateServiceUpdateUpgradeStatus(context.new(), system_id, firmware_type, 0, 20, 'Running',
        parameters)

    -- 解压固件，最大解压限制100M
    utils.secure_tar_unzip(file_path, dir, 0x6400000, 1024)

    log:notice('[PMBus_Vrd] Firmware unzipped to: %s', dir)
    return dir, firmware_name
end

-- 创建进度更新回调函数
local function create_progress_callback(self, system_id, firmware_type, chip_count, parameters)
    -- ind_vrd_manager内部会为每个芯片分配进度范围并回调这个函数
    -- chip_index: 当前芯片索引（1-based）
    -- chip_percentage: 当前芯片的进度（0-100）
    return function(chip_index, chip_percentage)
        -- 更新对应芯片的进度
        self.prog_stats_i:set_sub_task_progress(chip_index, chip_percentage)

        -- 立即上报进度到上层
        local current_progress = self.prog_stats_i:get_current_progress()
        fw_mgmt:UpdateServiceUpdateServiceUpdateUpgradeStatus(context.new(), system_id, firmware_type, 0,
            current_progress, 'Running', parameters)
    end
end

-- 执行VRD升级并更新版本
local function execute_vrd_upgrade(self, dir, system_id, firmware_type, update_progress_func, parameters)
    log:notice('[PMBus_Vrd] Executing VRD manager upgrade')

    -- 调用VRD管理器的upgrade方法
    local ret_code = self.upgrade_vrd_manager:vrd_upgrade(dir, update_progress_func)
    -- 更新固件版本
    self.upgrade_vrd_manager:update_firmware_version(self.bus)
    -- 更新升级进度
    if ret_code == defs.RET.OK then
        log:notice('[PMBus_Vrd] VRD manager upgrade successfully')
        -- 上报90%进度
        fw_mgmt:UpdateServiceUpdateServiceUpdateUpgradeStatus(context.new(), system_id, firmware_type,
            ret_code, 90, 'Running', parameters)
    else
        log:error('[PMBus_Vrd] VRD manager upgrade failed')
    end

    return ret_code
end

-- 升级处理阶段
local function pmbus_vrd_upgrade_process(self, system_id, firmware_type, file_path, parameters)
    log:notice('[PMBus_Vrd] Process upgrade start')

    -- 检查是否有待升级的VRD管理器
    if not self.upgrade_vrd_manager then
        log:error('[PMBus_Vrd] No VRD manager to upgrade')
        return defs.RET.ERR
    end

    log:notice('[PMBus_Vrd] Upgrading VRD manager, UID:%s', self.upgrade_vrd_manager.UID)

    -- 针对prepare阶段和process阶段上下电状态不一致的场景，避免写入固件时未加上电锁
    update_power_state(self, system_id)
    vrd_upgrade_poweron_lock(self, system_id)

    -- 获取VRD管理器内芯片数量
    local chip_count = self.upgrade_vrd_manager:get_chip_count()
    if chip_count == 0 then
        log:error('[PMBus_Vrd] VRD manager has no chips')
        return defs.RET.ERR
    end

    -- 初始化进度统计
    self.prog_stats_i = prog_stats.new(20, 85, chip_count)

    -- 解析并解压固件
    local dir, _ = parse_and_unzip_firmware(file_path, system_id, firmware_type, parameters)

    -- 检查是否需要缓存升级包（上电状态）
    if cache_vrd_if_needed(self, system_id) then
        log:notice('[PMBus_Vrd] System %d is powered on, upgrade file cached, will activate on power off',
            system_id)
        -- 上电状态，已缓存，不执行实际升级
        return defs.RET.OK
    end

    -- 创建进度更新回调函数
    local update_progress_func = create_progress_callback(self, system_id, firmware_type, chip_count, parameters)

    -- 执行VRD升级并更新版本
    return execute_vrd_upgrade(self, dir, system_id, firmware_type, update_progress_func, parameters)
end

-- 升级完成阶段
local function pmbus_vrd_upgrade_finish(self)
    log:notice('[PMBus_Vrd] Upgrade finish start')
    -- VRD注册生效策略
    local ok, err = pcall(function()
        register_vrd_active_action()
    end)
    if not ok then
        log:error('[PMBus_Vrd] Try to register active action failed, err: %s', err)
    end

    -- 保存cfg信息到数据库
    ok, err = pcall(function()
        save_db_cfg(self)
    end)
    if not ok then
        log:error('[PMBus_Vrd] Save cfg to DB failed, err: %s', err)
    end

    -- 清理升级资源（解除上电锁等）
    clear_vrd_upgrade_resource(self)

    -- 清理升级信息
    self.cfg_path = ''
    self.hpm_path = ''
    self.before_upgrade_version = ''
    self.upgrade_vrd_manager = nil
    self.prog_stats_i = nil
    self.system_id = nil
    self.is_upgrading = false

    log:notice('[PMBus_Vrd] Upgrade finish complete')
    return defs.RET.OK
end

function pmbus_vrd_upgrade:on_upgrade_prepare(_, system_id, firmware_type, cfg_path, hpm_path, parameters)
    log:notice('[PMBus_Vrd] on_upgrade_prepare, firmware_type:%s', firmware_type)
    firmware_type = defs.FIRMWARE_TYPE.UPGRADE
    if self.is_upgrading then
        log:error('[PMBus_Vrd] Firmware %s is upgrading', firmware_type)
        fw_mgmt:UpdateServiceUpdateServicePrepareReply(context.new(), system_id, firmware_type, '',
            defs.RET.OTHERS_UPGRADING, parameters)
        return
    end

    self.is_upgrading = true

    cmn.skynet.fork_once(function()
        local ok, ret_code, version_str = pcall(function()
            return pmbus_vrd_upgrade_prepare(self, system_id, firmware_type, cfg_path, hpm_path, parameters)
        end)

        if not ok then
            log:error('[PMBus_Vrd] Call pmbus_vrd_upgrade_prepare failed, ret: %s', ret_code)
            ret_code = defs.RET.ERR
            version_str = ''
            self.is_upgrading = false
        end

        if ret_code ~= defs.RET.OK then
            self.is_upgrading = false
            log:error('[PMBus_Vrd] Upgrade prepare failed, firmware_type:%s, ret_code: %s', firmware_type, ret_code)
        end

        fw_mgmt:UpdateServiceUpdateServicePrepareReply(context.new(), system_id, firmware_type, version_str, ret_code,
            parameters)
    end)
end

function pmbus_vrd_upgrade:on_upgrade_process(_, system_id, firmware_type, file_path, parameters)
    log:notice('[PMBus_Vrd] on_upgrade_process, firmware_type:%s', firmware_type)
    firmware_type = defs.FIRMWARE_TYPE.UPGRADE
    cmn.skynet.fork(function()
        local ok, ret_code = pcall(function()
            return pmbus_vrd_upgrade_process(self, system_id, firmware_type, file_path, parameters)
        end)

        if not ok or ret_code ~= defs.RET.OK then
            log:error('[PMBus_Vrd] Call pmbus_vrd_upgrade_process failed, ok: %s, ret: %s', ok, ret_code)
            ret_code = defs.RET.ERR
            clear_vrd_upgrade_resource(self)
        end
        self.is_upgrading = false

        fw_mgmt:UpdateServiceUpdateServiceProcessReply(context.new(), system_id, firmware_type, ret_code,
            parameters)
    end)
end

function pmbus_vrd_upgrade:on_upgrade_finish(_, system_id, firmware_type, parameters)
    log:notice('[PMBus_Vrd] on_upgrade_finish, firmware_type:%s', firmware_type)
    firmware_type = defs.FIRMWARE_TYPE.UPGRADE
    cmn.skynet.fork_once(function()
        local ok, ret_code = pcall(function()
            return pmbus_vrd_upgrade_finish(self)
        end)

        if not ok then
            log:error('[PMBus_Vrd] Call pmbus_vrd_upgrade_finish failed, ret: %s', ret_code)
            ret_code = defs.RET.ERR
        end
        self.is_upgrading = false

        fw_mgmt:UpdateServiceUpdateServiceFinishReply(context.new(), system_id, firmware_type, ret_code,
            parameters)
    end)
end

-- 查找缓存的升级文件
local function find_cached_upgrade_file(cache_dir)
    if not vos.get_file_accessible(cache_dir) then
        log:error('[PMBus_Vrd] cache upgrade directory not exist: %s', cache_dir)
        return nil
    end

    for _, file_name in pairs(utils_core.dir(cache_dir)) do
        -- file_name be like: HOST_<sys_id>_Independent_Vrd_PMBus.hpm
        if file_name:match(defs.FIRMWARE_TYPE.PMBUS_UPGRADE) then
            local file_path = cache_dir .. file_name
            log:notice('[PMBus_Vrd] Found cached upgrade file: %s', file_path)
            return file_path
        end
    end

    log:error('[PMBus_Vrd] No cached upgrade file found in: %s', cache_dir)
    return nil
end

-- 解压缓存的固件包
local function unzip_cached_firmware(self, file_path)
    -- 获取升级包信息
    local package_info = cmn.get_package_info(file_path)
    if not package_info or not package_info.FirmwareDirectory then
        log:error('[PMBus_Vrd] Failed to get package info from file: %s', file_path)
        return nil, defs.RET.ERR
    end
    local dir = package_info.FirmwareDirectory
    local firmware_name = get_firmware_name(self.db, dir)
    if not firmware_name then
        log:error('[PMBus_Vrd] Failed to locate firmware entry under directory: %s', dir)
        return nil, defs.RET.ERR
    end
    local firmware_path = dir .. firmware_name
    utils.secure_tar_unzip(firmware_path, dir, 0x6400000, 1024)
    return dir, defs.RET.OK
end

-- 生效所有VRD管理器
local function activate_all_vrd_managers(self, dir)
    -- 执行所有VRD管理器的升级
    for _, vrd_manager in pairs(self.vrd_manager_collection) do
        log:notice('[PMBus_Vrd] Activating VRD manager')
        local upgrade_ret = vrd_manager:vrd_upgrade(dir)
        vrd_manager:update_firmware_version(self.bus)
        if upgrade_ret ~= defs.RET.OK then
            return defs.RET.ERR
        end
        -- 更新固件版本
        log:notice('[PMBus_Vrd] VRD manager activated successfully')
    end
    return defs.RET.OK
end

-- 清理升级相关文件
local function cleanup_upgrade_files(file_path, dir)
    -- 删除缓存文件
    if vos.get_file_accessible(file_path) then
        utils.remove_file(file_path)
    end

    -- 删除解压目录
    if vos.get_file_accessible(dir) then
        utils.remove_file(dir)
    end
end

-- 等待VRD对象加载完成
local function wait_vrd_objects_complete(self)
    -- 如果集合为空，直接返回成功
    if not next(self.vrd_manager_collection) then
        log:notice('[PMBus_Vrd] No VRD managers to wait for')
        return true
    end

    for _ = 1, 200 do
        local all_complete = true
        -- 检查所有VRD管理器是否都已加载完成
        for position, vrd_manager in pairs(self.vrd_manager_collection) do
            if not vrd_manager:is_objects_complete() then
                all_complete = false
                log:debug('[PMBus_Vrd] Waiting for objects to complete, position: %s, UID: %s',
                    position, vrd_manager.UID)
                break
            end
        end

        if all_complete then
            log:notice('[PMBus_Vrd] All VRD objects loaded complete')
            return true
        end

        cmn.skynet.sleep(100)
    end

    log:error('[PMBus_Vrd] Wait for VRD objects load timeout')
    return false
end

-- 执行生效升级流程
local function execute_active_upgrade(self, file_path)
    -- 解压缓存的固件
    local dir, ret_code = unzip_cached_firmware(self, file_path)
    if ret_code ~= defs.RET.OK then
        log:error('[PMBus_Vrd] Failed to unzip cached firmware')
        return ret_code
    end

    -- 生效所有VRD管理器
    ret_code = activate_all_vrd_managers(self, dir)
    if ret_code ~= defs.RET.OK then
        log:error('[PMBus_Vrd] Failed to activate VRD managers')
        return ret_code
    end

    -- 清理升级文件
    cleanup_upgrade_files(file_path, dir)
    return defs.RET.OK
end

function pmbus_vrd_upgrade:on_active_process(_, system_id, firmware_type)
    log:notice('[PMBus_Vrd] on_active_process, firmware_type:%s', firmware_type)
    firmware_type = defs.FIRMWARE_TYPE.ACTIVE

    if self:is_upgrading_or_activing() then
        log:notice('[PMBus_Vrd] is_activing = %s or PMBus_Vrd is Upgrading', self.is_activing)
        fw_mgmt:FirmwareActiveFirmwareActiveActiveProcessReply(context.new(), system_id, firmware_type, defs.RET.ERR)
        return
    end

    log:notice('[PMBus_Vrd] active vrd start')
    self.is_activing = true

    -- 更新生效状态为Apply
    update_active_status(firmware_type, firmware_type, 'Apply')

    local ret_code
    local cache_dir = defs.FW_VALID_FILE_DIR[defs.FIRMWARE_TYPE.UPGRADE]

    -- 查找缓存的升级文件
    local file_path = find_cached_upgrade_file(cache_dir)
    if file_path then
        -- 等待VRD对象加载完成
        if not wait_vrd_objects_complete(self) then
            log:error('[PMBus_Vrd] Wait for VRD objects load failed, abort active upgrade')
            ret_code = defs.RET.ERR
        else
            -- 加上电锁，用于kvm展示
            fructl.set_poweron_lock_until_success(self.bus, system_id, true, LOCK_FOREVER, 'Vrd')
            ret_code = execute_active_upgrade(self, file_path)
        end
    else
        ret_code = defs.RET.ERR
    end

    -- 解除上电锁
    fructl.set_poweron_lock_until_success(self.bus, system_id, false, LOCK_FOREVER, 'Vrd')

    self.is_activing = false
    log:notice('[PMBus_Vrd] active vrd finish, ret_code: %s', ret_code)

    -- 等待1s，防止响应过快firmware_mgmt没有收到回应
    cmn.skynet.sleep(100)
    fw_mgmt:FirmwareActiveFirmwareActiveActiveProcessReply(context.new(), system_id, firmware_type, ret_code)
end

function pmbus_vrd_upgrade:is_upgrading_or_activing()
    if self.is_activing then
        log:debug('[PMBus_Vrd] find firmware is activing')
        return true
    end
    if self.is_upgrading then
        log:debug('[PMBus_Vrd] find firmware is upgrading')
        return true
    end
    return false
end

return pmbus_vrd_upgrade