-- Copyright (c) 2024 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.

local dtframe = require 'dtframe'
local bs = require 'mc.bitstring'
local json = require 'cjson'
local enums = require 'ipmi.enums'
local channel_type = enums.ChannelType
local FuzzNetworkAdapterIpmiCmds = {}
local bus = {}
local PROJECT_DIR = os.getenv('PROJECT_DIR')
if PROJECT_DIR == nil then
    error("PROJECT_DIR does not exist!")
end

local cf = {
    ["corpus_folder"] = PROJECT_DIR..'/test/fuzz/.dtframe/fuzz_corpus/',
    ["report_file"] = PROJECT_DIR..'/test/fuzz/.dtframe/fuzz_report.log',
    ["mds_path"] = PROJECT_DIR..'/test/fuzz/.dtframe/fuzz_mds/fuzz_ipmi.json',
    ["fuzz_count"] = 10000
}

local function setup_module()
    print("==call setup_module() succeed==")
end

local function teardown_module()
    print("==call teardown_module() succeed==")
end

local function setup()
    print("==call setup() succeed==")
end

local function teardown()
    print("==call teardown() succeed==")
end

local function fuzz_process(func, func_name)
    local count = cf["fuzz_count"]
    setup()
    print("================start fuzz "..func_name.."====================")
    dtframe.fuzz_start(func_name)
    for i = 1, count do
        dtframe.fuzz_for_start(i-1)
        dtframe.fuzz_run(func)
        if (dtframe.fuzz_for_end()) == 1 then
            print("break\n")
            break
        end
    end
    dtframe.fuzz_end()
    print("================complete fuzz "..func_name.."====================")
    teardown()
end

local function ipmi_test_tool(bus, ipmi_req)

    local ipmi_package = bs.new('<<_,_:2,DestNetFn:6,_:3/unit:8,Cmd,Payload/string>>')
    local req = ipmi_package:pack(ipmi_req)
    local ctx = json.encode({ ChanType = channel_type.CT_ME:value(), Instance = 0 })
    local rsp = bus:call('bmc.kepler.ipmi_core', '/bmc/kepler/IpmiCore',
        'bmc.kepler.IpmiCore', 'Route', 'a{ss}ayay', require 'mc.context'.new(), req, ctx)
    return rsp
end

local function fuzz_WriteMacAddress()

    local fuzz_data = dtframe.fuzz_set_get_ipmi('WriteMacAddress')
    local data = {
        DestNetFn=0x30,
        Cmd=0x90,
        Payload=fuzz_data .. '\x00'
    }
    ipmi_test_tool(bus, data)
end

local function fuzz_GetMacAddress()

    local fuzz_data = dtframe.fuzz_set_get_ipmi('GetMacAddress')
    local data = {
        DestNetFn=0x30,
        Cmd=0x90,
        Payload=fuzz_data .. '\x00'
    }
    ipmi_test_tool(bus, data)
end

local function fuzz_GetNcsiSlot()

    local fuzz_data = dtframe.fuzz_set_get_ipmi('GetNcsiSlot')
    local data = {
        DestNetFn=0x30,
        Cmd=0x93,
        Payload=fuzz_data .. '\x00'
    }
    ipmi_test_tool(bus, data)
end

local function fuzz_GetBusinessPortInfo()

    local fuzz_data = dtframe.fuzz_set_get_ipmi('GetBusinessPortInfo')
    local data = {
        DestNetFn=0x30,
        Cmd=0x93,
        Payload=fuzz_data .. '\x00'
    }
    ipmi_test_tool(bus, data)
end

local function fuzz_SetIPMCConfiguration()

    local fuzz_data = dtframe.fuzz_set_get_ipmi('SetIPMCConfiguration')
    local data = {
        DestNetFn=0x30,
        Cmd=0x93,
        Payload=fuzz_data .. '\x00'
    }
    ipmi_test_tool(bus, data)
end

local function fuzz_GetIPMCConfiguration()

    local fuzz_data = dtframe.fuzz_set_get_ipmi('GetIPMCConfiguration')
    local data = {
        DestNetFn=0x30,
        Cmd=0x93,
        Payload=fuzz_data .. '\x00'
    }
    ipmi_test_tool(bus, data)
end

local function fuzz_GetNetworkAdapterModelByLOM()

    local fuzz_data = dtframe.fuzz_set_get_ipmi('GetNetworkAdapterModelByLOM')
    local data = {
        DestNetFn=0x30,
        Cmd=0x93,
        Payload=fuzz_data .. '\x00'
    }
    ipmi_test_tool(bus, data)
end

local function fuzz_GetNetworkAdapterModelByOCPCard()

    local fuzz_data = dtframe.fuzz_set_get_ipmi('GetNetworkAdapterModelByOCPCard')
    local data = {
        DestNetFn=0x30,
        Cmd=0x93,
        Payload=fuzz_data .. '\x00'
    }
    ipmi_test_tool(bus, data)
end

function FuzzNetworkAdapterIpmiCmds.fuzz_test(b)
    bus = b
    dtframe.fuzz_updateconfig(cf)
    setup_module()
    fuzz_process(fuzz_WriteMacAddress, "WriteMacAddress")
    fuzz_process(fuzz_GetMacAddress, "GetMacAddress")
    fuzz_process(fuzz_GetNcsiSlot, "GetNcsiSlot")
    fuzz_process(fuzz_GetBusinessPortInfo, "GetBusinessPortInfo")
    fuzz_process(fuzz_SetIPMCConfiguration, "SetIPMCConfiguration")
    fuzz_process(fuzz_GetIPMCConfiguration, "GetIPMCConfiguration")
    fuzz_process(fuzz_GetNetworkAdapterModelByLOM, "GetNetworkAdapterModelByLOM")
    fuzz_process(fuzz_GetNetworkAdapterModelByOCPCard, "GetNetworkAdapterModelByOCPCard")
    teardown_module()
end

return FuzzNetworkAdapterIpmiCmds

