xref: /openbmc/bmcweb/features/redfish/lib/pcie.hpp (revision 8d78b7a9f5fbca338a5867d5dd4fa83890d79bc7)
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 
31adbe192aSJason M. Bills static inline void getPCIeDeviceList(std::shared_ptr<AsyncResp> asyncResp,
32adbe192aSJason M. Bills                                      const std::string &name)
33f5c9f8bdSJason M. Bills {
34adbe192aSJason M. Bills     auto getPCIeMapCallback = [asyncResp, name](
35adbe192aSJason 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         }
44adbe192aSJason 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         }
63adbe192aSJason 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 
72adbe192aSJason M. Bills class SystemPCIeDeviceCollection : public Node
73adbe192aSJason M. Bills {
74adbe192aSJason M. Bills   public:
75adbe192aSJason M. Bills     template <typename CrowApp>
76adbe192aSJason M. Bills     SystemPCIeDeviceCollection(CrowApp &app) :
77adbe192aSJason M. Bills         Node(app, "/redfish/v1/Systems/system/PCIeDevices/")
78adbe192aSJason M. Bills     {
79adbe192aSJason M. Bills         entityPrivileges = {
80adbe192aSJason M. Bills             {boost::beast::http::verb::get, {{"Login"}}},
81adbe192aSJason M. Bills             {boost::beast::http::verb::head, {{"Login"}}},
82adbe192aSJason M. Bills             {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
83adbe192aSJason M. Bills             {boost::beast::http::verb::put, {{"ConfigureManager"}}},
84adbe192aSJason M. Bills             {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
85adbe192aSJason M. Bills             {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
86adbe192aSJason M. Bills     }
87adbe192aSJason M. Bills 
88adbe192aSJason M. Bills   private:
89adbe192aSJason M. Bills     /**
90adbe192aSJason M. Bills      * Functions triggers appropriate requests on DBus
91adbe192aSJason M. Bills      */
92adbe192aSJason M. Bills     void doGet(crow::Response &res, const crow::Request &req,
93adbe192aSJason M. Bills                const std::vector<std::string> &params) override
94adbe192aSJason M. Bills     {
95adbe192aSJason M. Bills         std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
96adbe192aSJason M. Bills         asyncResp->res.jsonValue = {
97adbe192aSJason M. Bills             {"@odata.type", "#PCIeDeviceCollection.PCIeDeviceCollection"},
98adbe192aSJason M. Bills             {"@odata.id", "/redfish/v1/Systems/system/PCIeDevices"},
99adbe192aSJason M. Bills             {"Name", "PCIe Device Collection"},
100adbe192aSJason M. Bills             {"Description", "Collection of PCIe Devices"},
101adbe192aSJason M. Bills             {"Members", nlohmann::json::array()},
102adbe192aSJason M. Bills             {"Members@odata.count", 0}};
103adbe192aSJason M. Bills         getPCIeDeviceList(asyncResp, "Members");
104adbe192aSJason M. Bills     }
105adbe192aSJason M. Bills };
106adbe192aSJason M. Bills 
107f5c9f8bdSJason M. Bills class SystemPCIeDevice : public Node
108f5c9f8bdSJason M. Bills {
109f5c9f8bdSJason M. Bills   public:
110f5c9f8bdSJason M. Bills     SystemPCIeDevice(CrowApp &app) :
111f5c9f8bdSJason M. Bills         Node(app, "/redfish/v1/Systems/system/PCIeDevices/<str>/",
112f5c9f8bdSJason M. Bills              std::string())
113f5c9f8bdSJason M. Bills     {
114f5c9f8bdSJason M. Bills         entityPrivileges = {
115f5c9f8bdSJason M. Bills             {boost::beast::http::verb::get, {{"Login"}}},
116f5c9f8bdSJason M. Bills             {boost::beast::http::verb::head, {{"Login"}}},
117f5c9f8bdSJason M. Bills             {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
118f5c9f8bdSJason M. Bills             {boost::beast::http::verb::put, {{"ConfigureManager"}}},
119f5c9f8bdSJason M. Bills             {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
120f5c9f8bdSJason M. Bills             {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
121f5c9f8bdSJason M. Bills     }
122f5c9f8bdSJason M. Bills 
123f5c9f8bdSJason M. Bills   private:
124f5c9f8bdSJason M. Bills     void doGet(crow::Response &res, const crow::Request &req,
125f5c9f8bdSJason M. Bills                const std::vector<std::string> &params) override
126f5c9f8bdSJason M. Bills     {
127f5c9f8bdSJason M. Bills         std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
128f5c9f8bdSJason M. Bills         if (params.size() != 1)
129f5c9f8bdSJason M. Bills         {
130f5c9f8bdSJason M. Bills             messages::internalError(asyncResp->res);
131f5c9f8bdSJason M. Bills             return;
132f5c9f8bdSJason M. Bills         }
133f5c9f8bdSJason M. Bills         const std::string &device = params[0];
134f5c9f8bdSJason M. Bills 
135f5c9f8bdSJason M. Bills         auto getPCIeDeviceCallback =
136f5c9f8bdSJason M. Bills             [asyncResp,
137f5c9f8bdSJason M. Bills              device](const boost::system::error_code ec,
138f5c9f8bdSJason M. Bills                      boost::container::flat_map<
139f5c9f8bdSJason M. Bills                          std::string, sdbusplus::message::variant<std::string>>
140f5c9f8bdSJason M. Bills                          &pcieDevProperties) {
141f5c9f8bdSJason M. Bills                 if (ec)
142f5c9f8bdSJason M. Bills                 {
143f5c9f8bdSJason M. Bills                     BMCWEB_LOG_DEBUG
144f5c9f8bdSJason M. Bills                         << "failed to get PCIe Device properties ec: "
145271584abSEd Tanous                         << ec.value() << ": " << ec.message();
146f5c9f8bdSJason M. Bills                     if (ec.value() ==
147f5c9f8bdSJason M. Bills                         boost::system::linux_error::bad_request_descriptor)
148f5c9f8bdSJason M. Bills                     {
149f5c9f8bdSJason M. Bills                         messages::resourceNotFound(asyncResp->res, "PCIeDevice",
150f5c9f8bdSJason M. Bills                                                    device);
151f5c9f8bdSJason M. Bills                     }
152f5c9f8bdSJason M. Bills                     else
153f5c9f8bdSJason M. Bills                     {
154f5c9f8bdSJason M. Bills                         messages::internalError(asyncResp->res);
155f5c9f8bdSJason M. Bills                     }
156f5c9f8bdSJason M. Bills                     return;
157f5c9f8bdSJason M. Bills                 }
158f5c9f8bdSJason M. Bills 
159f5c9f8bdSJason M. Bills                 asyncResp->res.jsonValue = {
160dede6a98SJason M. Bills                     {"@odata.type", "#PCIeDevice.v1_4_0.PCIeDevice"},
161f5c9f8bdSJason M. Bills                     {"@odata.id",
162f5c9f8bdSJason M. Bills                      "/redfish/v1/Systems/system/PCIeDevices/" + device},
163f5c9f8bdSJason M. Bills                     {"Name", "PCIe Device"},
164f5c9f8bdSJason M. Bills                     {"Id", device}};
165f5c9f8bdSJason M. Bills 
166*8d78b7a9SPatrick Williams                 if (std::string *property = std::get_if<std::string>(
167f5c9f8bdSJason M. Bills                         &pcieDevProperties["Manufacturer"]);
168f5c9f8bdSJason M. Bills                     property)
169f5c9f8bdSJason M. Bills                 {
170f5c9f8bdSJason M. Bills                     asyncResp->res.jsonValue["Manufacturer"] = *property;
171f5c9f8bdSJason M. Bills                 }
172f5c9f8bdSJason M. Bills 
173*8d78b7a9SPatrick Williams                 if (std::string *property = std::get_if<std::string>(
174f5c9f8bdSJason M. Bills                         &pcieDevProperties["DeviceType"]);
175f5c9f8bdSJason M. Bills                     property)
176f5c9f8bdSJason M. Bills                 {
177f5c9f8bdSJason M. Bills                     asyncResp->res.jsonValue["DeviceType"] = *property;
178f5c9f8bdSJason M. Bills                 }
179f5c9f8bdSJason M. Bills 
180dede6a98SJason M. Bills                 asyncResp->res.jsonValue["PCIeFunctions"] = {
181dede6a98SJason M. Bills                     {"@odata.id", "/redfish/v1/Systems/system/PCIeDevices/" +
182dede6a98SJason M. Bills                                       device + "/PCIeFunctions"}};
183dede6a98SJason M. Bills             };
184dede6a98SJason M. Bills         std::string escapedPath = std::string(pciePath) + "/" + device;
185dede6a98SJason M. Bills         dbus::utility::escapePathForDbus(escapedPath);
186dede6a98SJason M. Bills         crow::connections::systemBus->async_method_call(
187dede6a98SJason M. Bills             std::move(getPCIeDeviceCallback), pcieService, escapedPath,
188dede6a98SJason M. Bills             "org.freedesktop.DBus.Properties", "GetAll", pcieDeviceInterface);
189dede6a98SJason M. Bills     }
190dede6a98SJason M. Bills };
191dede6a98SJason M. Bills 
192dede6a98SJason M. Bills class SystemPCIeFunctionCollection : public Node
193dede6a98SJason M. Bills {
194dede6a98SJason M. Bills   public:
195dede6a98SJason M. Bills     template <typename CrowApp>
196dede6a98SJason M. Bills     SystemPCIeFunctionCollection(CrowApp &app) :
197dede6a98SJason M. Bills         Node(app, "/redfish/v1/Systems/system/PCIeDevices/<str>/PCIeFunctions/",
198dede6a98SJason M. Bills              std::string())
199dede6a98SJason M. Bills     {
200dede6a98SJason M. Bills         entityPrivileges = {
201dede6a98SJason M. Bills             {boost::beast::http::verb::get, {{"Login"}}},
202dede6a98SJason M. Bills             {boost::beast::http::verb::head, {{"Login"}}},
203dede6a98SJason M. Bills             {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
204dede6a98SJason M. Bills             {boost::beast::http::verb::put, {{"ConfigureManager"}}},
205dede6a98SJason M. Bills             {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
206dede6a98SJason M. Bills             {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
207dede6a98SJason M. Bills     }
208dede6a98SJason M. Bills 
209dede6a98SJason M. Bills   private:
210dede6a98SJason M. Bills     /**
211dede6a98SJason M. Bills      * Functions triggers appropriate requests on DBus
212dede6a98SJason M. Bills      */
213dede6a98SJason M. Bills     void doGet(crow::Response &res, const crow::Request &req,
214dede6a98SJason M. Bills                const std::vector<std::string> &params) override
215dede6a98SJason M. Bills     {
216dede6a98SJason M. Bills         std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
217dede6a98SJason M. Bills         if (params.size() != 1)
218dede6a98SJason M. Bills         {
219dede6a98SJason M. Bills             messages::internalError(asyncResp->res);
220dede6a98SJason M. Bills             return;
221dede6a98SJason M. Bills         }
222dede6a98SJason M. Bills         const std::string &device = params[0];
223dede6a98SJason M. Bills         asyncResp->res.jsonValue = {
224dede6a98SJason M. Bills             {"@odata.type", "#PCIeFunctionCollection.PCIeFunctionCollection"},
225dede6a98SJason M. Bills             {"@odata.id", "/redfish/v1/Systems/system/PCIeDevices/" + device +
226dede6a98SJason M. Bills                               "/PCIeFunctions"},
227dede6a98SJason M. Bills             {"Name", "PCIe Function Collection"},
228dede6a98SJason M. Bills             {"Description",
229dede6a98SJason M. Bills              "Collection of PCIe Functions for PCIe Device " + device}};
230dede6a98SJason M. Bills 
231dede6a98SJason M. Bills         auto getPCIeDeviceCallback =
232dede6a98SJason M. Bills             [asyncResp,
233dede6a98SJason M. Bills              device](const boost::system::error_code ec,
234dede6a98SJason M. Bills                      boost::container::flat_map<
235dede6a98SJason M. Bills                          std::string, sdbusplus::message::variant<std::string>>
236dede6a98SJason M. Bills                          &pcieDevProperties) {
237dede6a98SJason M. Bills                 if (ec)
238dede6a98SJason M. Bills                 {
239dede6a98SJason M. Bills                     BMCWEB_LOG_DEBUG
240dede6a98SJason M. Bills                         << "failed to get PCIe Device properties ec: "
241dede6a98SJason M. Bills                         << ec.value() << ": " << ec.message();
242dede6a98SJason M. Bills                     if (ec.value() ==
243dede6a98SJason M. Bills                         boost::system::linux_error::bad_request_descriptor)
244dede6a98SJason M. Bills                     {
245dede6a98SJason M. Bills                         messages::resourceNotFound(asyncResp->res, "PCIeDevice",
246dede6a98SJason M. Bills                                                    device);
247dede6a98SJason M. Bills                     }
248dede6a98SJason M. Bills                     else
249dede6a98SJason M. Bills                     {
250dede6a98SJason M. Bills                         messages::internalError(asyncResp->res);
251dede6a98SJason M. Bills                     }
252dede6a98SJason M. Bills                     return;
253dede6a98SJason M. Bills                 }
254dede6a98SJason M. Bills 
255f5c9f8bdSJason M. Bills                 nlohmann::json &pcieFunctionList =
256dede6a98SJason M. Bills                     asyncResp->res.jsonValue["Members"];
257f5c9f8bdSJason M. Bills                 pcieFunctionList = nlohmann::json::array();
258f5c9f8bdSJason M. Bills                 static constexpr const int maxPciFunctionNum = 8;
259f5c9f8bdSJason M. Bills                 for (int functionNum = 0; functionNum < maxPciFunctionNum;
260f5c9f8bdSJason M. Bills                      functionNum++)
261f5c9f8bdSJason M. Bills                 {
262f5c9f8bdSJason M. Bills                     // Check if this function exists by looking for a device ID
263f5c9f8bdSJason M. Bills                     std::string devIDProperty =
264f5c9f8bdSJason M. Bills                         "Function" + std::to_string(functionNum) + "DeviceId";
265*8d78b7a9SPatrick Williams                     std::string *property = std::get_if<std::string>(
266f5c9f8bdSJason M. Bills                         &pcieDevProperties[devIDProperty]);
267dede6a98SJason M. Bills                     if (property && !property->empty())
268f5c9f8bdSJason M. Bills                     {
269f5c9f8bdSJason M. Bills                         pcieFunctionList.push_back(
270f5c9f8bdSJason M. Bills                             {{"@odata.id",
271f5c9f8bdSJason M. Bills                               "/redfish/v1/Systems/system/PCIeDevices/" +
272f5c9f8bdSJason M. Bills                                   device + "/PCIeFunctions/" +
273f5c9f8bdSJason M. Bills                                   std::to_string(functionNum)}});
274f5c9f8bdSJason M. Bills                     }
275f5c9f8bdSJason M. Bills                 }
276dede6a98SJason M. Bills                 asyncResp->res.jsonValue["PCIeFunctions@odata.count"] =
277f5c9f8bdSJason M. Bills                     pcieFunctionList.size();
278f5c9f8bdSJason M. Bills             };
279f5c9f8bdSJason M. Bills         std::string escapedPath = std::string(pciePath) + "/" + device;
280f5c9f8bdSJason M. Bills         dbus::utility::escapePathForDbus(escapedPath);
281f5c9f8bdSJason M. Bills         crow::connections::systemBus->async_method_call(
282f5c9f8bdSJason M. Bills             std::move(getPCIeDeviceCallback), pcieService, escapedPath,
283f5c9f8bdSJason M. Bills             "org.freedesktop.DBus.Properties", "GetAll", pcieDeviceInterface);
284f5c9f8bdSJason M. Bills     }
285f5c9f8bdSJason M. Bills };
286f5c9f8bdSJason M. Bills 
287f5c9f8bdSJason M. Bills class SystemPCIeFunction : public Node
288f5c9f8bdSJason M. Bills {
289f5c9f8bdSJason M. Bills   public:
290f5c9f8bdSJason M. Bills     SystemPCIeFunction(CrowApp &app) :
291f5c9f8bdSJason M. Bills         Node(
292f5c9f8bdSJason M. Bills             app,
293f5c9f8bdSJason M. Bills             "/redfish/v1/Systems/system/PCIeDevices/<str>/PCIeFunctions/<str>/",
294f5c9f8bdSJason M. Bills             std::string(), std::string())
295f5c9f8bdSJason M. Bills     {
296f5c9f8bdSJason M. Bills         entityPrivileges = {
297f5c9f8bdSJason M. Bills             {boost::beast::http::verb::get, {{"Login"}}},
298f5c9f8bdSJason M. Bills             {boost::beast::http::verb::head, {{"Login"}}},
299f5c9f8bdSJason M. Bills             {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
300f5c9f8bdSJason M. Bills             {boost::beast::http::verb::put, {{"ConfigureManager"}}},
301f5c9f8bdSJason M. Bills             {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
302f5c9f8bdSJason M. Bills             {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
303f5c9f8bdSJason M. Bills     }
304f5c9f8bdSJason M. Bills 
305f5c9f8bdSJason M. Bills   private:
306f5c9f8bdSJason M. Bills     void doGet(crow::Response &res, const crow::Request &req,
307f5c9f8bdSJason M. Bills                const std::vector<std::string> &params) override
308f5c9f8bdSJason M. Bills     {
309f5c9f8bdSJason M. Bills         std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
310f5c9f8bdSJason M. Bills         if (params.size() != 2)
311f5c9f8bdSJason M. Bills         {
312f5c9f8bdSJason M. Bills             messages::internalError(asyncResp->res);
313f5c9f8bdSJason M. Bills             return;
314f5c9f8bdSJason M. Bills         }
315f5c9f8bdSJason M. Bills         const std::string &device = params[0];
316f5c9f8bdSJason M. Bills         const std::string &function = params[1];
317f5c9f8bdSJason M. Bills 
318*8d78b7a9SPatrick Williams         auto getPCIeDeviceCallback = [asyncResp, device, function](
319f5c9f8bdSJason M. Bills                                          const boost::system::error_code ec,
320f5c9f8bdSJason M. Bills                                          boost::container::flat_map<
321*8d78b7a9SPatrick Williams                                              std::string,
322*8d78b7a9SPatrick Williams                                              sdbusplus::message::variant<
323*8d78b7a9SPatrick Williams                                                  std::string>>
324f5c9f8bdSJason M. Bills                                              &pcieDevProperties) {
325f5c9f8bdSJason M. Bills             if (ec)
326f5c9f8bdSJason M. Bills             {
327f5c9f8bdSJason M. Bills                 BMCWEB_LOG_DEBUG
328*8d78b7a9SPatrick Williams                     << "failed to get PCIe Device properties ec: " << ec.value()
329*8d78b7a9SPatrick Williams                     << ": " << ec.message();
330f5c9f8bdSJason M. Bills                 if (ec.value() ==
331f5c9f8bdSJason M. Bills                     boost::system::linux_error::bad_request_descriptor)
332f5c9f8bdSJason M. Bills                 {
333f5c9f8bdSJason M. Bills                     messages::resourceNotFound(asyncResp->res, "PCIeDevice",
334f5c9f8bdSJason M. Bills                                                device);
335f5c9f8bdSJason M. Bills                 }
336f5c9f8bdSJason M. Bills                 else
337f5c9f8bdSJason M. Bills                 {
338f5c9f8bdSJason M. Bills                     messages::internalError(asyncResp->res);
339f5c9f8bdSJason M. Bills                 }
340f5c9f8bdSJason M. Bills                 return;
341f5c9f8bdSJason M. Bills             }
342f5c9f8bdSJason M. Bills 
343f5c9f8bdSJason M. Bills             // Check if this function exists by looking for a device ID
344f5c9f8bdSJason M. Bills             std::string devIDProperty = "Function" + function + "DeviceId";
345f5c9f8bdSJason M. Bills             if (std::string *property =
346*8d78b7a9SPatrick Williams                     std::get_if<std::string>(&pcieDevProperties[devIDProperty]);
347f5c9f8bdSJason M. Bills                 property && property->empty())
348f5c9f8bdSJason M. Bills             {
349f5c9f8bdSJason M. Bills                 messages::resourceNotFound(asyncResp->res, "PCIeFunction",
350f5c9f8bdSJason M. Bills                                            function);
351f5c9f8bdSJason M. Bills                 return;
352f5c9f8bdSJason M. Bills             }
353f5c9f8bdSJason M. Bills 
354f5c9f8bdSJason M. Bills             asyncResp->res.jsonValue = {
355f5c9f8bdSJason M. Bills                 {"@odata.type", "#PCIeFunction.v1_2_0.PCIeFunction"},
356f5c9f8bdSJason M. Bills                 {"@odata.id", "/redfish/v1/Systems/system/PCIeDevices/" +
357f5c9f8bdSJason M. Bills                                   device + "/PCIeFunctions/" + function},
358f5c9f8bdSJason M. Bills                 {"Name", "PCIe Function"},
359f5c9f8bdSJason M. Bills                 {"Id", function},
360f5c9f8bdSJason M. Bills                 {"FunctionId", std::stoi(function)},
361f5c9f8bdSJason M. Bills                 {"Links",
362f5c9f8bdSJason M. Bills                  {{"PCIeDevice",
363f5c9f8bdSJason M. Bills                    {{"@odata.id",
364*8d78b7a9SPatrick Williams                      "/redfish/v1/Systems/system/PCIeDevices/" + device}}}}}};
365f5c9f8bdSJason M. Bills 
366*8d78b7a9SPatrick Williams             if (std::string *property = std::get_if<std::string>(
367*8d78b7a9SPatrick Williams                     &pcieDevProperties["Function" + function + "DeviceId"]);
368f5c9f8bdSJason M. Bills                 property)
369f5c9f8bdSJason M. Bills             {
370f5c9f8bdSJason M. Bills                 asyncResp->res.jsonValue["DeviceId"] = *property;
371f5c9f8bdSJason M. Bills             }
372f5c9f8bdSJason M. Bills 
373*8d78b7a9SPatrick Williams             if (std::string *property = std::get_if<std::string>(
374*8d78b7a9SPatrick Williams                     &pcieDevProperties["Function" + function + "VendorId"]);
375f5c9f8bdSJason M. Bills                 property)
376f5c9f8bdSJason M. Bills             {
377f5c9f8bdSJason M. Bills                 asyncResp->res.jsonValue["VendorId"] = *property;
378f5c9f8bdSJason M. Bills             }
379f5c9f8bdSJason M. Bills 
380*8d78b7a9SPatrick Williams             if (std::string *property = std::get_if<std::string>(
381*8d78b7a9SPatrick Williams                     &pcieDevProperties["Function" + function + "FunctionType"]);
382f5c9f8bdSJason M. Bills                 property)
383f5c9f8bdSJason M. Bills             {
384f5c9f8bdSJason M. Bills                 asyncResp->res.jsonValue["FunctionType"] = *property;
385f5c9f8bdSJason M. Bills             }
386f5c9f8bdSJason M. Bills 
387*8d78b7a9SPatrick Williams             if (std::string *property = std::get_if<std::string>(
388*8d78b7a9SPatrick Williams                     &pcieDevProperties["Function" + function + "DeviceClass"]);
389f5c9f8bdSJason M. Bills                 property)
390f5c9f8bdSJason M. Bills             {
391f5c9f8bdSJason M. Bills                 asyncResp->res.jsonValue["DeviceClass"] = *property;
392f5c9f8bdSJason M. Bills             }
393f5c9f8bdSJason M. Bills 
394*8d78b7a9SPatrick Williams             if (std::string *property = std::get_if<std::string>(
395*8d78b7a9SPatrick Williams                     &pcieDevProperties["Function" + function + "ClassCode"]);
396f5c9f8bdSJason M. Bills                 property)
397f5c9f8bdSJason M. Bills             {
398f5c9f8bdSJason M. Bills                 asyncResp->res.jsonValue["ClassCode"] = *property;
399f5c9f8bdSJason M. Bills             }
400f5c9f8bdSJason M. Bills 
401*8d78b7a9SPatrick Williams             if (std::string *property = std::get_if<std::string>(
402*8d78b7a9SPatrick Williams                     &pcieDevProperties["Function" + function + "RevisionId"]);
403f5c9f8bdSJason M. Bills                 property)
404f5c9f8bdSJason M. Bills             {
405f5c9f8bdSJason M. Bills                 asyncResp->res.jsonValue["RevisionId"] = *property;
406f5c9f8bdSJason M. Bills             }
407f5c9f8bdSJason M. Bills 
408*8d78b7a9SPatrick Williams             if (std::string *property = std::get_if<std::string>(
409*8d78b7a9SPatrick Williams                     &pcieDevProperties["Function" + function + "SubsystemId"]);
410f5c9f8bdSJason M. Bills                 property)
411f5c9f8bdSJason M. Bills             {
412f5c9f8bdSJason M. Bills                 asyncResp->res.jsonValue["SubsystemId"] = *property;
413f5c9f8bdSJason M. Bills             }
414f5c9f8bdSJason M. Bills 
415*8d78b7a9SPatrick Williams             if (std::string *property = std::get_if<std::string>(
416f5c9f8bdSJason M. Bills                     &pcieDevProperties["Function" + function +
417f5c9f8bdSJason M. Bills                                        "SubsystemVendorId"]);
418f5c9f8bdSJason M. Bills                 property)
419f5c9f8bdSJason M. Bills             {
420f5c9f8bdSJason M. Bills                 asyncResp->res.jsonValue["SubsystemVendorId"] = *property;
421f5c9f8bdSJason M. Bills             }
422f5c9f8bdSJason M. Bills         };
423f5c9f8bdSJason M. Bills         std::string escapedPath = std::string(pciePath) + "/" + device;
424f5c9f8bdSJason M. Bills         dbus::utility::escapePathForDbus(escapedPath);
425f5c9f8bdSJason M. Bills         crow::connections::systemBus->async_method_call(
426f5c9f8bdSJason M. Bills             std::move(getPCIeDeviceCallback), pcieService, escapedPath,
427f5c9f8bdSJason M. Bills             "org.freedesktop.DBus.Properties", "GetAll", pcieDeviceInterface);
428f5c9f8bdSJason M. Bills     }
429f5c9f8bdSJason M. Bills };
430f5c9f8bdSJason M. Bills 
431f5c9f8bdSJason M. Bills } // namespace redfish
432