summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason M. Bills <jason.m.bills@linux.intel.com>2018-12-19 03:51:18 +0300
committerEd Tanous <ed.tanous@intel.com>2019-07-11 04:26:07 +0300
commitf5c9f8bda365b90c978a95738b66419ad21df27f (patch)
tree7a4f6a1c75a9312323fd099de3d06edfb829430e
parent7052517fd63c5ed8bd16bc5225c4992a23a176f6 (diff)
downloadbmcweb-f5c9f8bda365b90c978a95738b66419ad21df27f.tar.xz
Add Redfish PCIe information
This adds the capability to get PCIe device information from D-Bus and display it in the appropriate Redfish PCIeDevice and PCIeFunction objects. Tested: Passed the Redfish validator for the new PCIeDevice and PCIeFunction objects. Change-Id: I06f3b0e7d283e48d2235b7d34f78f603b22de79f Signed-off-by: Jason M. Bills <jason.m.bills@linux.intel.com>
-rw-r--r--redfish-core/include/redfish.hpp5
-rw-r--r--redfish-core/lib/pcie.hpp345
-rw-r--r--redfish-core/lib/systems.hpp2
3 files changed, 352 insertions, 0 deletions
diff --git a/redfish-core/include/redfish.hpp b/redfish-core/include/redfish.hpp
index 44cc74c0f5..21d6500ffd 100644
--- a/redfish-core/include/redfish.hpp
+++ b/redfish-core/include/redfish.hpp
@@ -24,6 +24,7 @@
#include "../lib/managers.hpp"
#include "../lib/message_registries.hpp"
#include "../lib/network_protocol.hpp"
+#include "../lib/pcie.hpp"
#include "../lib/power.hpp"
#include "../lib/redfish_sessions.hpp"
#include "../lib/roles.hpp"
@@ -132,6 +133,10 @@ class RedfishService
nodes.emplace_back(std::make_unique<HTTPSCertificate>(app));
nodes.emplace_back(std::make_unique<LDAPCertificateCollection>(app));
nodes.emplace_back(std::make_unique<LDAPCertificate>(app));
+
+ nodes.emplace_back(std::make_unique<SystemPCIeFunction>(app));
+ nodes.emplace_back(std::make_unique<SystemPCIeDevice>(app));
+
for (const auto& node : nodes)
{
node->initPrivileges();
diff --git a/redfish-core/lib/pcie.hpp b/redfish-core/lib/pcie.hpp
new file mode 100644
index 0000000000..6b8600f081
--- /dev/null
+++ b/redfish-core/lib/pcie.hpp
@@ -0,0 +1,345 @@
+/*
+// 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 "node.hpp"
+
+#include <boost/system/linux_error.hpp>
+
+namespace redfish
+{
+
+static constexpr char const *pcieService = "xyz.openbmc_project.PCIe";
+static constexpr char const *pciePath = "/xyz/openbmc_project/PCIe";
+static constexpr char const *pcieDeviceInterface =
+ "xyz.openbmc_project.PCIe.Device";
+
+static inline void getPCIeDeviceList(std::shared_ptr<AsyncResp> asyncResp)
+{
+ auto getPCIeMapCallback =
+ [asyncResp](const boost::system::error_code ec,
+ std::vector<std::string> &pcieDevicePaths) {
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG << "failed to get PCIe device paths ec: "
+ << ec.message();
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ nlohmann::json &pcieDeviceList =
+ asyncResp->res.jsonValue["PCIeDevices"];
+ pcieDeviceList = nlohmann::json::array();
+ for (const std::string &pcieDevicePath : pcieDevicePaths)
+ {
+ size_t devStart = pcieDevicePath.rfind("/");
+ if (devStart == std::string::npos)
+ {
+ continue;
+ }
+
+ std::string devName = pcieDevicePath.substr(devStart + 1);
+ if (devName.empty())
+ {
+ continue;
+ }
+ pcieDeviceList.push_back(
+ {{"@odata.id",
+ "/redfish/v1/Systems/system/PCIeDevices/" + devName}});
+ }
+ asyncResp->res.jsonValue["PCIeDevices@odata.count"] =
+ pcieDeviceList.size();
+ };
+ crow::connections::systemBus->async_method_call(
+ std::move(getPCIeMapCallback), "xyz.openbmc_project.ObjectMapper",
+ "/xyz/openbmc_project/object_mapper",
+ "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths",
+ std::string(pciePath) + "/", 1, std::array<std::string, 0>());
+}
+
+class SystemPCIeDevice : public Node
+{
+ public:
+ SystemPCIeDevice(CrowApp &app) :
+ Node(app, "/redfish/v1/Systems/system/PCIeDevices/<str>/",
+ std::string())
+ {
+ entityPrivileges = {
+ {boost::beast::http::verb::get, {{"Login"}}},
+ {boost::beast::http::verb::head, {{"Login"}}},
+ {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
+ {boost::beast::http::verb::put, {{"ConfigureManager"}}},
+ {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
+ {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
+ }
+
+ private:
+ void doGet(crow::Response &res, const crow::Request &req,
+ const std::vector<std::string> &params) override
+ {
+ std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
+ if (params.size() != 1)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ const std::string &device = params[0];
+
+ auto getPCIeDeviceCallback =
+ [asyncResp,
+ device](const boost::system::error_code ec,
+ boost::container::flat_map<
+ std::string, sdbusplus::message::variant<std::string>>
+ &pcieDevProperties) {
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG
+ << "failed to get PCIe Device properties ec: "
+ << static_cast<int>(ec.value()) << ": " << ec.message();
+ if (ec.value() ==
+ boost::system::linux_error::bad_request_descriptor)
+ {
+ messages::resourceNotFound(asyncResp->res, "PCIeDevice",
+ device);
+ }
+ else
+ {
+ messages::internalError(asyncResp->res);
+ }
+ return;
+ }
+
+ asyncResp->res.jsonValue = {
+ {"@odata.type", "#PCIeDevice.v1_2_0.PCIeDevice"},
+ {"@odata.context",
+ "/redfish/v1/$metadata#PCIeDevice.v1_2_0.PCIeDevice"},
+ {"@odata.id",
+ "/redfish/v1/Systems/system/PCIeDevices/" + device},
+ {"Name", "PCIe Device"},
+ {"Id", device}};
+
+ if (std::string *property =
+ sdbusplus::message::variant_ns::get_if<std::string>(
+ &pcieDevProperties["Manufacturer"]);
+ property)
+ {
+ asyncResp->res.jsonValue["Manufacturer"] = *property;
+ }
+
+ if (std::string *property =
+ sdbusplus::message::variant_ns::get_if<std::string>(
+ &pcieDevProperties["DeviceType"]);
+ property)
+ {
+ asyncResp->res.jsonValue["DeviceType"] = *property;
+ }
+
+ nlohmann::json &pcieFunctionList =
+ asyncResp->res.jsonValue["Links"]["PCIeFunctions"];
+ pcieFunctionList = nlohmann::json::array();
+ static constexpr const int maxPciFunctionNum = 8;
+ for (int functionNum = 0; functionNum < maxPciFunctionNum;
+ functionNum++)
+ {
+ // Check if this function exists by looking for a device ID
+ std::string devIDProperty =
+ "Function" + std::to_string(functionNum) + "DeviceId";
+ if (std::string *property =
+ sdbusplus::message::variant_ns::get_if<std::string>(
+ &pcieDevProperties[devIDProperty]);
+ property && !property->empty())
+ {
+ pcieFunctionList.push_back(
+ {{"@odata.id",
+ "/redfish/v1/Systems/system/PCIeDevices/" +
+ device + "/PCIeFunctions/" +
+ std::to_string(functionNum)}});
+ }
+ }
+ asyncResp->res.jsonValue["Links"]["PCIeFunctions@odata.count"] =
+ pcieFunctionList.size();
+ };
+ std::string escapedPath = std::string(pciePath) + "/" + device;
+ dbus::utility::escapePathForDbus(escapedPath);
+ crow::connections::systemBus->async_method_call(
+ std::move(getPCIeDeviceCallback), pcieService, escapedPath,
+ "org.freedesktop.DBus.Properties", "GetAll", pcieDeviceInterface);
+ }
+};
+
+class SystemPCIeFunction : public Node
+{
+ public:
+ SystemPCIeFunction(CrowApp &app) :
+ Node(
+ app,
+ "/redfish/v1/Systems/system/PCIeDevices/<str>/PCIeFunctions/<str>/",
+ std::string(), std::string())
+ {
+ entityPrivileges = {
+ {boost::beast::http::verb::get, {{"Login"}}},
+ {boost::beast::http::verb::head, {{"Login"}}},
+ {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
+ {boost::beast::http::verb::put, {{"ConfigureManager"}}},
+ {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
+ {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
+ }
+
+ private:
+ void doGet(crow::Response &res, const crow::Request &req,
+ const std::vector<std::string> &params) override
+ {
+ std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
+ if (params.size() != 2)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ const std::string &device = params[0];
+ const std::string &function = params[1];
+
+ auto getPCIeDeviceCallback =
+ [asyncResp, device, function](
+ const boost::system::error_code ec,
+ boost::container::flat_map<
+ std::string, sdbusplus::message::variant<std::string>>
+ &pcieDevProperties) {
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG
+ << "failed to get PCIe Device properties ec: "
+ << static_cast<int>(ec.value()) << ": " << ec.message();
+ if (ec.value() ==
+ boost::system::linux_error::bad_request_descriptor)
+ {
+ messages::resourceNotFound(asyncResp->res, "PCIeDevice",
+ device);
+ }
+ else
+ {
+ messages::internalError(asyncResp->res);
+ }
+ return;
+ }
+
+ // Check if this function exists by looking for a device ID
+ std::string devIDProperty = "Function" + function + "DeviceId";
+ if (std::string *property =
+ sdbusplus::message::variant_ns::get_if<std::string>(
+ &pcieDevProperties[devIDProperty]);
+ property && property->empty())
+ {
+ messages::resourceNotFound(asyncResp->res, "PCIeFunction",
+ function);
+ return;
+ }
+
+ asyncResp->res.jsonValue = {
+ {"@odata.type", "#PCIeFunction.v1_2_0.PCIeFunction"},
+ {"@odata.context",
+ "/redfish/v1/$metadata#PCIeFunction.PCIeFunction"},
+ {"@odata.id", "/redfish/v1/Systems/system/PCIeDevices/" +
+ device + "/PCIeFunctions/" + function},
+ {"Name", "PCIe Function"},
+ {"Id", function},
+ {"FunctionId", std::stoi(function)},
+ {"Links",
+ {{"PCIeDevice",
+ {{"@odata.id",
+ "/redfish/v1/Systems/system/PCIeDevices/" +
+ device}}}}}};
+
+ if (std::string *property =
+ sdbusplus::message::variant_ns::get_if<std::string>(
+ &pcieDevProperties["Function" + function +
+ "DeviceId"]);
+ property)
+ {
+ asyncResp->res.jsonValue["DeviceId"] = *property;
+ }
+
+ if (std::string *property =
+ sdbusplus::message::variant_ns::get_if<std::string>(
+ &pcieDevProperties["Function" + function +
+ "VendorId"]);
+ property)
+ {
+ asyncResp->res.jsonValue["VendorId"] = *property;
+ }
+
+ if (std::string *property =
+ sdbusplus::message::variant_ns::get_if<std::string>(
+ &pcieDevProperties["Function" + function +
+ "FunctionType"]);
+ property)
+ {
+ asyncResp->res.jsonValue["FunctionType"] = *property;
+ }
+
+ if (std::string *property =
+ sdbusplus::message::variant_ns::get_if<std::string>(
+ &pcieDevProperties["Function" + function +
+ "DeviceClass"]);
+ property)
+ {
+ asyncResp->res.jsonValue["DeviceClass"] = *property;
+ }
+
+ if (std::string *property =
+ sdbusplus::message::variant_ns::get_if<std::string>(
+ &pcieDevProperties["Function" + function +
+ "ClassCode"]);
+ property)
+ {
+ asyncResp->res.jsonValue["ClassCode"] = *property;
+ }
+
+ if (std::string *property =
+ sdbusplus::message::variant_ns::get_if<std::string>(
+ &pcieDevProperties["Function" + function +
+ "RevisionId"]);
+ property)
+ {
+ asyncResp->res.jsonValue["RevisionId"] = *property;
+ }
+
+ if (std::string *property =
+ sdbusplus::message::variant_ns::get_if<std::string>(
+ &pcieDevProperties["Function" + function +
+ "SubsystemId"]);
+ property)
+ {
+ asyncResp->res.jsonValue["SubsystemId"] = *property;
+ }
+
+ if (std::string *property =
+ sdbusplus::message::variant_ns::get_if<std::string>(
+ &pcieDevProperties["Function" + function +
+ "SubsystemVendorId"]);
+ property)
+ {
+ asyncResp->res.jsonValue["SubsystemVendorId"] = *property;
+ }
+ };
+ std::string escapedPath = std::string(pciePath) + "/" + device;
+ dbus::utility::escapePathForDbus(escapedPath);
+ crow::connections::systemBus->async_method_call(
+ std::move(getPCIeDeviceCallback), pcieService, escapedPath,
+ "org.freedesktop.DBus.Properties", "GetAll", pcieDeviceInterface);
+ }
+};
+
+} // namespace redfish
diff --git a/redfish-core/lib/systems.hpp b/redfish-core/lib/systems.hpp
index e5f47a1bb6..1a94139abf 100644
--- a/redfish-core/lib/systems.hpp
+++ b/redfish-core/lib/systems.hpp
@@ -16,6 +16,7 @@
#pragma once
#include "health.hpp"
+#include "pcie.hpp"
#include "redfish_util.hpp"
#include <boost/container/flat_map.hpp>
@@ -1298,6 +1299,7 @@ class Systems : public Node
getComputerSystem(asyncResp);
getHostState(asyncResp);
getBootProperties(asyncResp);
+ getPCIeDeviceList(asyncResp);
}
void doPatch(crow::Response &res, const crow::Request &req,