Redfish: Added OCP mandatory properties

- Manager: Added SerialConsole, Links/ManagerForChassis and Links/ManagerForChassis@odata.count
- System: Added Links/Chassis, Links/ManagedBy, Status, BiosVersion
- Power: Added placeholder for PowerControl

Tested:
GET /redfish/v1/Systems/system HTTP/1.1
Response:
{
    "@odata.context": "/redfish/v1/$metadata#ComputerSystem.ComputerSystem",
    "@odata.id": "/redfish/v1/Systems/system",
    "@odata.type": "#ComputerSystem.v1_6_0.ComputerSystem",
    ......
    "BiosVersion": "SE5C620.86B.01.00.0361.120520162351",
    ......
    "Description": "Computer System",
    "Id": "system",
    "IndicatorLED": "Off",
    "Links": {
        "Chassis": [
            {
                "@odata.id": "/redfish/v1/Chassis/R1000_Chassis"
            }
        ],
        "ManagedBy": [
            {
                "@odata.id": "/redfish/v1/Managers/bmc"
            }
        ]
    },
    ......

    "Processors": {
        "@odata.id": "/redfish/v1/Systems/system/Processors"
    },
    "Status": {
        "Health": "OK",
        "State": "Enabled"
    },
    "SystemType": "Physical",
    "UUID": "13876882-7708-4200-bcf2-2c5681218bc8"
}

GET /redfish/v1/Managers/bmc HTTP/1.1
Response:
{
    "@odata.context": "/redfish/v1/$metadata#Manager.Manager",
    "@odata.id": "/redfish/v1/Managers/bmc",
    "@odata.type": "#Manager.v1_3_0.Manager",
    ......
    "Description": "Baseboard Management Controller",
    "Linkn"fces": {
        "@odata.id": "/redfish/v1/Managers/bmc/EthernetInterfaces"
    },
    "FirmwareVersion": "2.7.0-dev-266-g111d297-d14e857",
    "Id": "bmc",
    Links: {
        "ManagerForChassis": [
            {
                "@odata.id": "/redfish/v1/Chassis/R1000_Chassis"
            }
        ],
        "ManagerForChassis@odata.count": 1,
        "ManagerForServers": [
            {
                "@odata.id": "/redfish/v1/Systems/system"
            }
        ],
        "ManagerForServers@odata.count": 1
    },
    ......

    "SerialConsole": {
        "ConnectTypesSupported": [
            "IPMI",
            "SSH"
        ],
        "ServiceEnabled": true
    },
    "Status": {
        "Health": "OK",
        "State": "Enabled"
    },
    "UUID": "067b4e8d-6c29-475c-92a1-6590d4e5818c"
}

GET /redfish/v1/Chassis/R1000_Chassis/Power HTTP/1.1
Response:
{
    "@odata.context": "/redfish/v1/$metadata#Power.Power",
    "@odata.id": "/redfish/v1/Chassis/R1000_Chassis/Power",
    "@odata.type": "#Power.v1_2_1.Power",
    "Id": "Power",
    "Name": "Power",
    "PowerControl": []
}

Signed-off-by: Jennifer Lee <jennifer1.lee@intel.com>
Change-Id: I61d8ba493ad689d7062e1f8bfd26d9a0d80230da
diff --git a/redfish-core/lib/managers.hpp b/redfish-core/lib/managers.hpp
index 176c67f..6d3cc92 100644
--- a/redfish-core/lib/managers.hpp
+++ b/redfish-core/lib/managers.hpp
@@ -16,6 +16,7 @@
 #pragma once
 
 #include "node.hpp"
+#include "redfish_util.hpp"
 
 #include <boost/algorithm/string/replace.hpp>
 #include <boost/date_time.hpp>
@@ -1566,6 +1567,13 @@
             "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
         auto pids = std::make_shared<GetPIDValues>(asyncResp);
         pids->run();
+
+        getMainChassisId(asyncResp, [](const std::string& chassisId,
+                                       const std::shared_ptr<AsyncResp> aRsp) {
+            aRsp->res.jsonValue["Links"]["ManagerForChassis@odata.count"] = 1;
+            aRsp->res.jsonValue["Links"]["ManagerForChassis"] = {
+                {{"@odata.id", "/redfish/v1/Chassis/" + chassisId}}};
+        });
     }
 
     void doPatch(crow::Response& res, const crow::Request& req,
diff --git a/redfish-core/lib/power.hpp b/redfish-core/lib/power.hpp
index b5951d5..07b4b38 100644
--- a/redfish-core/lib/power.hpp
+++ b/redfish-core/lib/power.hpp
@@ -52,6 +52,8 @@
         }
         const std::string& chassis_name = params[0];
 
+        res.jsonValue["PowerControl"] = nlohmann::json::array();
+
         auto sensorAsyncResp = std::make_shared<SensorsAsyncResp>(
             res, chassis_name, typeList, "Power");
 
diff --git a/redfish-core/lib/redfish_util.hpp b/redfish-core/lib/redfish_util.hpp
new file mode 100644
index 0000000..0c874e6
--- /dev/null
+++ b/redfish-core/lib/redfish_util.hpp
@@ -0,0 +1,64 @@
+/*
+// Copyright (c) 2019 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.
+*/
+#ifndef BMCWEB_ENABLE_REDFISH_ONE_CHASSIS
+#pragma once
+
+#include <node.hpp>
+
+namespace redfish
+{
+
+template <typename CallbackFunc>
+void getMainChassisId(std::shared_ptr<AsyncResp> asyncResp,
+                      CallbackFunc&& callback)
+{
+    // Find managed chassis
+    crow::connections::systemBus->async_method_call(
+        [callback,
+         asyncResp](const boost::system::error_code ec,
+                    const crow::openbmc_mapper::GetSubTreeType& subtree) {
+            if (ec)
+            {
+                BMCWEB_LOG_ERROR << ec;
+                return;
+            }
+            if (subtree.size() == 0)
+            {
+                BMCWEB_LOG_DEBUG << "Can't find chassis!";
+                return;
+            }
+
+            std::size_t idPos = subtree[0].first.rfind("/");
+            if (idPos == std::string::npos ||
+                (idPos + 1) >= subtree[0].first.size())
+            {
+                messages::internalError(asyncResp->res);
+                BMCWEB_LOG_DEBUG << "Can't parse chassis ID!";
+                return;
+            }
+            std::string chassisId = subtree[0].first.substr(idPos + 1);
+            BMCWEB_LOG_DEBUG << "chassisId = " << chassisId;
+            callback(chassisId, asyncResp);
+        },
+        "xyz.openbmc_project.ObjectMapper",
+        "/xyz/openbmc_project/object_mapper",
+        "xyz.openbmc_project.ObjectMapper", "GetSubTree",
+        "/xyz/openbmc_project/inventory", 0,
+        std::array<const char*, 1>{
+            "xyz.openbmc_project.Inventory.Item.Chassis"});
+}
+} // namespace redfish
+#endif
diff --git a/redfish-core/lib/systems.hpp b/redfish-core/lib/systems.hpp
index ae682c8..fc13803 100644
--- a/redfish-core/lib/systems.hpp
+++ b/redfish-core/lib/systems.hpp
@@ -15,6 +15,8 @@
 */
 #pragma once
 
+#include "redfish_util.hpp"
+
 #include <boost/container/flat_map.hpp>
 #include <node.hpp>
 #include <utils/fw_utils.hpp>
@@ -36,7 +38,7 @@
 {
     BMCWEB_LOG_DEBUG << "Get available system components.";
     crow::connections::systemBus->async_method_call(
-        [aResp{std::move(aResp)}](
+        [aResp](
             const boost::system::error_code ec,
             const std::vector<std::pair<
                 std::string,
@@ -306,7 +308,7 @@
 {
     BMCWEB_LOG_DEBUG << "Get led groups";
     crow::connections::systemBus->async_method_call(
-        [aResp{std::move(aResp)},
+        [aResp,
          callback{std::move(callback)}](const boost::system::error_code &ec,
                                         const ManagedObjectsType &resp) {
             if (ec)
@@ -405,7 +407,6 @@
         "org.freedesktop.DBus.Properties", "GetAll",
         "xyz.openbmc_project.Led.Physical");
 }
-
 /**
  * @brief Retrieves host state properties over dbus
  *
@@ -417,8 +418,8 @@
 {
     BMCWEB_LOG_DEBUG << "Get host information.";
     crow::connections::systemBus->async_method_call(
-        [aResp{std::move(aResp)}](const boost::system::error_code ec,
-                                  const std::variant<std::string> &hostState) {
+        [aResp](const boost::system::error_code ec,
+                const std::variant<std::string> &hostState) {
             if (ec)
             {
                 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
@@ -708,9 +709,8 @@
     BMCWEB_LOG_DEBUG << "Get boot information.";
 
     crow::connections::systemBus->async_method_call(
-        [aResp{std::move(aResp)}](
-            const boost::system::error_code ec,
-            const sdbusplus::message::variant<bool> &oneTime) {
+        [aResp](const boost::system::error_code ec,
+                const sdbusplus::message::variant<bool> &oneTime) {
             if (ec)
             {
                 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
@@ -1182,28 +1182,60 @@
         res.jsonValue["LogServices"] = {
             {"@odata.id", "/redfish/v1/Systems/system/LogServices"}};
 
+        res.jsonValue["Links"]["ManagedBy"] = {
+            {{"@odata.id", "/redfish/v1/Managers/bmc"}}};
+
+        res.jsonValue["Status"] = {
+            {"Health", "OK"},
+            {"State", "Enabled"},
+        };
         auto asyncResp = std::make_shared<AsyncResp>(res);
 
+        crow::connections::systemBus->async_method_call(
+            [asyncResp](const boost::system::error_code ec,
+                        const VariantType &biosId) {
+                if (ec)
+                {
+                    BMCWEB_LOG_ERROR << ec;
+                    messages::internalError(asyncResp->res);
+                    return;
+                }
+                const std::string *strBiosId =
+                    std::get_if<std::string>(&biosId);
+                if (strBiosId != nullptr)
+                {
+                    BMCWEB_LOG_DEBUG << "bios ver. = " << strBiosId;
+                    asyncResp->res.jsonValue["BiosVersion"] = *strBiosId;
+                }
+            },
+            "xyz.openbmc_project.Settings", "/xyz/openbmc_project/bios",
+            "org.freedesktop.DBus.Properties", "Get",
+            "xyz.openbmc_project.Inventory.Item.Bios", "BiosId");
+
+        getMainChassisId(asyncResp, [](const std::string &chassisId,
+                                       std::shared_ptr<AsyncResp> aRsp) {
+            aRsp->res.jsonValue["Links"]["Chassis"] = {
+                {{"@odata.id", "/redfish/v1/Chassis/" + chassisId}}};
+        });
         getLedGroupIdentify(
             asyncResp,
-            [&](const bool &asserted, const std::shared_ptr<AsyncResp> &aResp) {
+            [](const bool &asserted, const std::shared_ptr<AsyncResp> aRsp) {
                 if (asserted)
                 {
                     // If led group is asserted, then another call is needed to
                     // get led status
                     getLedIdentify(
-                        aResp, [](const std::string &ledStatus,
-                                  const std::shared_ptr<AsyncResp> &aResp) {
+                        aRsp, [](const std::string &ledStatus,
+                                 const std::shared_ptr<AsyncResp> aRsp) {
                             if (!ledStatus.empty())
                             {
-                                aResp->res.jsonValue["IndicatorLED"] =
-                                    ledStatus;
+                                aRsp->res.jsonValue["IndicatorLED"] = ledStatus;
                             }
                         });
                 }
                 else
                 {
-                    aResp->res.jsonValue["IndicatorLED"] = "Off";
+                    aRsp->res.jsonValue["IndicatorLED"] = "Off";
                 }
             });
         getComputerSystem(asyncResp);