Add system dbus service for MDR V2

Add BIOS version and UUID in smbios table and provide dbus
interface for redfish to get these information.

Tested:
DC cycle the system and waiting for BIOS entering setup page.
Redfish should be able to show correct UUID.

Signed-off-by: Cheng C Yang <cheng.c.yang@linux.intel.com>
Change-Id: I0d364f27488d3efa24e4a9dde97086f09e94d2a2
diff --git a/include/mdrv2.hpp b/include/mdrv2.hpp
index 3dfedf5..772711d 100644
--- a/include/mdrv2.hpp
+++ b/include/mdrv2.hpp
@@ -176,6 +176,7 @@
     int getTotalDimmSlot(void);
     std::vector<std::unique_ptr<Cpu>> cpus;
     std::vector<std::unique_ptr<Dimm>> dimms;
+    std::unique_ptr<System> system;
 };
 
 } // namespace smbios
diff --git a/include/system.hpp b/include/system.hpp
new file mode 100644
index 0000000..6d99599
--- /dev/null
+++ b/include/system.hpp
@@ -0,0 +1,114 @@
+/*
+// 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.
+*/
+
+#pragma once
+#include "smbios.hpp"
+
+#include <xyz/openbmc_project/Common/UUID/server.hpp>
+#include <xyz/openbmc_project/Inventory/Decorator/Revision/server.hpp>
+
+namespace phosphor
+{
+
+namespace smbios
+{
+
+class System : sdbusplus::server::object::object<
+                   sdbusplus::xyz::openbmc_project::Common::server::UUID>,
+               sdbusplus::server::object::object<
+                   sdbusplus::xyz::openbmc_project::Inventory::Decorator::
+                       server::Revision>
+{
+  public:
+    System() = delete;
+    ~System() = default;
+    System(const System &) = delete;
+    System &operator=(const System &) = delete;
+    System(System &&) = default;
+    System &operator=(System &&) = default;
+
+    System(sdbusplus::bus::bus &bus, const std::string &objPath,
+           uint8_t *smbiosTableStorage) :
+        sdbusplus::server::object::object<
+            sdbusplus::xyz::openbmc_project::Common::server::UUID>(
+            bus, objPath.c_str()),
+        sdbusplus::server::object::object<
+            sdbusplus::xyz::openbmc_project::Inventory::Decorator::server::
+                Revision>(bus, objPath.c_str()),
+        path(objPath), storage(smbiosTableStorage)
+    {
+        std::string input = "0";
+        uUID(input);
+        version("0.00");
+    }
+
+    std::string uUID(std::string value) override;
+
+    std::string version(std::string value) override;
+
+  private:
+    /** @brief Path of the group instance */
+    std::string path;
+
+    uint8_t *storage;
+
+    struct BIOSInfo
+    {
+        uint8_t type;
+        uint8_t length;
+        uint16_t handle;
+        uint8_t vendor;
+        uint8_t biosVersion;
+        uint16_t startAddrSegment;
+        uint8_t releaseData;
+        uint8_t romSize;
+        uint64_t characteristics;
+        uint16_t externCharacteristics;
+        uint8_t systemBIOSMajor;
+        uint8_t systemBIOSMinor;
+        uint8_t embeddedFirmwareMajor;
+        uint8_t embeddedFirmwareMinor;
+    } __attribute__((packed));
+
+    struct UUID
+    {
+        uint32_t timeLow;
+        uint16_t timeMid;
+        uint16_t timeHiAndVer;
+        uint8_t clockSeqHi;
+        uint8_t clockSeqLow;
+        uint8_t node[6];
+    } __attribute__((packed));
+
+    struct SystemInfo
+    {
+        uint8_t type;
+        uint8_t length;
+        uint16_t handle;
+        uint8_t manufacturer;
+        uint8_t productName;
+        uint8_t version;
+        uint8_t serialNum;
+        struct UUID uUID;
+        uint8_t wakeupType;
+        uint8_t skuNum;
+        uint8_t family;
+    } __attribute__((packed));
+};
+
+} // namespace smbios
+
+} // namespace phosphor
diff --git a/src/mdrv2.cpp b/src/mdrv2.cpp
index c392127..07dcc6b 100644
--- a/src/mdrv2.cpp
+++ b/src/mdrv2.cpp
@@ -396,6 +396,10 @@
         dimms.emplace_back(std::make_unique<phosphor::smbios::Dimm>(
             bus, path, index, smbiosDir.dir[smbiosDirIndex].dataStorage));
     }
+
+    system.reset();
+    system = std::make_unique<System>(
+        bus, systemPath, smbiosDir.dir[smbiosDirIndex].dataStorage);
 }
 
 int MDR_V2::getTotalCpuSlot()
diff --git a/src/system.cpp b/src/system.cpp
new file mode 100644
index 0000000..8cdcbe3
--- /dev/null
+++ b/src/system.cpp
@@ -0,0 +1,83 @@
+/*
+// 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 "system.hpp"
+
+#include "mdrv2.hpp"
+
+#include <iomanip>
+#include <iostream>
+#include <sstream>
+namespace phosphor
+{
+namespace smbios
+{
+
+std::string System::uUID(std::string value)
+{
+    uint8_t *dataIn = storage;
+    dataIn = getSMBIOSTypePtr(dataIn, systemType);
+    if (dataIn != nullptr)
+    {
+        auto systemInfo = reinterpret_cast<struct SystemInfo *>(dataIn);
+        std::stringstream stream;
+        stream << std::setfill('0') << std::hex;
+        stream << std::setw(8) << systemInfo->uUID.timeLow;
+        stream << "-";
+        stream << std::setw(4) << systemInfo->uUID.timeMid;
+        stream << "-";
+        stream << std::setw(4) << systemInfo->uUID.timeHiAndVer;
+        stream << "-";
+        stream << std::setw(2) << static_cast<int>(systemInfo->uUID.clockSeqHi);
+        stream << std::setw(2)
+               << static_cast<int>(systemInfo->uUID.clockSeqLow);
+        stream << "-";
+        static_assert(sizeof(systemInfo->uUID.node) == 6);
+        stream << std::setw(2) << static_cast<int>(systemInfo->uUID.node[0]);
+        stream << std::setw(2) << static_cast<int>(systemInfo->uUID.node[1]);
+        stream << std::setw(2) << static_cast<int>(systemInfo->uUID.node[2]);
+        stream << std::setw(2) << static_cast<int>(systemInfo->uUID.node[3]);
+        stream << std::setw(2) << static_cast<int>(systemInfo->uUID.node[4]);
+        stream << std::setw(2) << static_cast<int>(systemInfo->uUID.node[5]);
+
+        return sdbusplus::xyz::openbmc_project::Common::server::UUID::uUID(
+            stream.str());
+    }
+
+    return sdbusplus::xyz::openbmc_project::Common::server::UUID::uUID(
+        "00000000-0000-0000-0000-000000000000");
+}
+
+std::string System::version(std::string value)
+{
+    std::string result = "No BIOS Version";
+    uint8_t *dataIn = storage;
+    dataIn = getSMBIOSTypePtr(dataIn, biosType);
+    if (dataIn != nullptr)
+    {
+        auto biosInfo = reinterpret_cast<struct BIOSInfo *>(dataIn);
+        uint8_t biosVerByte = biosInfo->biosVersion;
+        std::string tempS =
+            positionToString(biosInfo->biosVersion, biosInfo->length, dataIn);
+        result = tempS;
+    }
+
+    return sdbusplus::xyz::openbmc_project::Inventory::Decorator::server::
+        Revision::version(result);
+}
+
+} // namespace smbios
+} // namespace phosphor