/*
// Copyright (c) 2018 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
*/

#include "dimm.hpp"

#include "mdrv2.hpp"

#include <boost/algorithm/string.hpp>
#include <phosphor-logging/elog-errors.hpp>

#include <regex>

namespace phosphor
{
namespace smbios
{

#ifdef DIMM_ONLY_LOCATOR
bool onlyDimmLocationCode = true;
#else
bool onlyDimmLocationCode = false;
#endif

using DeviceType =
    sdbusplus::server::xyz::openbmc_project::inventory::item::Dimm::DeviceType;

using EccType =
    sdbusplus::server::xyz::openbmc_project::inventory::item::Dimm::Ecc;

static constexpr uint16_t maxOldDimmSize = 0x7fff;
void Dimm::memoryInfoUpdate(uint8_t* smbiosTableStorage,
                            const std::string& motherboard)
{
    storage = smbiosTableStorage;
    motherboardPath = motherboard;

    uint8_t* dataIn = storage;

    dataIn = getSMBIOSTypePtr(dataIn, memoryDeviceType);

    if (dataIn == nullptr)
    {
        return;
    }
    for (uint8_t index = 0; index < dimmNum; index++)
    {
        dataIn = smbiosNextPtr(dataIn);
        if (dataIn == nullptr)
        {
            return;
        }
        dataIn = getSMBIOSTypePtr(dataIn, memoryDeviceType);
        if (dataIn == nullptr)
        {
            return;
        }
    }

    auto memoryInfo = reinterpret_cast<struct MemoryInfo*>(dataIn);

    memoryDataWidth(memoryInfo->dataWidth);
    memoryTotalWidth(memoryInfo->totalWidth);

    if (memoryInfo->size == maxOldDimmSize)
    {
        dimmSizeExt(memoryInfo->extendedSize);
    }
    else
    {
        dimmSize(memoryInfo->size);
    }
    // If the size is 0, no memory device is installed in the socket.
    const auto isDimmPresent = memoryInfo->size > 0;
    present(isDimmPresent);
    functional(isDimmPresent);

    dimmDeviceLocator(memoryInfo->bankLocator, memoryInfo->deviceLocator,
                      memoryInfo->length, dataIn);
    dimmType(memoryInfo->memoryType);
    dimmTypeDetail(memoryInfo->typeDetail);
    maxMemorySpeedInMhz(memoryInfo->speed);
    dimmManufacturer(memoryInfo->manufacturer, memoryInfo->length, dataIn);
    dimmSerialNum(memoryInfo->serialNum, memoryInfo->length, dataIn);
    dimmPartNum(memoryInfo->partNum, memoryInfo->length, dataIn);
    memoryAttributes(memoryInfo->attributes);
    dimmMedia(memoryInfo->memoryTechnology);
    memoryConfiguredSpeedInMhz(memoryInfo->confClockSpeed);

    updateEccType(memoryInfo->phyArrayHandle);

    if (!motherboardPath.empty())
    {
        std::vector<std::tuple<std::string, std::string, std::string>> assocs;
        assocs.emplace_back("chassis", "memories", motherboardPath);
        association::associations(assocs);
    }

    return;
}

void Dimm::updateEccType(uint16_t exPhyArrayHandle)
{
    uint8_t* dataIn = storage;

    while (dataIn != nullptr)
    {
        dataIn = getSMBIOSTypePtr(dataIn, physicalMemoryArrayType);
        if (dataIn == nullptr)
        {
            phosphor::logging::log<phosphor::logging::level::ERR>(
                "Failed to get SMBIOS table type-16 data.");
            return;
        }

        auto info = reinterpret_cast<struct PhysicalMemoryArrayInfo*>(dataIn);
        if (info->handle == exPhyArrayHandle)
        {
            std::map<uint8_t, EccType>::const_iterator it =
                dimmEccTypeMap.find(info->memoryErrorCorrection);
            if (it == dimmEccTypeMap.end())
            {
                ecc(EccType::NoECC);
            }
            else
            {
                ecc(it->second);
            }
            return;
        }

        dataIn = smbiosNextPtr(dataIn);
    }
    phosphor::logging::log<phosphor::logging::level::ERR>(
        "Failed find the corresponding SMBIOS table type-16 data for dimm:",
        phosphor::logging::entry("DIMM:%d", dimmNum));
}

EccType Dimm::ecc(EccType value)
{
    return sdbusplus::server::xyz::openbmc_project::inventory::item::Dimm::ecc(
        value);
}

uint16_t Dimm::memoryDataWidth(uint16_t value)
{
    return sdbusplus::server::xyz::openbmc_project::inventory::item::Dimm::
        memoryDataWidth(value);
}

uint16_t Dimm::memoryTotalWidth(uint16_t value)
{
    return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm::
        memoryTotalWidth(value);
}

static constexpr uint16_t baseNewVersionDimmSize = 0x8000;
static constexpr uint16_t dimmSizeUnit = 1024;
void Dimm::dimmSize(const uint16_t size)
{
    uint32_t result = size & maxOldDimmSize;
    if (0 == (size & baseNewVersionDimmSize))
    {
        result = result * dimmSizeUnit;
    }
    memorySizeInKB(result);
}

void Dimm::dimmSizeExt(uint32_t size)
{
    size = size * dimmSizeUnit;
    memorySizeInKB(size);
}

size_t Dimm::memorySizeInKB(size_t value)
{
    return sdbusplus::server::xyz::openbmc_project::inventory::item::Dimm::
        memorySizeInKB(value);
}

void Dimm::dimmDeviceLocator(const uint8_t bankLocatorPositionNum,
                             const uint8_t deviceLocatorPositionNum,
                             const uint8_t structLen, uint8_t* dataIn)
{
    std::string deviceLocator =
        positionToString(deviceLocatorPositionNum, structLen, dataIn);
    std::string bankLocator =
        positionToString(bankLocatorPositionNum, structLen, dataIn);

    std::string result;
    if (bankLocator.empty() || onlyDimmLocationCode)
    {
        result = deviceLocator;
    }
    else
    {
        result = bankLocator + " " + deviceLocator;
    }

    memoryDeviceLocator(result);

    locationCode(result);
    const std::string substrCpu = "CPU";
    auto cpuPos = deviceLocator.find(substrCpu);

    if (cpuPos != std::string::npos)
    {
        std::string socketString =
            deviceLocator.substr(cpuPos + substrCpu.length(), 1);
        try
        {
            uint8_t socketNum =
                static_cast<uint8_t>(std::stoi(socketString) + 1);
            socket(socketNum);
        }
        catch (const sdbusplus::exception_t& ex)
        {
            phosphor::logging::log<phosphor::logging::level::ERR>(
                "std::stoi operation failed ",
                phosphor::logging::entry("ERROR=%s", ex.what()));
        }
    }

    const std::string substrDimm = "DIMM";
    auto dimmPos = deviceLocator.find(substrDimm);

    if (dimmPos != std::string::npos)
    {
        std::string slotString =
            deviceLocator.substr(dimmPos + substrDimm.length() + 1);
        /* slotString is extracted from substrDimm (DIMM_A) if slotString is
         * single alphabet like A, B , C.. then assign ASCII value of slotString
         * to slot */
        if ((std::regex_match(slotString, std::regex("^[A-Za-z]+$"))) &&
            (slotString.length() == 1))
        {
            slot(static_cast<uint8_t>(toupper(slotString[0])));
        }
    }
}

std::string Dimm::memoryDeviceLocator(std::string value)
{
    return sdbusplus::server::xyz::openbmc_project::inventory::item::Dimm::
        memoryDeviceLocator(value);
}

void Dimm::dimmType(const uint8_t type)
{
    std::map<uint8_t, DeviceType>::const_iterator it = dimmTypeTable.find(type);
    if (it == dimmTypeTable.end())
    {
        memoryType(DeviceType::Unknown);
    }
    else
    {
        memoryType(it->second);
    }
}

DeviceType Dimm::memoryType(DeviceType value)
{
    return sdbusplus::server::xyz::openbmc_project::inventory::item::Dimm::
        memoryType(value);
}

void Dimm::dimmMedia(const uint8_t type)
{
    std::map<uint8_t, MemoryTechType>::const_iterator it =
        dimmMemoryTechTypeMap.find(type);
    if (it == dimmMemoryTechTypeMap.end())
    {
        memoryMedia(MemoryTechType::Unknown);
    }
    else
    {
        memoryMedia(it->second);
    }
}

MemoryTechType Dimm::memoryMedia(MemoryTechType value)
{
    return sdbusplus::server::xyz::openbmc_project::inventory::item::Dimm::
        memoryMedia(value);
}

void Dimm::dimmTypeDetail(uint16_t detail)
{
    std::string result;
    for (uint8_t index = 0; index < (8 * sizeof(detail)); index++)
    {
        if (detail & 0x01)
        {
            result += detailTable[index];
        }
        detail >>= 1;
    }
    memoryTypeDetail(result);
}

std::string Dimm::memoryTypeDetail(std::string value)
{
    return sdbusplus::server::xyz::openbmc_project::inventory::item::Dimm::
        memoryTypeDetail(value);
}

uint16_t Dimm::maxMemorySpeedInMhz(uint16_t value)
{
    return sdbusplus::server::xyz::openbmc_project::inventory::item::Dimm::
        maxMemorySpeedInMhz(value);
}

void Dimm::dimmManufacturer(const uint8_t positionNum, const uint8_t structLen,
                            uint8_t* dataIn)
{
    std::string result = positionToString(positionNum, structLen, dataIn);

    if (result == "NO DIMM")
    {
        // No dimm presence so making manufacturer value as "" (instead of
        // NO DIMM - as there won't be any manufacturer for DIMM which is not
        // present).
        result = "";
    }
    manufacturer(result);
}

std::string Dimm::manufacturer(std::string value)
{
    return sdbusplus::server::xyz::openbmc_project::inventory::decorator::
        Asset::manufacturer(value);
}

bool Dimm::present(bool value)
{
    return sdbusplus::server::xyz::openbmc_project::inventory::Item::present(
        value);
}

void Dimm::dimmSerialNum(const uint8_t positionNum, const uint8_t structLen,
                         uint8_t* dataIn)
{
    std::string result = positionToString(positionNum, structLen, dataIn);

    serialNumber(result);
}

std::string Dimm::serialNumber(std::string value)
{
    return sdbusplus::server::xyz::openbmc_project::inventory::decorator::
        Asset::serialNumber(value);
}

void Dimm::dimmPartNum(const uint8_t positionNum, const uint8_t structLen,
                       uint8_t* dataIn)
{
    std::string result = positionToString(positionNum, structLen, dataIn);

    // Part number could contain spaces at the end. Eg: "abcd123  ". Since its
    // unnecessary, we should remove them.
    boost::algorithm::trim_right(result);
    partNumber(result);
}

std::string Dimm::partNumber(std::string value)
{
    return sdbusplus::server::xyz::openbmc_project::inventory::decorator::
        Asset::partNumber(value);
}

std::string Dimm::locationCode(std::string value)
{
    return sdbusplus::server::xyz::openbmc_project::inventory::decorator::
        LocationCode::locationCode(value);
}

size_t Dimm::memoryAttributes(size_t value)
{
    return sdbusplus::server::xyz::openbmc_project::inventory::item::Dimm::
        memoryAttributes(value);
}

uint8_t Dimm::slot(uint8_t value)
{
    return sdbusplus::server::xyz::openbmc_project::inventory::item::dimm::
        MemoryLocation::slot(value);
}

uint8_t Dimm::socket(uint8_t value)
{
    return sdbusplus::server::xyz::openbmc_project::inventory::item::dimm::
        MemoryLocation::socket(value);
}

uint16_t Dimm::memoryConfiguredSpeedInMhz(uint16_t value)
{
    return sdbusplus::server::xyz::openbmc_project::inventory::item::Dimm::
        memoryConfiguredSpeedInMhz(value);
}

bool Dimm::functional(bool value)
{
    return sdbusplus::server::xyz::openbmc_project::state::decorator::
        OperationalStatus::functional(value);
}

} // namespace smbios
} // namespace phosphor
