xref: /openbmc/bmcweb/features/redfish/lib/pcie.hpp (revision 1214b7e7d921e331fb1480c7e5d579ffa5811cda)
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,
13819bd78d9SPatrick Williams                      boost::container::flat_map<std::string,
139*1214b7e7SGunnar Mills                                                 std::variant<std::string>>&
140*1214b7e7SGunnar Mills                          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 
1668d78b7a9SPatrick 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 
1738d78b7a9SPatrick 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,
23419bd78d9SPatrick Williams                      boost::container::flat_map<std::string,
235*1214b7e7SGunnar Mills                                                 std::variant<std::string>>&
236*1214b7e7SGunnar Mills                          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";
2658d78b7a9SPatrick 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 
3188d78b7a9SPatrick Williams         auto getPCIeDeviceCallback = [asyncResp, device, function](
319f5c9f8bdSJason M. Bills                                          const boost::system::error_code ec,
320f5c9f8bdSJason M. Bills                                          boost::container::flat_map<
3218d78b7a9SPatrick Williams                                              std::string,
322*1214b7e7SGunnar Mills                                              std::variant<std::string>>&
323*1214b7e7SGunnar Mills                                              pcieDevProperties) {
324f5c9f8bdSJason M. Bills             if (ec)
325f5c9f8bdSJason M. Bills             {
326f5c9f8bdSJason M. Bills                 BMCWEB_LOG_DEBUG
3278d78b7a9SPatrick Williams                     << "failed to get PCIe Device properties ec: " << ec.value()
3288d78b7a9SPatrick Williams                     << ": " << ec.message();
329f5c9f8bdSJason M. Bills                 if (ec.value() ==
330f5c9f8bdSJason M. Bills                     boost::system::linux_error::bad_request_descriptor)
331f5c9f8bdSJason M. Bills                 {
332f5c9f8bdSJason M. Bills                     messages::resourceNotFound(asyncResp->res, "PCIeDevice",
333f5c9f8bdSJason M. Bills                                                device);
334f5c9f8bdSJason M. Bills                 }
335f5c9f8bdSJason M. Bills                 else
336f5c9f8bdSJason M. Bills                 {
337f5c9f8bdSJason M. Bills                     messages::internalError(asyncResp->res);
338f5c9f8bdSJason M. Bills                 }
339f5c9f8bdSJason M. Bills                 return;
340f5c9f8bdSJason M. Bills             }
341f5c9f8bdSJason M. Bills 
342f5c9f8bdSJason M. Bills             // Check if this function exists by looking for a device ID
343f5c9f8bdSJason M. Bills             std::string devIDProperty = "Function" + function + "DeviceId";
344f5c9f8bdSJason M. Bills             if (std::string* property =
3458d78b7a9SPatrick Williams                     std::get_if<std::string>(&pcieDevProperties[devIDProperty]);
346f5c9f8bdSJason M. Bills                 property && property->empty())
347f5c9f8bdSJason M. Bills             {
348f5c9f8bdSJason M. Bills                 messages::resourceNotFound(asyncResp->res, "PCIeFunction",
349f5c9f8bdSJason M. Bills                                            function);
350f5c9f8bdSJason M. Bills                 return;
351f5c9f8bdSJason M. Bills             }
352f5c9f8bdSJason M. Bills 
353f5c9f8bdSJason M. Bills             asyncResp->res.jsonValue = {
354f5c9f8bdSJason M. Bills                 {"@odata.type", "#PCIeFunction.v1_2_0.PCIeFunction"},
355f5c9f8bdSJason M. Bills                 {"@odata.id", "/redfish/v1/Systems/system/PCIeDevices/" +
356f5c9f8bdSJason M. Bills                                   device + "/PCIeFunctions/" + function},
357f5c9f8bdSJason M. Bills                 {"Name", "PCIe Function"},
358f5c9f8bdSJason M. Bills                 {"Id", function},
359f5c9f8bdSJason M. Bills                 {"FunctionId", std::stoi(function)},
360f5c9f8bdSJason M. Bills                 {"Links",
361f5c9f8bdSJason M. Bills                  {{"PCIeDevice",
362f5c9f8bdSJason M. Bills                    {{"@odata.id",
3638d78b7a9SPatrick Williams                      "/redfish/v1/Systems/system/PCIeDevices/" + device}}}}}};
364f5c9f8bdSJason M. Bills 
3658d78b7a9SPatrick Williams             if (std::string* property = std::get_if<std::string>(
3668d78b7a9SPatrick Williams                     &pcieDevProperties["Function" + function + "DeviceId"]);
367f5c9f8bdSJason M. Bills                 property)
368f5c9f8bdSJason M. Bills             {
369f5c9f8bdSJason M. Bills                 asyncResp->res.jsonValue["DeviceId"] = *property;
370f5c9f8bdSJason M. Bills             }
371f5c9f8bdSJason M. Bills 
3728d78b7a9SPatrick Williams             if (std::string* property = std::get_if<std::string>(
3738d78b7a9SPatrick Williams                     &pcieDevProperties["Function" + function + "VendorId"]);
374f5c9f8bdSJason M. Bills                 property)
375f5c9f8bdSJason M. Bills             {
376f5c9f8bdSJason M. Bills                 asyncResp->res.jsonValue["VendorId"] = *property;
377f5c9f8bdSJason M. Bills             }
378f5c9f8bdSJason M. Bills 
3798d78b7a9SPatrick Williams             if (std::string* property = std::get_if<std::string>(
3808d78b7a9SPatrick Williams                     &pcieDevProperties["Function" + function + "FunctionType"]);
381f5c9f8bdSJason M. Bills                 property)
382f5c9f8bdSJason M. Bills             {
383f5c9f8bdSJason M. Bills                 asyncResp->res.jsonValue["FunctionType"] = *property;
384f5c9f8bdSJason M. Bills             }
385f5c9f8bdSJason M. Bills 
3868d78b7a9SPatrick Williams             if (std::string* property = std::get_if<std::string>(
3878d78b7a9SPatrick Williams                     &pcieDevProperties["Function" + function + "DeviceClass"]);
388f5c9f8bdSJason M. Bills                 property)
389f5c9f8bdSJason M. Bills             {
390f5c9f8bdSJason M. Bills                 asyncResp->res.jsonValue["DeviceClass"] = *property;
391f5c9f8bdSJason M. Bills             }
392f5c9f8bdSJason M. Bills 
3938d78b7a9SPatrick Williams             if (std::string* property = std::get_if<std::string>(
3948d78b7a9SPatrick Williams                     &pcieDevProperties["Function" + function + "ClassCode"]);
395f5c9f8bdSJason M. Bills                 property)
396f5c9f8bdSJason M. Bills             {
397f5c9f8bdSJason M. Bills                 asyncResp->res.jsonValue["ClassCode"] = *property;
398f5c9f8bdSJason M. Bills             }
399f5c9f8bdSJason M. Bills 
4008d78b7a9SPatrick Williams             if (std::string* property = std::get_if<std::string>(
4018d78b7a9SPatrick Williams                     &pcieDevProperties["Function" + function + "RevisionId"]);
402f5c9f8bdSJason M. Bills                 property)
403f5c9f8bdSJason M. Bills             {
404f5c9f8bdSJason M. Bills                 asyncResp->res.jsonValue["RevisionId"] = *property;
405f5c9f8bdSJason M. Bills             }
406f5c9f8bdSJason M. Bills 
4078d78b7a9SPatrick Williams             if (std::string* property = std::get_if<std::string>(
4088d78b7a9SPatrick Williams                     &pcieDevProperties["Function" + function + "SubsystemId"]);
409f5c9f8bdSJason M. Bills                 property)
410f5c9f8bdSJason M. Bills             {
411f5c9f8bdSJason M. Bills                 asyncResp->res.jsonValue["SubsystemId"] = *property;
412f5c9f8bdSJason M. Bills             }
413f5c9f8bdSJason M. Bills 
4148d78b7a9SPatrick Williams             if (std::string* property = std::get_if<std::string>(
415f5c9f8bdSJason M. Bills                     &pcieDevProperties["Function" + function +
416f5c9f8bdSJason M. Bills                                        "SubsystemVendorId"]);
417f5c9f8bdSJason M. Bills                 property)
418f5c9f8bdSJason M. Bills             {
419f5c9f8bdSJason M. Bills                 asyncResp->res.jsonValue["SubsystemVendorId"] = *property;
420f5c9f8bdSJason M. Bills             }
421f5c9f8bdSJason M. Bills         };
422f5c9f8bdSJason M. Bills         std::string escapedPath = std::string(pciePath) + "/" + device;
423f5c9f8bdSJason M. Bills         dbus::utility::escapePathForDbus(escapedPath);
424f5c9f8bdSJason M. Bills         crow::connections::systemBus->async_method_call(
425f5c9f8bdSJason M. Bills             std::move(getPCIeDeviceCallback), pcieService, escapedPath,
426f5c9f8bdSJason M. Bills             "org.freedesktop.DBus.Properties", "GetAll", pcieDeviceInterface);
427f5c9f8bdSJason M. Bills     }
428f5c9f8bdSJason M. Bills };
429f5c9f8bdSJason M. Bills 
430f5c9f8bdSJason M. Bills } // namespace redfish
431