Add CPU dbus service for MDR V2

Add all CPU information in smbios table and provide dbus
interface for redfish to get CPU information.

Tested:
DC cycle system and waiting for BIOS entering setup page.
Check CPU information in Redfish, Redfish should show correct CPU
information.

Signed-off-by: Cheng C Yang <cheng.c.yang@linux.intel.com>
Change-Id: I8e6f803c516267de094a01fb1b1fa7d2420d2474
diff --git a/src/cpu.cpp b/src/cpu.cpp
new file mode 100644
index 0000000..f7681c9
--- /dev/null
+++ b/src/cpu.cpp
@@ -0,0 +1,249 @@
+/*
+// 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 "cpu.hpp"
+
+#include <iostream>
+#include <map>
+
+namespace phosphor
+{
+namespace smbios
+{
+
+void Cpu::cpuSocket(const uint8_t positionNum, const uint8_t structLen,
+                    uint8_t *dataIn)
+{
+    std::string result = positionToString(positionNum, structLen, dataIn);
+
+    processorSocket(result);
+}
+
+std::string Cpu::processorSocket(std::string value)
+{
+    return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Cpu::
+        processorSocket(value);
+}
+
+void Cpu::cpuType(const uint8_t value)
+{
+    std::map<uint8_t, const char *>::const_iterator it =
+        processorTypeTable.find(value);
+    if (it == processorTypeTable.end())
+    {
+        processorType("Unknown Processor Type");
+    }
+    else
+    {
+        processorType(it->second);
+    }
+}
+
+std::string Cpu::processorType(std::string value)
+{
+    return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Cpu::
+        processorType(value);
+}
+
+void Cpu::cpuFamily(const uint8_t value)
+{
+    std::map<uint8_t, const char *>::const_iterator it =
+        familyTable.find(value);
+    if (it == familyTable.end())
+    {
+        processorFamily("Unknown Processor Family");
+    }
+    else
+    {
+        processorFamily(it->second);
+    }
+}
+
+std::string Cpu::processorFamily(std::string value)
+{
+    return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Cpu::
+        processorFamily(value);
+}
+
+void Cpu::cpuManufacturer(const uint8_t positionNum, const uint8_t structLen,
+                          uint8_t *dataIn)
+{
+    std::string result = positionToString(positionNum, structLen, dataIn);
+
+    manufacturer(result);
+}
+
+std::string Cpu::manufacturer(std::string value)
+{
+    return sdbusplus::xyz::openbmc_project::Inventory::Decorator::server::
+        Asset::manufacturer(value);
+}
+
+uint32_t Cpu::processorId(uint32_t value)
+{
+    return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Cpu::
+        processorId(value);
+}
+
+void Cpu::cpuVersion(const uint8_t positionNum, const uint8_t structLen,
+                     uint8_t *dataIn)
+{
+    std::string result;
+
+    result = positionToString(positionNum, structLen, dataIn);
+
+    processorVersion(result);
+}
+
+std::string Cpu::processorVersion(std::string value)
+{
+    return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Cpu::
+        processorVersion(value);
+}
+
+uint16_t Cpu::processorMaxSpeed(uint16_t value)
+{
+    return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Cpu::
+        processorMaxSpeed(value);
+}
+
+void Cpu::cpuCharacteristics(uint16_t value)
+{
+    std::string result = "";
+    for (uint8_t index = 0; index < (8 * sizeof(value)); index++)
+    {
+        if (value & 0x01)
+        {
+            result += characteristicsTable[index];
+        }
+        value >>= 1;
+    }
+
+    processorCharacteristics(result);
+}
+
+std::string Cpu::processorCharacteristics(std::string value)
+{
+    return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Cpu::
+        processorCharacteristics(value);
+}
+
+uint16_t Cpu::processorCoreCount(uint16_t value)
+{
+    return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Cpu::
+        processorCoreCount(value);
+}
+
+uint16_t Cpu::processorThreadCount(uint16_t value)
+{
+    return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Cpu::
+        processorThreadCount(value);
+}
+
+static constexpr const uint8_t populateMask = 1 << 6;
+static constexpr const uint8_t statusMask = 0x07;
+void Cpu::cpuStatus(uint8_t value)
+{
+    if (!(value & populateMask))
+    {
+        present(false);
+        functional(false);
+        return;
+    }
+    present(true);
+    if ((value & statusMask) == 1)
+    {
+        functional(true);
+    }
+    else
+    {
+        functional(false);
+    }
+}
+
+bool Cpu::present(bool value)
+{
+    return sdbusplus::xyz::openbmc_project::Inventory::server::Item::present(
+        value);
+}
+
+bool Cpu::functional(bool value)
+{
+    return sdbusplus::xyz::openbmc_project::State::Decorator::server::
+        OperationalStatus::functional(value);
+}
+
+static constexpr uint8_t maxOldVersionCount = 0xff;
+void Cpu::processorInfoUpdate(void)
+{
+    uint8_t *dataIn = storage;
+
+    dataIn = getSMBIOSTypePtr(dataIn, processorsType);
+    if (dataIn == nullptr)
+    {
+        return;
+    }
+
+    for (uint8_t index = 0; index < cpuNum; index++)
+    {
+        dataIn = smbiosNextPtr(dataIn);
+        if (dataIn == nullptr)
+        {
+            return;
+        }
+        dataIn = getSMBIOSTypePtr(dataIn, processorsType);
+        if (dataIn == nullptr)
+        {
+            return;
+        }
+    }
+
+    auto cpuInfo = reinterpret_cast<struct ProcessorInfo *>(dataIn);
+
+    cpuSocket(cpuInfo->socketDesignation, cpuInfo->length,
+              dataIn);               // offset 4h
+    cpuType(cpuInfo->processorType); // offset 5h
+    cpuFamily(cpuInfo->family);      // offset 6h
+    cpuManufacturer(cpuInfo->manufacturer, cpuInfo->length,
+                    dataIn);                               // offset 7h
+    processorId(cpuInfo->id);                              // offset 8h
+    cpuVersion(cpuInfo->version, cpuInfo->length, dataIn); // offset 10h
+    processorMaxSpeed(cpuInfo->maxSpeed);                  // offset 14h
+    if (cpuInfo->coreCount < maxOldVersionCount)           // offset 23h or 2Ah
+    {
+        processorCoreCount(cpuInfo->coreCount);
+    }
+    else
+    {
+        processorCoreCount(cpuInfo->coreCount2);
+    }
+
+    if (cpuInfo->threadCount < maxOldVersionCount) // offset 25h or 2Eh)
+    {
+        processorThreadCount(cpuInfo->threadCount);
+    }
+    else
+    {
+        processorThreadCount(cpuInfo->threadCount2);
+    }
+
+    cpuCharacteristics(cpuInfo->characteristics); // offset 26h
+
+    cpuStatus(cpuInfo->status);
+}
+
+} // namespace smbios
+} // namespace phosphor