------------------- openUBMC INFO -------------------
IPMC                   CPU:         {* CpuType *}
IPMI               Version:         2.0
Active openUBMC    Version:         {* ActiveVersion *}
Active openUBMC      Build:         {* ActiveBuildNum *}
Active openUBMC      Built:         {* ActiveReleaseDate *}
Backup openUBMC    Version:         {* BackupVersion *}
Available openUBMC Version:         {* AvailableVersion *}
Available openUBMC   Build:         {* AvailableBuildNum *}
Active Uboot       Version:         {* ActiveUbootVersion *} ({* ActiveUbootReleaseDate *})
Backup Uboot       Version:         {* BackupUbootVersion *} ({* BackupUbootReleaseDate *})
Active Secure Bootloader Version: {* ActiveSecureBootloaderVersion *} ({* ActiveSecureBootloaderReleaseDate *})
Backup Secure Bootloader Version: {* BackupSecureBootloaderVersion *} ({* BackupSecureBootloaderReleaseDate *})
Active Secure Firmware   Version: {* ActiveSecureFirmwareVersion *} ({* ActiveSecureFirmwareReleaseDate *})
Backup Secure Firmware   Version: {* BackupSecureFirmwareVersion *} ({* BackupSecureFirmwareReleaseDate *})
Active BMCSDK      Version:         {* ActiveBMCSDKVersion *}
{%
if CoprocessorFirmwareVersion ~= '' then
    echo(string.format('Coprocessor Firmware     Version: %s\n', CoprocessorFirmwareVersion))
end
local function string_split(str, delimiter)
    -- 复用/echoes/ipmcget/_sel下的函数，用于字符串的拆分
    if str == nil or str == '' then
        return {}
    end
    if delimiter == nil then
        delimiter = ','
    end

    local res = {}
    for match in (str .. delimiter):gmatch("(.-)" .. delimiter) do
        table.insert(res, match)
    end
    return res
end

local function filter_type(version, name)
    -- 获取对应物理实体的版本
    -- version的格式为 e.g. SR_EXU_0101/MCU_IEU_01010101
    local all_version = {}
    if type(version) == 'table' then
        for _, v in pairs(version) do
            if type(v.Id) == 'string' and type(v.Version) == 'string' and string_split(v.Id,"_")[2] == name then
                table.insert(all_version, v.Version)
            end
        end
    end
    return all_version
end

local function get_nic_version(version, name, card_name)
    -- Name组成为固定格式DeviceName+' CSR',不取后四个字符匹配
    if type(version) == 'table' then
        for _, v in pairs(version) do
            if type(v.Id) == 'string' and type(v.Version) == 'string' and string_split(v.Id,"_")[2] == name
                and string.sub(v.Name, 1, -5) == card_name then
                return v.Version
            end
        end
    end
    return 'N/A'
end

echo('----------------- Product INFO -----------------\n')
if type(ProductId) == 'number' then
    echo(string.format('Product                 ID:         0x%04x\n', ProductId))
end
if type(ProductName) == 'string' then
    echo(string.format('Product               Name:         %s\n', ProductName))
end
if type(ProductUniqueID) == 'string' then
    echo(string.format('Product          Unique ID:         %s\n', ProductUniqueID))
end
for _, v in pairs(Bios) do
    local BiosVersion, BiosBackupVersion = v.Version, v.Version
    local BiosLocation = v.Location
    local Index = v.Index ~= 0 and tostring(v.Index) or ''
    if type(BiosLocation) ~= 'string' then
        BiosLocation = ''
    end
    if type(BiosVersion) ~= 'string' then
        BiosVersion = ''
    end
    if type(BiosBackupVersion) ~= 'string' then
        BiosBackupVersion = ''
    end
    if Index == '' then
        echo(string.format('Active BIOS%s        Version:         (%s)%s\n', Index, BiosLocation , BiosVersion))
        echo(string.format('Backup BIOS%s        Version:         %s\n', Index, BiosBackupVersion))
    else
        echo(string.format('Active BIOS%s       Version:         (%s)%s\n', Index, BiosLocation , BiosVersion))
        echo(string.format('Backup BIOS%s       Version:         %s\n', Index, BiosBackupVersion))
    end
end

if #filter_type(CsrVersion, 'PSR') > 0 then
    -- PSR归属Product INFO
    echo(string.format('PSR                Version:         %s\n', filter_type(CsrVersion, 'PSR')[1]))
end

if type(RiserCards) == 'table' and #RiserCards > 0 then
    echo('--------------- Riser Card INFO ----------------\n')
    local riser_name = 'Riser'
    table.sort(RiserCards, function (a, b)
        return a.Slot < b.Slot
    end)
    for _, v in pairs(RiserCards) do
        if type(v.Slot) == 'number' and type(v.Name) == 'string' and type(v.BoardID) == 'number' and type(v.UID) == 'string' then
            echo(string.format('%s%-5d       BoardName:         %s\n', riser_name, v.Slot, v.Name))
            echo(string.format('%s%-7d       BoardID:         0x%04x\n', riser_name, v.Slot, v.BoardID))
            echo(string.format('%s%-12d     CUID:         %s\n', riser_name, v.Slot, v.UID))
            if type(v.PCBVersion) == 'string' and v.PCBVersion ~= 'N/A'then
                echo(string.format('%s%-11d       PCB:         %s\n',  riser_name, v.Slot, v.PCBVersion))
            end
            if type(v.LogicVersion) == 'string' and type(v.LogicUnit) == 'number' and v.LogicVersion ~= "" and  v.LogicVersion ~= 'N/A' then
                echo(string.format('%s%-2d       CPLD Version:         (U%d)%s\n', riser_name, v.Slot, v.LogicUnit, v.LogicVersion))
            end
            if type(v.SRVersion) == 'string' and #v.SRVersion > 0 then
                echo(string.format('%s%-11d       CSR:         %s\n', riser_name, v.Slot, v.SRVersion))
            end
            if type(v.MCUVersion) == 'string' and #v.MCUVersion > 0 then
                echo(string.format('%s%-11d       MCU:         %s\n', riser_name, v.Slot, v.MCUVersion))
            end
        end
    end
end

if type(HddBackplanes) == 'table' and #HddBackplanes > 0 then
    echo('-------------- HDD Backplane INFO --------------\n')
    for _, v in pairs(HddBackplanes) do
        if type(v.DeviceName) == 'string' and type(v.Name) == 'string' and type(v.BoardID) == 'number' and type(v.UID) == 'string' and type(v.PCBVersion) == 'string' then
            echo(string.format('%-12s     BoardName:         %s\n', v.DeviceName, v.Name))
            echo(string.format('%-14s     BoardID:         0x%04x\n', v.DeviceName, v.BoardID))
            echo(string.format('%-17s     CUID:         %s\n', v.DeviceName, v.UID))
            echo(string.format('%-18s     PCB:         %s\n', v.DeviceName, v.PCBVersion))
            if type(v.LogicVersion) == 'string' and type(v.LogicUnit) == 'number' and v.LogicVersion ~= "" and  v.LogicVersion ~= 'N/A' then
                echo(string.format('%-9s     CPLD Version:         (U%d)%s\n', v.DeviceName, v.LogicUnit, v.LogicVersion))
            else
                echo(string.format('%-9s     CPLD Version:         N/A\n', v.DeviceName))
            end
            -- SEU归属该实体
            if type(v.SRVersion) == 'string' and #v.SRVersion > 0 then
                echo(string.format('%-18s     CSR:         %s\n', v.DeviceName, v.SRVersion))
            end
            if type(v.MCUVersion) == 'string' and #v.MCUVersion > 0 then
                echo(string.format('%-18s     MCU:         %s\n', v.DeviceName, v.MCUVersion))
            end
        end
    end
end

local function print_cpld_version(count, board_name, board)
    if count > 1 then
        for i = 1, count do
            echo(string.format('%s%-2d   CPLD%d Version:         (U%d)%s\n', board_name, board.Slot, i,
                board.MultiLogicUnit[string.format("CPLD%d", i)], board.MultiLogicVersion[string.format("CPLD%d", i)]))
        end
    elseif #board.LogicVersion > 0 and type(board.LogicVersion) == 'string' and type(board.LogicUnit) == 'number' then
        echo(string.format('%s%-1d     CPLD Version:         (U%d)%s\n', board_name, board.Slot, board.LogicUnit, board.LogicVersion))
    end
end

local function print_fpga_version(fpga_count, board_name, board)
    if fpga_count > 0 then
        echo(string.format('%s%-2d    FPGA Version:         (U%d)%s\n', board_name, board.Slot,
            board.MultiLogicUnit["FPGA"], board.MultiLogicVersion[string.format("FPGA")]))
    end
end

local function print_csr_version(board_name, board)
    if type(board.SRVersion) == 'string' and #board.SRVersion > 0 then
        echo(string.format('%s%-10d     CSR:         %s\n', board_name, board.Slot, board.SRVersion))
    end
end

local function print_mcu_version(board_name, board)
    if type(board.MCUVersion) == 'string' and #board.MCUVersion > 0 then
        echo(string.format('%s%-10d     MCU:         %s\n', board_name, board.Slot, board.MCUVersion))
    end
end

local function print_xpu_boards(boards, board_name)
    for _, v in pairs(boards) do
        if type(v.Slot) == 'number' and type(v.Name) == 'string' and type(v.BoardID) == 'number' and type(v.UID) == 'string' and type(v.PCBVersion) == 'string' then
            echo(string.format('%s%-4d     BoardName:         %s\n', board_name, v.Slot, v.Name))
            echo(string.format('%s%-6d     BoardID:         0x%04x\n', board_name, v.Slot, v.BoardID))
            echo(string.format('%s%-9d     CUID:         %s\n', board_name, v.Slot, v.UID))
            echo(string.format('%s%-10d     PCB:         %s\n', board_name, v.Slot, v.PCBVersion))
            local count = 0
            local fpga_count = 0
            for key, value in pairs(v.MultiLogicVersion) do
                if not value or value == '0.00' then
                    goto continue
                end
                if string.match(key, "FPGA") then
                    fpga_count = fpga_count + 1
                    goto continue
                end
                count = count + 1
                ::continue::
            end
            print_cpld_version(count, board_name, v)
            print_fpga_version(fpga_count, board_name, v)
            print_csr_version(board_name, v)
            print_mcu_version(board_name, v)
        end
    end
end

if type(CpuBoards) == 'table' and #CpuBoards > 0 then
    echo('---------------- CPU Board INFO ----------------\n')
    print_xpu_boards(CpuBoards, 'CpuBoard')
end

if type(NpuBoards) == 'table' and #NpuBoards > 0 then
    echo('-------------- NPU/GPU Board INFO --------------\n')
    print_xpu_boards(NpuBoards, 'NpuBoard')
end

if type(ExpBoards) == 'table' and #ExpBoards > 0 then
    echo('---------------- EXP Board INFO ----------------\n')
    print_xpu_boards(ExpBoards, 'ExpBoard')
end

if type(FanBoards) == 'table' and #FanBoards > 0 then
    echo('---------------- FAN Board INFO ----------------\n')
    local fan_board_name = 'FanBoard'
    for _, v in pairs(FanBoards) do
        if type(v.Slot) == 'number' and type(v.Name) == 'string' and type(v.UID) == 'string' and type(v.PCBVersion) == 'string' then
            echo(string.format('%s%-4d     BoardName:         %s\n', fan_board_name, v.Slot, v.Name))
            if type(v.BoardID) == 'number' and v.BoardID ~= 0 then
                echo(string.format('%s%-6d     BoardID:         0x%04x\n', fan_board_name, v.Slot, v.BoardID))
            end
            echo(string.format('%s%-9d     CUID:         %s\n', fan_board_name, v.Slot, v.UID))
            echo(string.format('%s%-10d     PCB:         %s\n', fan_board_name, v.Slot, v.PCBVersion))
            if type(v.LogicVersion) == 'string' and type(v.LogicUnit) == 'number' and #v.LogicVersion > 0 and v.LogicVersion ~= "" then
                echo(string.format('%s%-1d     CPLD Version:         (U%d)%s\n', fan_board_name, v.Slot, v.LogicUnit, v.LogicVersion))
            end
            if type(v.SRVersion) == 'string' and #v.SRVersion > 0 then
                echo(string.format('%s%-10d     CSR:         %s\n', fan_board_name, v.Slot, v.SRVersion))
            end
            if type(v.MCUVersion) == 'string' and #v.MCUVersion > 0 then
                echo(string.format('%s%-10d     MCU:         %s\n', fan_board_name, v.Slot, v.MCUVersion))
            end
        end
    end
end

if type(NetworkCards) == 'table' and #NetworkCards > 0 then
    local nic_exist = false
    -- 根据槽位排序
    table.sort(NetworkCards, function(a, b)
        return tonumber(string.match(a.DeviceLocator, '%d+')) < tonumber(string.match(b.DeviceLocator, '%d+'))
    end)
    for _, v in pairs(NetworkCards) do
        if v.Type == 1 and type(v.DeviceLocator) == 'string' and type(v.BoardID) == 'number' and type(v.ComponentUniqueID) == 'string' and type(v.PCBVersion) == 'string' then
            if not nic_exist then
                echo('------------------- NIC INFO -------------------\n')
            end

            nic_exist = true
            local spaces = string.rep(' ', 9)
            local len = #v.DeviceLocator
            -- 当网卡长度大于临界值14时，计算对齐board_id增加空格
            if len > 14 then
                -- 9是正常打印情况下的空格个数
                spaces = string.rep(' ', 9 - (len - 14))
            end

            echo(string.format('%-14s     BoardID:%s0x%04x\n', v.DeviceLocator, spaces, v.BoardID))
            echo(string.format('%-17s     CUID:         %s\n', v.DeviceLocator, v.ComponentUniqueID))
            echo(string.format('%-18s     PCB:         %s\n', v.DeviceLocator, v.PCBVersion))
            if #filter_type(CsrVersion, 'NIC') > 0 then
                echo(string.format('%-18s     CSR:         %s\n', v.DeviceLocator, get_nic_version(CsrVersion, 'NIC', v.Name)))
            end
            if #filter_type(McuVersion, 'NIC') > 0 then
                echo(string.format('%-18s     MCU:         %s\n', v.DeviceLocator, get_nic_version(McuVersion, 'NIC', v.Name)))
            end
        end
    end
end

if type(PCIeCards) == 'table' and #PCIeCards > 0 then
    echo('---------------- PCIe Card INFO ----------------\n')
    for _, v in pairs(PCIeCards) do
        if type(v.Slot) == 'number' and type(v.Name) == 'string' and type(v.BoardID) == 'number' and type(v.PCBVersion) == 'string' then
            echo(string.format('PCIe%-6d     ProductName:         %s\n', v.Slot, v.Name))
            echo(string.format('PCIe%-10d     BoardID:         0x%04x\n', v.Slot, v.BoardID))
            echo(string.format('PCIe%-14d     PCB:         %s\n', v.Slot, v.PCBVersion))
            if type(v.CPLDVersion) == 'string' and #v.CPLDVersion > 0 then
                echo(string.format('PCIe%-5d     CLPD Version:         %s\n', v.Slot, v.CPLDVersion))
            end
            if type(v.SRVersion) == 'string' and #v.SRVersion > 0 then
                echo(string.format('PCIe%-7d     CSRVersion:         %s\n', v.Slot, v.SRVersion))
            end
            if type(v.UID) == 'string' and #v.UID > 0 then
                echo(string.format('PCIe%-13d     CUID:         %s\n', v.Slot, v.UID))
            end
            if type(v.MCUVersion) == 'string' and #v.MCUVersion > 0 then
                echo(string.format('PCIe%-14d     MCU:         %s\n', v.Slot, v.MCUVersion))
            end
            if type(v.VrdVersion) == 'string' and #v.VrdVersion > 0 then
                echo(string.format('PCIe%-14d     VRD:         %s\n', v.Slot, v.VrdVersion))
            end
        end
    end
end

if type(SecurityModules) == 'table' and #SecurityModules > 0 then
    echo('------------- Security Module INFO -------------\n')
    for _, v in pairs(SecurityModules) do
        if type(v.Protocol) == 'string' and type(v.ProtocolVersion) == 'string' and type(v.Manufacturer) == 'string' and type(v.FirmwareVersion) == 'string' then
            echo(string.format('Specification         Type:         %s\n', v.Protocol))
            echo(string.format('Specification      Version:         %s\n', v.ProtocolVersion))
            echo(string.format('Manufacturer          Name:         %s\n', v.Manufacturer))
            echo(string.format('Manufacturer       Version:         %s\n', v.FirmwareVersion))
        end
    end
end

if type(PsuBoards) == 'table' and #PsuBoards > 0 then
    -- 电源板对外作为单个电源组件展示
    echo('------------------- PSU INFO -------------------\n')
    local psu_board_name = 'PSU'
    for _, v in pairs(PsuBoards) do
        if type(v.Slot) == 'number' and type(v.Name) == 'string' and type(v.UID) == 'string' and type(v.PCBVersion) == 'string' then
            echo(string.format('%s%-9d     BoardName:         %s\n', psu_board_name, v.Slot, v.Name))
            if type(v.BoardID) == 'number' and v.BoardID ~= 0 then
                echo(string.format('%s%-11d     BoardID:         0x%04x\n', psu_board_name, v.Slot, v.BoardID))
            end
            echo(string.format('%s%-14d   CUID:         %s\n', psu_board_name, v.Slot, v.UID))
            if type(v.PCBVersion) == 'string' and #v.PCBVersion > 0 and v.PCBVersion ~= "" and v.PCBVersion ~= "N/A" then
                echo(string.format('%s%-15d     PCB:         %s\n', psu_board_name, v.Slot, v.PCBVersion))
            end
            if type(v.LogicVersion) == 'string' and type(v.LogicUnit) == 'number' and #v.LogicVersion > 0 and v.LogicVersion ~= "" and v.LogicVersion ~= "N/A" then
                echo(string.format('%s%-6d     CPLD Version:         (U%d)%s\n', psu_board_name, v.Slot, v.LogicUnit, v.LogicVersion))
            end
            if type(v.SRVersion) == 'string' and #v.SRVersion > 0 then
                echo(string.format('%s%-15d     CSR:         %s\n', psu_board_name, v.Slot, v.SRVersion))
            end
        end
    end
end

if type(PSUs) == 'table' and #PSUs > 0 then
    local one_powers = {}
    local power_converters = {}
    for _, v in pairs(PSUs) do
        if type(v.DeviceLocator) == 'string' and type(v.FirmwareVersion) == 'string' and string.match(v.DeviceLocator, "PSU") then
            one_powers[#one_powers + 1] = v
        end

        if type(v.DeviceLocator) == 'string' and type(v.FirmwareVersion) == 'string' and string.match(v.DeviceLocator, "PowerConverter") then
            power_converters[#power_converters + 1] = v
        end
    end

    table.sort(one_powers, function (a, b)
        return a.SlotNumber < b.SlotNumber
    end)

    if #one_powers > 0 then
        -- 存在电源板时已打印此信息，此处避免重复打印
        if #PsuBoards == 0 then
            echo('------------------- PSU INFO -------------------\n')
        end

        for _, v in pairs(one_powers) do
            echo(string.format('%s               Version:           %s\n', v.DeviceLocator, v.FirmwareVersion))
        end
    end

    if #power_converters > 0 then
        echo('-------------------- Power Converter INFO -------------------\n')
        for _, v in pairs(power_converters) do
            echo(string.format('%s               Version:           %s\n', v.DeviceLocator, v.FirmwareVersion))
        end
    end 
end

if type(PeuBoards) == 'table' and #PeuBoards > 0 then
    echo('---------------- PEU Board INFO ----------------\n')
    local peu_board_name = 'PeuBoard'
    for _, v in pairs(PeuBoards) do
        if type(v.Slot) == 'number' and type(v.Name) == 'string' and type(v.UID) == 'string' and type(v.PCBVersion) == 'string' then
            echo(string.format('%s%-4d     BoardName:         %s\n', peu_board_name, v.Slot, v.Name))
            if type(v.BoardID) == 'number' and v.BoardID ~= 0 then
                echo(string.format('%s%-6d     BoardID:         0x%04x\n', peu_board_name, v.Slot, v.BoardID))
            end
            echo(string.format('%s%-9d     CUID:         %s\n', peu_board_name, v.Slot, v.UID))
            if type(v.PCBVersion) == 'string' and #v.PCBVersion > 0 and v.PCBVersion ~= "" and v.PCBVersion ~= "N/A" then
                echo(string.format('%s%-10d     PCB:         %s\n', peu_board_name, v.Slot, v.PCBVersion))
            end
            if type(v.LogicVersion) == 'string' and type(v.LogicUnit) == 'number' and #v.LogicVersion > 0 and v.LogicVersion ~= "" and v.LogicVersion ~= "N/A" then
                echo(string.format('%s%-1d     CPLD Version:         (U%d)%s\n', peu_board_name, v.Slot, v.LogicUnit, v.LogicVersion))
            end
            if type(v.SRVersion) == 'string' and #v.SRVersion > 0 then
                echo(string.format('%s%-10d     CSR:         %s\n', peu_board_name, v.Slot, v.SRVersion))
            end
        end
    end
end
 
if type(VrdVersion) == 'table' and #VrdVersion > 0 then
    echo('------------------- Power INFO -------------------\n')
    local vrd_list = {}
    local vrd_name
    for _, v in pairs(VrdVersion) do
        vrd_name = string.match(v.Name, 'CpuBoard(%d+)')
        if type(v.Version) == 'string' and v.Version ~= '' and type(v.Name) == 'string' and vrd_name then
            table.insert(vrd_list, {vrd_name, v.Version})
        end
    end
    table.sort(vrd_list, function (a, b)
        return tonumber(a[1]) < tonumber(b[1])
    end)
    for _, value in ipairs(vrd_list) do
        echo(string.format('CpuBoard%-7s    Version:         %s\n', value[1] .. 'VRD', value[2]))
    end
end

if type(M2TransferCards) == 'table' and #M2TransferCards > 0 then
    echo('--------------- M.2 Adapter INFO ----------------\n')
    for _, v in pairs(M2TransferCards) do
        if type(v.DeviceName) == 'string' and type(v.Name) == 'string' and type(v.BoardID) == 'number' and type(v.UID) == 'string' and type(v.PCBVersion) == 'string' then
            echo(string.format('%-12s      BoardName:     %s\n', v.DeviceName, v.Name))
            echo(string.format('%-14s        BoardID:     0x%04x\n', v.DeviceName, v.BoardID))
            echo(string.format('%-17s         CUID:     %s\n', v.DeviceName, v.UID))
            echo(string.format('%-18s         PCB:     %s\n', v.DeviceName, v.PCBVersion))
            if type(v.LogicVersion) == 'string' and type(v.LogicUnit) == 'number' and v.LogicVersion ~= "" and  v.LogicVersion ~= 'N/A' then
                echo(string.format('%-9s   CPLD Version:     (U%d)%s\n', v.DeviceName, v.LogicUnit, v.LogicVersion))
            else
                echo(string.format('%-9s   CPLD Version:     N/A\n', v.DeviceName))
            end
            -- SEU归属该实体
            if type(v.SRVersion) == 'string' and #v.SRVersion > 0 then
                echo(string.format('%-18s         CSR:     %s\n', v.DeviceName, v.SRVersion))
            end
            if type(v.MCUVersion) == 'string' and #v.MCUVersion > 0 then
                echo(string.format('%-18s         MCU:     %s\n', v.DeviceName, v.MCUVersion))
            end
        end
    end
end
%}