xref: /openbmc/bmcweb/features/redfish/lib/pcie.hpp (revision adbe192a68306d403c2546dbc8ebf98ae5a99d7b)
1f5c9f8bdSJason M. Bills /*
2f5c9f8bdSJason M. Bills // Copyright (c) 2018 Intel Corporation
3f5c9f8bdSJason M. Bills //
4f5c9f8bdSJason M. Bills // Licensed under the Apache License, Version 2.0 (the "License");
5f5c9f8bdSJason M. Bills // you may not use this file except in compliance with the License.
6f5c9f8bdSJason M. Bills // You may obtain a copy of the License at
7f5c9f8bdSJason M. Bills //
8f5c9f8bdSJason M. Bills //      http://www.apache.org/licenses/LICENSE-2.0
9f5c9f8bdSJason M. Bills //
10f5c9f8bdSJason M. Bills // Unless required by applicable law or agreed to in writing, software
11f5c9f8bdSJason M. Bills // distributed under the License is distributed on an "AS IS" BASIS,
12f5c9f8bdSJason M. Bills // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f5c9f8bdSJason M. Bills // See the License for the specific language governing permissions and
14f5c9f8bdSJason M. Bills // limitations under the License.
15f5c9f8bdSJason M. Bills */
16f5c9f8bdSJason M. Bills 
17f5c9f8bdSJason M. Bills #pragma once
18f5c9f8bdSJason M. Bills 
19f5c9f8bdSJason M. Bills #include "node.hpp"
20f5c9f8bdSJason M. Bills 
21f5c9f8bdSJason M. Bills #include <boost/system/linux_error.hpp>
22f5c9f8bdSJason M. Bills 
23f5c9f8bdSJason M. Bills namespace redfish
24f5c9f8bdSJason M. Bills {
25f5c9f8bdSJason M. Bills 
26f5c9f8bdSJason M. Bills static constexpr char const *pcieService = "xyz.openbmc_project.PCIe";
27f5c9f8bdSJason M. Bills static constexpr char const *pciePath = "/xyz/openbmc_project/PCIe";
28f5c9f8bdSJason M. Bills static constexpr char const *pcieDeviceInterface =
29f5c9f8bdSJason M. Bills     "xyz.openbmc_project.PCIe.Device";
30f5c9f8bdSJason M. Bills 
31*adbe192aSJason M. Bills static inline void getPCIeDeviceList(std::shared_ptr<AsyncResp> asyncResp,
32*adbe192aSJason M. Bills                                      const std::string &name)
33f5c9f8bdSJason M. Bills {
34*adbe192aSJason M. Bills     auto getPCIeMapCallback = [asyncResp, name](
35*adbe192aSJason M. Bills                                   const boost::system::error_code ec,
36f5c9f8bdSJason M. Bills                                   std::vector<std::string> &pcieDevicePaths) {
37f5c9f8bdSJason M. Bills         if (ec)
38f5c9f8bdSJason M. Bills         {
39a2730f01SAndrew Geissler             BMCWEB_LOG_DEBUG << "no PCIe device paths found ec: "
40f5c9f8bdSJason M. Bills                              << ec.message();
41a2730f01SAndrew Geissler             // Not an error, system just doesn't have PCIe info
42f5c9f8bdSJason M. Bills             return;
43f5c9f8bdSJason M. Bills         }
44*adbe192aSJason M. Bills         nlohmann::json &pcieDeviceList = asyncResp->res.jsonValue[name];
45f5c9f8bdSJason M. Bills         pcieDeviceList = nlohmann::json::array();
46f5c9f8bdSJason M. Bills         for (const std::string &pcieDevicePath : pcieDevicePaths)
47f5c9f8bdSJason M. Bills         {
48f5c9f8bdSJason M. Bills             size_t devStart = pcieDevicePath.rfind("/");
49f5c9f8bdSJason M. Bills             if (devStart == std::string::npos)
50f5c9f8bdSJason M. Bills             {
51f5c9f8bdSJason M. Bills                 continue;
52f5c9f8bdSJason M. Bills             }
53f5c9f8bdSJason M. Bills 
54f5c9f8bdSJason M. Bills             std::string devName = pcieDevicePath.substr(devStart + 1);
55f5c9f8bdSJason M. Bills             if (devName.empty())
56f5c9f8bdSJason M. Bills             {
57f5c9f8bdSJason M. Bills                 continue;
58f5c9f8bdSJason M. Bills             }
59f5c9f8bdSJason M. Bills             pcieDeviceList.push_back(
60f5c9f8bdSJason M. Bills                 {{"@odata.id",
61f5c9f8bdSJason M. Bills                   "/redfish/v1/Systems/system/PCIeDevices/" + devName}});
62f5c9f8bdSJason M. Bills         }
63*adbe192aSJason M. Bills         asyncResp->res.jsonValue[name + "@odata.count"] = pcieDeviceList.size();
64f5c9f8bdSJason M. Bills     };
65f5c9f8bdSJason M. Bills     crow::connections::systemBus->async_method_call(
66f5c9f8bdSJason M. Bills         std::move(getPCIeMapCallback), "xyz.openbmc_project.ObjectMapper",
67f5c9f8bdSJason M. Bills         "/xyz/openbmc_project/object_mapper",
68f5c9f8bdSJason M. Bills         "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths",
69f5c9f8bdSJason M. Bills         std::string(pciePath) + "/", 1, std::array<std::string, 0>());
70f5c9f8bdSJason M. Bills }
71f5c9f8bdSJason M. Bills 
72*adbe192aSJason M. Bills class SystemPCIeDeviceCollection : public Node
73*adbe192aSJason M. Bills {
74*adbe192aSJason M. Bills   public:
75*adbe192aSJason M. Bills     template <typename CrowApp>
76*adbe192aSJason M. Bills     SystemPCIeDeviceCollection(CrowApp &app) :
77*adbe192aSJason M. Bills         Node(app, "/redfish/v1/Systems/system/PCIeDevices/")
78*adbe192aSJason M. Bills     {
79*adbe192aSJason M. Bills         entityPrivileges = {
80*adbe192aSJason M. Bills             {boost::beast::http::verb::get, {{"Login"}}},
81*adbe192aSJason M. Bills             {boost::beast::http::verb::head, {{"Login"}}},
82*adbe192aSJason M. Bills             {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
83*adbe192aSJason M. Bills             {boost::beast::http::verb::put, {{"ConfigureManager"}}},
84*adbe192aSJason M. Bills             {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
85*adbe192aSJason M. Bills             {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
86*adbe192aSJason M. Bills     }
87*adbe192aSJason M. Bills 
88*adbe192aSJason M. Bills   private:
89*adbe192aSJason M. Bills     /**
90*adbe192aSJason M. Bills      * Functions triggers appropriate requests on DBus
91*adbe192aSJason M. Bills      */
92*adbe192aSJason M. Bills     void doGet(crow::Response &res, const crow::Request &req,
93*adbe192aSJason M. Bills                const std::vector<std::string> &params) override
94*adbe192aSJason M. Bills     {
95*adbe192aSJason M. Bills         std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
96*adbe192aSJason M. Bills         asyncResp->res.jsonValue = {
97*adbe192aSJason M. Bills             {"@odata.type", "#PCIeDeviceCollection.PCIeDeviceCollection"},
98*adbe192aSJason M. Bills             {"@odata.context",
99*adbe192aSJason M. Bills              "/redfish/v1/"
100*adbe192aSJason M. Bills              "$metadata#PCIeDeviceCollection.PCIeDeviceCollection"},
101*adbe192aSJason M. Bills             {"@odata.id", "/redfish/v1/Systems/system/PCIeDevices"},
102*adbe192aSJason M. Bills             {"Name", "PCIe Device Collection"},
103*adbe192aSJason M. Bills             {"Description", "Collection of PCIe Devices"},
104*adbe192aSJason M. Bills             {"Members", nlohmann::json::array()},
105*adbe192aSJason M. Bills             {"Members@odata.count", 0}};
106*adbe192aSJason M. Bills         getPCIeDeviceList(asyncResp, "Members");
107*adbe192aSJason M. Bills     }
108*adbe192aSJason M. Bills };
109*adbe192aSJason M. Bills 
110f5c9f8bdSJason M. Bills class SystemPCIeDevice : public Node
111f5c9f8bdSJason M. Bills {
112f5c9f8bdSJason M. Bills   public:
113f5c9f8bdSJason M. Bills     SystemPCIeDevice(CrowApp &app) :
114f5c9f8bdSJason M. Bills         Node(app, "/redfish/v1/Systems/system/PCIeDevices/<str>/",
115f5c9f8bdSJason M. Bills              std::string())
116f5c9f8bdSJason M. Bills     {
117f5c9f8bdSJason M. Bills         entityPrivileges = {
118f5c9f8bdSJason M. Bills             {boost::beast::http::verb::get, {{"Login"}}},
119f5c9f8bdSJason M. Bills             {boost::beast::http::verb::head, {{"Login"}}},
120f5c9f8bdSJason M. Bills             {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
121f5c9f8bdSJason M. Bills             {boost::beast::http::verb::put, {{"ConfigureManager"}}},
122f5c9f8bdSJason M. Bills             {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
123f5c9f8bdSJason M. Bills             {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
124f5c9f8bdSJason M. Bills     }
125f5c9f8bdSJason M. Bills 
126f5c9f8bdSJason M. Bills   private:
127f5c9f8bdSJason M. Bills     void doGet(crow::Response &res, const crow::Request &req,
128f5c9f8bdSJason M. Bills                const std::vector<std::string> &params) override
129f5c9f8bdSJason M. Bills     {
130f5c9f8bdSJason M. Bills         std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
131f5c9f8bdSJason M. Bills         if (params.size() != 1)
132f5c9f8bdSJason M. Bills         {
133f5c9f8bdSJason M. Bills             messages::internalError(asyncResp->res);
134f5c9f8bdSJason M. Bills             return;
135f5c9f8bdSJason M. Bills         }
136f5c9f8bdSJason M. Bills         const std::string &device = params[0];
137f5c9f8bdSJason M. Bills 
138f5c9f8bdSJason M. Bills         auto getPCIeDeviceCallback =
139f5c9f8bdSJason M. Bills             [asyncResp,
140f5c9f8bdSJason M. Bills              device](const boost::system::error_code ec,
141f5c9f8bdSJason M. Bills                      boost::container::flat_map<
142f5c9f8bdSJason M. Bills                          std::string, sdbusplus::message::variant<std::string>>
143f5c9f8bdSJason M. Bills                          &pcieDevProperties) {
144f5c9f8bdSJason M. Bills                 if (ec)
145f5c9f8bdSJason M. Bills                 {
146f5c9f8bdSJason M. Bills                     BMCWEB_LOG_DEBUG
147f5c9f8bdSJason M. Bills                         << "failed to get PCIe Device properties ec: "
148271584abSEd Tanous                         << ec.value() << ": " << ec.message();
149f5c9f8bdSJason M. Bills                     if (ec.value() ==
150f5c9f8bdSJason M. Bills                         boost::system::linux_error::bad_request_descriptor)
151f5c9f8bdSJason M. Bills                     {
152f5c9f8bdSJason M. Bills                         messages::resourceNotFound(asyncResp->res, "PCIeDevice",
153f5c9f8bdSJason M. Bills                                                    device);
154f5c9f8bdSJason M. Bills                     }
155f5c9f8bdSJason M. Bills                     else
156f5c9f8bdSJason M. Bills                     {
157f5c9f8bdSJason M. Bills                         messages::internalError(asyncResp->res);
158f5c9f8bdSJason M. Bills                     }
159f5c9f8bdSJason M. Bills                     return;
160f5c9f8bdSJason M. Bills                 }
161f5c9f8bdSJason M. Bills 
162f5c9f8bdSJason M. Bills                 asyncResp->res.jsonValue = {
163dede6a98SJason M. Bills                     {"@odata.type", "#PCIeDevice.v1_4_0.PCIeDevice"},
164f5c9f8bdSJason M. Bills                     {"@odata.context",
165dede6a98SJason M. Bills                      "/redfish/v1/$metadata#PCIeDevice.v1_4_0.PCIeDevice"},
166f5c9f8bdSJason M. Bills                     {"@odata.id",
167f5c9f8bdSJason M. Bills                      "/redfish/v1/Systems/system/PCIeDevices/" + device},
168f5c9f8bdSJason M. Bills                     {"Name", "PCIe Device"},
169f5c9f8bdSJason M. Bills                     {"Id", device}};
170f5c9f8bdSJason M. Bills 
171f5c9f8bdSJason M. Bills                 if (std::string *property =
172f5c9f8bdSJason M. Bills                         sdbusplus::message::variant_ns::get_if<std::string>(
173f5c9f8bdSJason M. Bills                             &pcieDevProperties["Manufacturer"]);
174f5c9f8bdSJason M. Bills                     property)
175f5c9f8bdSJason M. Bills                 {
176f5c9f8bdSJason M. Bills                     asyncResp->res.jsonValue["Manufacturer"] = *property;
177f5c9f8bdSJason M. Bills                 }
178f5c9f8bdSJason M. Bills 
179f5c9f8bdSJason M. Bills                 if (std::string *property =
180f5c9f8bdSJason M. Bills                         sdbusplus::message::variant_ns::get_if<std::string>(
181f5c9f8bdSJason M. Bills                             &pcieDevProperties["DeviceType"]);
182f5c9f8bdSJason M. Bills                     property)
183f5c9f8bdSJason M. Bills                 {
184f5c9f8bdSJason M. Bills                     asyncResp->res.jsonValue["DeviceType"] = *property;
185f5c9f8bdSJason M. Bills                 }
186f5c9f8bdSJason M. Bills 
187dede6a98SJason M. Bills                 asyncResp->res.jsonValue["PCIeFunctions"] = {
188dede6a98SJason M. Bills                     {"@odata.id", "/redfish/v1/Systems/system/PCIeDevices/" +
189dede6a98SJason M. Bills                                       device + "/PCIeFunctions"}};
190dede6a98SJason M. Bills             };
191dede6a98SJason M. Bills         std::string escapedPath = std::string(pciePath) + "/" + device;
192dede6a98SJason M. Bills         dbus::utility::escapePathForDbus(escapedPath);
193dede6a98SJason M. Bills         crow::connections::systemBus->async_method_call(
194dede6a98SJason M. Bills             std::move(getPCIeDeviceCallback), pcieService, escapedPath,
195dede6a98SJason M. Bills             "org.freedesktop.DBus.Properties", "GetAll", pcieDeviceInterface);
196dede6a98SJason M. Bills     }
197dede6a98SJason M. Bills };
198dede6a98SJason M. Bills 
199dede6a98SJason M. Bills class SystemPCIeFunctionCollection : public Node
200dede6a98SJason M. Bills {
201dede6a98SJason M. Bills   public:
202dede6a98SJason M. Bills     template <typename CrowApp>
203dede6a98SJason M. Bills     SystemPCIeFunctionCollection(CrowApp &app) :
204dede6a98SJason M. Bills         Node(app, "/redfish/v1/Systems/system/PCIeDevices/<str>/PCIeFunctions/",
205dede6a98SJason M. Bills              std::string())
206dede6a98SJason M. Bills     {
207dede6a98SJason M. Bills         entityPrivileges = {
208dede6a98SJason M. Bills             {boost::beast::http::verb::get, {{"Login"}}},
209dede6a98SJason M. Bills             {boost::beast::http::verb::head, {{"Login"}}},
210dede6a98SJason M. Bills             {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
211dede6a98SJason M. Bills             {boost::beast::http::verb::put, {{"ConfigureManager"}}},
212dede6a98SJason M. Bills             {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
213dede6a98SJason M. Bills             {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
214dede6a98SJason M. Bills     }
215dede6a98SJason M. Bills 
216dede6a98SJason M. Bills   private:
217dede6a98SJason M. Bills     /**
218dede6a98SJason M. Bills      * Functions triggers appropriate requests on DBus
219dede6a98SJason M. Bills      */
220dede6a98SJason M. Bills     void doGet(crow::Response &res, const crow::Request &req,
221dede6a98SJason M. Bills                const std::vector<std::string> &params) override
222dede6a98SJason M. Bills     {
223dede6a98SJason M. Bills         std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
224dede6a98SJason M. Bills         if (params.size() != 1)
225dede6a98SJason M. Bills         {
226dede6a98SJason M. Bills             messages::internalError(asyncResp->res);
227dede6a98SJason M. Bills             return;
228dede6a98SJason M. Bills         }
229dede6a98SJason M. Bills         const std::string &device = params[0];
230dede6a98SJason M. Bills         asyncResp->res.jsonValue = {
231dede6a98SJason M. Bills             {"@odata.type", "#PCIeFunctionCollection.PCIeFunctionCollection"},
232dede6a98SJason M. Bills             {"@odata.context",
233dede6a98SJason M. Bills              "/redfish/v1/"
234dede6a98SJason M. Bills              "$metadata#PCIeFunctionCollection.PCIeFunctionCollection"},
235dede6a98SJason M. Bills             {"@odata.id", "/redfish/v1/Systems/system/PCIeDevices/" + device +
236dede6a98SJason M. Bills                               "/PCIeFunctions"},
237dede6a98SJason M. Bills             {"Name", "PCIe Function Collection"},
238dede6a98SJason M. Bills             {"Description",
239dede6a98SJason M. Bills              "Collection of PCIe Functions for PCIe Device " + device}};
240dede6a98SJason M. Bills 
241dede6a98SJason M. Bills         auto getPCIeDeviceCallback =
242dede6a98SJason M. Bills             [asyncResp,
243dede6a98SJason M. Bills              device](const boost::system::error_code ec,
244dede6a98SJason M. Bills                      boost::container::flat_map<
245dede6a98SJason M. Bills                          std::string, sdbusplus::message::variant<std::string>>
246dede6a98SJason M. Bills                          &pcieDevProperties) {
247dede6a98SJason M. Bills                 if (ec)
248dede6a98SJason M. Bills                 {
249dede6a98SJason M. Bills                     BMCWEB_LOG_DEBUG
250dede6a98SJason M. Bills                         << "failed to get PCIe Device properties ec: "
251dede6a98SJason M. Bills                         << ec.value() << ": " << ec.message();
252dede6a98SJason M. Bills                     if (ec.value() ==
253dede6a98SJason M. Bills                         boost::system::linux_error::bad_request_descriptor)
254dede6a98SJason M. Bills                     {
255dede6a98SJason M. Bills                         messages::resourceNotFound(asyncResp->res, "PCIeDevice",
256dede6a98SJason M. Bills                                                    device);
257dede6a98SJason M. Bills                     }
258dede6a98SJason M. Bills                     else
259dede6a98SJason M. Bills                     {
260dede6a98SJason M. Bills                         messages::internalError(asyncResp->res);
261dede6a98SJason M. Bills                     }
262dede6a98SJason M. Bills                     return;
263dede6a98SJason M. Bills                 }
264dede6a98SJason M. Bills 
265f5c9f8bdSJason M. Bills                 nlohmann::json &pcieFunctionList =
266dede6a98SJason M. Bills                     asyncResp->res.jsonValue["Members"];
267f5c9f8bdSJason M. Bills                 pcieFunctionList = nlohmann::json::array();
268f5c9f8bdSJason M. Bills                 static constexpr const int maxPciFunctionNum = 8;
269f5c9f8bdSJason M. Bills                 for (int functionNum = 0; functionNum < maxPciFunctionNum;
270f5c9f8bdSJason M. Bills                      functionNum++)
271f5c9f8bdSJason M. Bills                 {
272f5c9f8bdSJason M. Bills                     // Check if this function exists by looking for a device ID
273f5c9f8bdSJason M. Bills                     std::string devIDProperty =
274f5c9f8bdSJason M. Bills                         "Function" + std::to_string(functionNum) + "DeviceId";
275dede6a98SJason M. Bills                     std::string *property =
276f5c9f8bdSJason M. Bills                         sdbusplus::message::variant_ns::get_if<std::string>(
277f5c9f8bdSJason M. Bills                             &pcieDevProperties[devIDProperty]);
278dede6a98SJason M. Bills                     if (property && !property->empty())
279f5c9f8bdSJason M. Bills                     {
280f5c9f8bdSJason M. Bills                         pcieFunctionList.push_back(
281f5c9f8bdSJason M. Bills                             {{"@odata.id",
282f5c9f8bdSJason M. Bills                               "/redfish/v1/Systems/system/PCIeDevices/" +
283f5c9f8bdSJason M. Bills                                   device + "/PCIeFunctions/" +
284f5c9f8bdSJason M. Bills                                   std::to_string(functionNum)}});
285f5c9f8bdSJason M. Bills                     }
286f5c9f8bdSJason M. Bills                 }
287dede6a98SJason M. Bills                 asyncResp->res.jsonValue["PCIeFunctions@odata.count"] =
288f5c9f8bdSJason M. Bills                     pcieFunctionList.size();
289f5c9f8bdSJason M. Bills             };
290f5c9f8bdSJason M. Bills         std::string escapedPath = std::string(pciePath) + "/" + device;
291f5c9f8bdSJason M. Bills         dbus::utility::escapePathForDbus(escapedPath);
292f5c9f8bdSJason M. Bills         crow::connections::systemBus->async_method_call(
293f5c9f8bdSJason M. Bills             std::move(getPCIeDeviceCallback), pcieService, escapedPath,
294f5c9f8bdSJason M. Bills             "org.freedesktop.DBus.Properties", "GetAll", pcieDeviceInterface);
295f5c9f8bdSJason M. Bills     }
296f5c9f8bdSJason M. Bills };
297f5c9f8bdSJason M. Bills 
298f5c9f8bdSJason M. Bills class SystemPCIeFunction : public Node
299f5c9f8bdSJason M. Bills {
300f5c9f8bdSJason M. Bills   public:
301f5c9f8bdSJason M. Bills     SystemPCIeFunction(CrowApp &app) :
302f5c9f8bdSJason M. Bills         Node(
303f5c9f8bdSJason M. Bills             app,
304f5c9f8bdSJason M. Bills             "/redfish/v1/Systems/system/PCIeDevices/<str>/PCIeFunctions/<str>/",
305f5c9f8bdSJason M. Bills             std::string(), std::string())
306f5c9f8bdSJason M. Bills     {
307f5c9f8bdSJason M. Bills         entityPrivileges = {
308f5c9f8bdSJason M. Bills             {boost::beast::http::verb::get, {{"Login"}}},
309f5c9f8bdSJason M. Bills             {boost::beast::http::verb::head, {{"Login"}}},
310f5c9f8bdSJason M. Bills             {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
311f5c9f8bdSJason M. Bills             {boost::beast::http::verb::put, {{"ConfigureManager"}}},
312f5c9f8bdSJason M. Bills             {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
313f5c9f8bdSJason M. Bills             {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
314f5c9f8bdSJason M. Bills     }
315f5c9f8bdSJason M. Bills 
316f5c9f8bdSJason M. Bills   private:
317f5c9f8bdSJason M. Bills     void doGet(crow::Response &res, const crow::Request &req,
318f5c9f8bdSJason M. Bills                const std::vector<std::string> &params) override
319f5c9f8bdSJason M. Bills     {
320f5c9f8bdSJason M. Bills         std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
321f5c9f8bdSJason M. Bills         if (params.size() != 2)
322f5c9f8bdSJason M. Bills         {
323f5c9f8bdSJason M. Bills             messages::internalError(asyncResp->res);
324f5c9f8bdSJason M. Bills             return;
325f5c9f8bdSJason M. Bills         }
326f5c9f8bdSJason M. Bills         const std::string &device = params[0];
327f5c9f8bdSJason M. Bills         const std::string &function = params[1];
328f5c9f8bdSJason M. Bills 
329f5c9f8bdSJason M. Bills         auto getPCIeDeviceCallback =
330f5c9f8bdSJason M. Bills             [asyncResp, device, function](
331f5c9f8bdSJason M. Bills                 const boost::system::error_code ec,
332f5c9f8bdSJason M. Bills                 boost::container::flat_map<
333f5c9f8bdSJason M. Bills                     std::string, sdbusplus::message::variant<std::string>>
334f5c9f8bdSJason M. Bills                     &pcieDevProperties) {
335f5c9f8bdSJason M. Bills                 if (ec)
336f5c9f8bdSJason M. Bills                 {
337f5c9f8bdSJason M. Bills                     BMCWEB_LOG_DEBUG
338f5c9f8bdSJason M. Bills                         << "failed to get PCIe Device properties ec: "
339271584abSEd Tanous                         << ec.value() << ": " << ec.message();
340f5c9f8bdSJason M. Bills                     if (ec.value() ==
341f5c9f8bdSJason M. Bills                         boost::system::linux_error::bad_request_descriptor)
342f5c9f8bdSJason M. Bills                     {
343f5c9f8bdSJason M. Bills                         messages::resourceNotFound(asyncResp->res, "PCIeDevice",
344f5c9f8bdSJason M. Bills                                                    device);
345f5c9f8bdSJason M. Bills                     }
346f5c9f8bdSJason M. Bills                     else
347f5c9f8bdSJason M. Bills                     {
348f5c9f8bdSJason M. Bills                         messages::internalError(asyncResp->res);
349f5c9f8bdSJason M. Bills                     }
350f5c9f8bdSJason M. Bills                     return;
351f5c9f8bdSJason M. Bills                 }
352f5c9f8bdSJason M. Bills 
353f5c9f8bdSJason M. Bills                 // Check if this function exists by looking for a device ID
354f5c9f8bdSJason M. Bills                 std::string devIDProperty = "Function" + function + "DeviceId";
355f5c9f8bdSJason M. Bills                 if (std::string *property =
356f5c9f8bdSJason M. Bills                         sdbusplus::message::variant_ns::get_if<std::string>(
357f5c9f8bdSJason M. Bills                             &pcieDevProperties[devIDProperty]);
358f5c9f8bdSJason M. Bills                     property && property->empty())
359f5c9f8bdSJason M. Bills                 {
360f5c9f8bdSJason M. Bills                     messages::resourceNotFound(asyncResp->res, "PCIeFunction",
361f5c9f8bdSJason M. Bills                                                function);
362f5c9f8bdSJason M. Bills                     return;
363f5c9f8bdSJason M. Bills                 }
364f5c9f8bdSJason M. Bills 
365f5c9f8bdSJason M. Bills                 asyncResp->res.jsonValue = {
366f5c9f8bdSJason M. Bills                     {"@odata.type", "#PCIeFunction.v1_2_0.PCIeFunction"},
367f5c9f8bdSJason M. Bills                     {"@odata.context",
368f5c9f8bdSJason M. Bills                      "/redfish/v1/$metadata#PCIeFunction.PCIeFunction"},
369f5c9f8bdSJason M. Bills                     {"@odata.id", "/redfish/v1/Systems/system/PCIeDevices/" +
370f5c9f8bdSJason M. Bills                                       device + "/PCIeFunctions/" + function},
371f5c9f8bdSJason M. Bills                     {"Name", "PCIe Function"},
372f5c9f8bdSJason M. Bills                     {"Id", function},
373f5c9f8bdSJason M. Bills                     {"FunctionId", std::stoi(function)},
374f5c9f8bdSJason M. Bills                     {"Links",
375f5c9f8bdSJason M. Bills                      {{"PCIeDevice",
376f5c9f8bdSJason M. Bills                        {{"@odata.id",
377f5c9f8bdSJason M. Bills                          "/redfish/v1/Systems/system/PCIeDevices/" +
378f5c9f8bdSJason M. Bills                              device}}}}}};
379f5c9f8bdSJason M. Bills 
380f5c9f8bdSJason M. Bills                 if (std::string *property =
381f5c9f8bdSJason M. Bills                         sdbusplus::message::variant_ns::get_if<std::string>(
382f5c9f8bdSJason M. Bills                             &pcieDevProperties["Function" + function +
383f5c9f8bdSJason M. Bills                                                "DeviceId"]);
384f5c9f8bdSJason M. Bills                     property)
385f5c9f8bdSJason M. Bills                 {
386f5c9f8bdSJason M. Bills                     asyncResp->res.jsonValue["DeviceId"] = *property;
387f5c9f8bdSJason M. Bills                 }
388f5c9f8bdSJason M. Bills 
389f5c9f8bdSJason M. Bills                 if (std::string *property =
390f5c9f8bdSJason M. Bills                         sdbusplus::message::variant_ns::get_if<std::string>(
391f5c9f8bdSJason M. Bills                             &pcieDevProperties["Function" + function +
392f5c9f8bdSJason M. Bills                                                "VendorId"]);
393f5c9f8bdSJason M. Bills                     property)
394f5c9f8bdSJason M. Bills                 {
395f5c9f8bdSJason M. Bills                     asyncResp->res.jsonValue["VendorId"] = *property;
396f5c9f8bdSJason M. Bills                 }
397f5c9f8bdSJason M. Bills 
398f5c9f8bdSJason M. Bills                 if (std::string *property =
399f5c9f8bdSJason M. Bills                         sdbusplus::message::variant_ns::get_if<std::string>(
400f5c9f8bdSJason M. Bills                             &pcieDevProperties["Function" + function +
401f5c9f8bdSJason M. Bills                                                "FunctionType"]);
402f5c9f8bdSJason M. Bills                     property)
403f5c9f8bdSJason M. Bills                 {
404f5c9f8bdSJason M. Bills                     asyncResp->res.jsonValue["FunctionType"] = *property;
405f5c9f8bdSJason M. Bills                 }
406f5c9f8bdSJason M. Bills 
407f5c9f8bdSJason M. Bills                 if (std::string *property =
408f5c9f8bdSJason M. Bills                         sdbusplus::message::variant_ns::get_if<std::string>(
409f5c9f8bdSJason M. Bills                             &pcieDevProperties["Function" + function +
410f5c9f8bdSJason M. Bills                                                "DeviceClass"]);
411f5c9f8bdSJason M. Bills                     property)
412f5c9f8bdSJason M. Bills                 {
413f5c9f8bdSJason M. Bills                     asyncResp->res.jsonValue["DeviceClass"] = *property;
414f5c9f8bdSJason M. Bills                 }
415f5c9f8bdSJason M. Bills 
416f5c9f8bdSJason M. Bills                 if (std::string *property =
417f5c9f8bdSJason M. Bills                         sdbusplus::message::variant_ns::get_if<std::string>(
418f5c9f8bdSJason M. Bills                             &pcieDevProperties["Function" + function +
419f5c9f8bdSJason M. Bills                                                "ClassCode"]);
420f5c9f8bdSJason M. Bills                     property)
421f5c9f8bdSJason M. Bills                 {
422f5c9f8bdSJason M. Bills                     asyncResp->res.jsonValue["ClassCode"] = *property;
423f5c9f8bdSJason M. Bills                 }
424f5c9f8bdSJason M. Bills 
425f5c9f8bdSJason M. Bills                 if (std::string *property =
426f5c9f8bdSJason M. Bills                         sdbusplus::message::variant_ns::get_if<std::string>(
427f5c9f8bdSJason M. Bills                             &pcieDevProperties["Function" + function +
428f5c9f8bdSJason M. Bills                                                "RevisionId"]);
429f5c9f8bdSJason M. Bills                     property)
430f5c9f8bdSJason M. Bills                 {
431f5c9f8bdSJason M. Bills                     asyncResp->res.jsonValue["RevisionId"] = *property;
432f5c9f8bdSJason M. Bills                 }
433f5c9f8bdSJason M. Bills 
434f5c9f8bdSJason M. Bills                 if (std::string *property =
435f5c9f8bdSJason M. Bills                         sdbusplus::message::variant_ns::get_if<std::string>(
436f5c9f8bdSJason M. Bills                             &pcieDevProperties["Function" + function +
437f5c9f8bdSJason M. Bills                                                "SubsystemId"]);
438f5c9f8bdSJason M. Bills                     property)
439f5c9f8bdSJason M. Bills                 {
440f5c9f8bdSJason M. Bills                     asyncResp->res.jsonValue["SubsystemId"] = *property;
441f5c9f8bdSJason M. Bills                 }
442f5c9f8bdSJason M. Bills 
443f5c9f8bdSJason M. Bills                 if (std::string *property =
444f5c9f8bdSJason M. Bills                         sdbusplus::message::variant_ns::get_if<std::string>(
445f5c9f8bdSJason M. Bills                             &pcieDevProperties["Function" + function +
446f5c9f8bdSJason M. Bills                                                "SubsystemVendorId"]);
447f5c9f8bdSJason M. Bills                     property)
448f5c9f8bdSJason M. Bills                 {
449f5c9f8bdSJason M. Bills                     asyncResp->res.jsonValue["SubsystemVendorId"] = *property;
450f5c9f8bdSJason M. Bills                 }
451f5c9f8bdSJason M. Bills             };
452f5c9f8bdSJason M. Bills         std::string escapedPath = std::string(pciePath) + "/" + device;
453f5c9f8bdSJason M. Bills         dbus::utility::escapePathForDbus(escapedPath);
454f5c9f8bdSJason M. Bills         crow::connections::systemBus->async_method_call(
455f5c9f8bdSJason M. Bills             std::move(getPCIeDeviceCallback), pcieService, escapedPath,
456f5c9f8bdSJason M. Bills             "org.freedesktop.DBus.Properties", "GetAll", pcieDeviceInterface);
457f5c9f8bdSJason M. Bills     }
458f5c9f8bdSJason M. Bills };
459f5c9f8bdSJason M. Bills 
460f5c9f8bdSJason M. Bills } // namespace redfish
461