xref: /openbmc/bmcweb/features/redfish/lib/pcie.hpp (revision b5a76932eab7d40487ffb305cd745ec155813c4e)
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*b5a76932SEd Tanous static inline void
32*b5a76932SEd Tanous     getPCIeDeviceList(const std::shared_ptr<AsyncResp>& asyncResp,
33adbe192aSJason M. Bills                       const std::string& name)
34f5c9f8bdSJason M. Bills {
35adbe192aSJason M. Bills     auto getPCIeMapCallback = [asyncResp, name](
36adbe192aSJason M. Bills                                   const boost::system::error_code ec,
37f5c9f8bdSJason M. Bills                                   std::vector<std::string>& pcieDevicePaths) {
38f5c9f8bdSJason M. Bills         if (ec)
39f5c9f8bdSJason M. Bills         {
40a2730f01SAndrew Geissler             BMCWEB_LOG_DEBUG << "no PCIe device paths found ec: "
41f5c9f8bdSJason M. Bills                              << ec.message();
42a2730f01SAndrew Geissler             // Not an error, system just doesn't have PCIe info
43f5c9f8bdSJason M. Bills             return;
44f5c9f8bdSJason M. Bills         }
45adbe192aSJason M. Bills         nlohmann::json& pcieDeviceList = asyncResp->res.jsonValue[name];
46f5c9f8bdSJason M. Bills         pcieDeviceList = nlohmann::json::array();
47f5c9f8bdSJason M. Bills         for (const std::string& pcieDevicePath : pcieDevicePaths)
48f5c9f8bdSJason M. Bills         {
493174e4dfSEd Tanous             size_t devStart = pcieDevicePath.rfind('/');
50f5c9f8bdSJason M. Bills             if (devStart == std::string::npos)
51f5c9f8bdSJason M. Bills             {
52f5c9f8bdSJason M. Bills                 continue;
53f5c9f8bdSJason M. Bills             }
54f5c9f8bdSJason M. Bills 
55f5c9f8bdSJason M. Bills             std::string devName = pcieDevicePath.substr(devStart + 1);
56f5c9f8bdSJason M. Bills             if (devName.empty())
57f5c9f8bdSJason M. Bills             {
58f5c9f8bdSJason M. Bills                 continue;
59f5c9f8bdSJason M. Bills             }
60f5c9f8bdSJason M. Bills             pcieDeviceList.push_back(
61f5c9f8bdSJason M. Bills                 {{"@odata.id",
62f5c9f8bdSJason M. Bills                   "/redfish/v1/Systems/system/PCIeDevices/" + devName}});
63f5c9f8bdSJason M. Bills         }
64adbe192aSJason M. Bills         asyncResp->res.jsonValue[name + "@odata.count"] = pcieDeviceList.size();
65f5c9f8bdSJason M. Bills     };
66f5c9f8bdSJason M. Bills     crow::connections::systemBus->async_method_call(
67f5c9f8bdSJason M. Bills         std::move(getPCIeMapCallback), "xyz.openbmc_project.ObjectMapper",
68f5c9f8bdSJason M. Bills         "/xyz/openbmc_project/object_mapper",
69f5c9f8bdSJason M. Bills         "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths",
70f5c9f8bdSJason M. Bills         std::string(pciePath) + "/", 1, std::array<std::string, 0>());
71f5c9f8bdSJason M. Bills }
72f5c9f8bdSJason M. Bills 
73adbe192aSJason M. Bills class SystemPCIeDeviceCollection : public Node
74adbe192aSJason M. Bills {
75adbe192aSJason M. Bills   public:
7652cc112dSEd Tanous     SystemPCIeDeviceCollection(App& 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      */
92cb13a392SEd Tanous     void doGet(crow::Response& res, const crow::Request&,
93cb13a392SEd Tanous                const std::vector<std::string>&) 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:
11052cc112dSEd Tanous     SystemPCIeDevice(App& 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:
124cb13a392SEd Tanous     void doGet(crow::Response& res, const crow::Request&,
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,
1391214b7e7SGunnar Mills                                                 std::variant<std::string>>&
1401214b7e7SGunnar 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:
19552cc112dSEd Tanous     SystemPCIeFunctionCollection(App& app) :
196dede6a98SJason M. Bills         Node(app, "/redfish/v1/Systems/system/PCIeDevices/<str>/PCIeFunctions/",
197dede6a98SJason M. Bills              std::string())
198dede6a98SJason M. Bills     {
199dede6a98SJason M. Bills         entityPrivileges = {
200dede6a98SJason M. Bills             {boost::beast::http::verb::get, {{"Login"}}},
201dede6a98SJason M. Bills             {boost::beast::http::verb::head, {{"Login"}}},
202dede6a98SJason M. Bills             {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
203dede6a98SJason M. Bills             {boost::beast::http::verb::put, {{"ConfigureManager"}}},
204dede6a98SJason M. Bills             {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
205dede6a98SJason M. Bills             {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
206dede6a98SJason M. Bills     }
207dede6a98SJason M. Bills 
208dede6a98SJason M. Bills   private:
209dede6a98SJason M. Bills     /**
210dede6a98SJason M. Bills      * Functions triggers appropriate requests on DBus
211dede6a98SJason M. Bills      */
212cb13a392SEd Tanous     void doGet(crow::Response& res, const crow::Request&,
213dede6a98SJason M. Bills                const std::vector<std::string>& params) override
214dede6a98SJason M. Bills     {
215dede6a98SJason M. Bills         std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
216dede6a98SJason M. Bills         if (params.size() != 1)
217dede6a98SJason M. Bills         {
218dede6a98SJason M. Bills             messages::internalError(asyncResp->res);
219dede6a98SJason M. Bills             return;
220dede6a98SJason M. Bills         }
221dede6a98SJason M. Bills         const std::string& device = params[0];
222dede6a98SJason M. Bills         asyncResp->res.jsonValue = {
223dede6a98SJason M. Bills             {"@odata.type", "#PCIeFunctionCollection.PCIeFunctionCollection"},
224dede6a98SJason M. Bills             {"@odata.id", "/redfish/v1/Systems/system/PCIeDevices/" + device +
225dede6a98SJason M. Bills                               "/PCIeFunctions"},
226dede6a98SJason M. Bills             {"Name", "PCIe Function Collection"},
227dede6a98SJason M. Bills             {"Description",
228dede6a98SJason M. Bills              "Collection of PCIe Functions for PCIe Device " + device}};
229dede6a98SJason M. Bills 
230dede6a98SJason M. Bills         auto getPCIeDeviceCallback =
231dede6a98SJason M. Bills             [asyncResp,
232dede6a98SJason M. Bills              device](const boost::system::error_code ec,
23319bd78d9SPatrick Williams                      boost::container::flat_map<std::string,
2341214b7e7SGunnar Mills                                                 std::variant<std::string>>&
2351214b7e7SGunnar Mills                          pcieDevProperties) {
236dede6a98SJason M. Bills                 if (ec)
237dede6a98SJason M. Bills                 {
238dede6a98SJason M. Bills                     BMCWEB_LOG_DEBUG
239dede6a98SJason M. Bills                         << "failed to get PCIe Device properties ec: "
240dede6a98SJason M. Bills                         << ec.value() << ": " << ec.message();
241dede6a98SJason M. Bills                     if (ec.value() ==
242dede6a98SJason M. Bills                         boost::system::linux_error::bad_request_descriptor)
243dede6a98SJason M. Bills                     {
244dede6a98SJason M. Bills                         messages::resourceNotFound(asyncResp->res, "PCIeDevice",
245dede6a98SJason M. Bills                                                    device);
246dede6a98SJason M. Bills                     }
247dede6a98SJason M. Bills                     else
248dede6a98SJason M. Bills                     {
249dede6a98SJason M. Bills                         messages::internalError(asyncResp->res);
250dede6a98SJason M. Bills                     }
251dede6a98SJason M. Bills                     return;
252dede6a98SJason M. Bills                 }
253dede6a98SJason M. Bills 
254f5c9f8bdSJason M. Bills                 nlohmann::json& pcieFunctionList =
255dede6a98SJason M. Bills                     asyncResp->res.jsonValue["Members"];
256f5c9f8bdSJason M. Bills                 pcieFunctionList = nlohmann::json::array();
257f5c9f8bdSJason M. Bills                 static constexpr const int maxPciFunctionNum = 8;
258f5c9f8bdSJason M. Bills                 for (int functionNum = 0; functionNum < maxPciFunctionNum;
259f5c9f8bdSJason M. Bills                      functionNum++)
260f5c9f8bdSJason M. Bills                 {
261f5c9f8bdSJason M. Bills                     // Check if this function exists by looking for a device ID
262f5c9f8bdSJason M. Bills                     std::string devIDProperty =
263f5c9f8bdSJason M. Bills                         "Function" + std::to_string(functionNum) + "DeviceId";
2648d78b7a9SPatrick Williams                     std::string* property = std::get_if<std::string>(
265f5c9f8bdSJason M. Bills                         &pcieDevProperties[devIDProperty]);
266dede6a98SJason M. Bills                     if (property && !property->empty())
267f5c9f8bdSJason M. Bills                     {
268f5c9f8bdSJason M. Bills                         pcieFunctionList.push_back(
269f5c9f8bdSJason M. Bills                             {{"@odata.id",
270f5c9f8bdSJason M. Bills                               "/redfish/v1/Systems/system/PCIeDevices/" +
271f5c9f8bdSJason M. Bills                                   device + "/PCIeFunctions/" +
272f5c9f8bdSJason M. Bills                                   std::to_string(functionNum)}});
273f5c9f8bdSJason M. Bills                     }
274f5c9f8bdSJason M. Bills                 }
275dede6a98SJason M. Bills                 asyncResp->res.jsonValue["PCIeFunctions@odata.count"] =
276f5c9f8bdSJason M. Bills                     pcieFunctionList.size();
277f5c9f8bdSJason M. Bills             };
278f5c9f8bdSJason M. Bills         std::string escapedPath = std::string(pciePath) + "/" + device;
279f5c9f8bdSJason M. Bills         dbus::utility::escapePathForDbus(escapedPath);
280f5c9f8bdSJason M. Bills         crow::connections::systemBus->async_method_call(
281f5c9f8bdSJason M. Bills             std::move(getPCIeDeviceCallback), pcieService, escapedPath,
282f5c9f8bdSJason M. Bills             "org.freedesktop.DBus.Properties", "GetAll", pcieDeviceInterface);
283f5c9f8bdSJason M. Bills     }
284f5c9f8bdSJason M. Bills };
285f5c9f8bdSJason M. Bills 
286f5c9f8bdSJason M. Bills class SystemPCIeFunction : public Node
287f5c9f8bdSJason M. Bills {
288f5c9f8bdSJason M. Bills   public:
28952cc112dSEd Tanous     SystemPCIeFunction(App& app) :
290f5c9f8bdSJason M. Bills         Node(
291f5c9f8bdSJason M. Bills             app,
292f5c9f8bdSJason M. Bills             "/redfish/v1/Systems/system/PCIeDevices/<str>/PCIeFunctions/<str>/",
293f5c9f8bdSJason M. Bills             std::string(), std::string())
294f5c9f8bdSJason M. Bills     {
295f5c9f8bdSJason M. Bills         entityPrivileges = {
296f5c9f8bdSJason M. Bills             {boost::beast::http::verb::get, {{"Login"}}},
297f5c9f8bdSJason M. Bills             {boost::beast::http::verb::head, {{"Login"}}},
298f5c9f8bdSJason M. Bills             {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
299f5c9f8bdSJason M. Bills             {boost::beast::http::verb::put, {{"ConfigureManager"}}},
300f5c9f8bdSJason M. Bills             {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
301f5c9f8bdSJason M. Bills             {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
302f5c9f8bdSJason M. Bills     }
303f5c9f8bdSJason M. Bills 
304f5c9f8bdSJason M. Bills   private:
305cb13a392SEd Tanous     void doGet(crow::Response& res, const crow::Request&,
306f5c9f8bdSJason M. Bills                const std::vector<std::string>& params) override
307f5c9f8bdSJason M. Bills     {
308f5c9f8bdSJason M. Bills         std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
309f5c9f8bdSJason M. Bills         if (params.size() != 2)
310f5c9f8bdSJason M. Bills         {
311f5c9f8bdSJason M. Bills             messages::internalError(asyncResp->res);
312f5c9f8bdSJason M. Bills             return;
313f5c9f8bdSJason M. Bills         }
314f5c9f8bdSJason M. Bills         const std::string& device = params[0];
315f5c9f8bdSJason M. Bills         const std::string& function = params[1];
316f5c9f8bdSJason M. Bills 
3178d78b7a9SPatrick Williams         auto getPCIeDeviceCallback = [asyncResp, device, function](
318f5c9f8bdSJason M. Bills                                          const boost::system::error_code ec,
319f5c9f8bdSJason M. Bills                                          boost::container::flat_map<
3208d78b7a9SPatrick Williams                                              std::string,
3211214b7e7SGunnar Mills                                              std::variant<std::string>>&
3221214b7e7SGunnar Mills                                              pcieDevProperties) {
323f5c9f8bdSJason M. Bills             if (ec)
324f5c9f8bdSJason M. Bills             {
325f5c9f8bdSJason M. Bills                 BMCWEB_LOG_DEBUG
3268d78b7a9SPatrick Williams                     << "failed to get PCIe Device properties ec: " << ec.value()
3278d78b7a9SPatrick Williams                     << ": " << ec.message();
328f5c9f8bdSJason M. Bills                 if (ec.value() ==
329f5c9f8bdSJason M. Bills                     boost::system::linux_error::bad_request_descriptor)
330f5c9f8bdSJason M. Bills                 {
331f5c9f8bdSJason M. Bills                     messages::resourceNotFound(asyncResp->res, "PCIeDevice",
332f5c9f8bdSJason M. Bills                                                device);
333f5c9f8bdSJason M. Bills                 }
334f5c9f8bdSJason M. Bills                 else
335f5c9f8bdSJason M. Bills                 {
336f5c9f8bdSJason M. Bills                     messages::internalError(asyncResp->res);
337f5c9f8bdSJason M. Bills                 }
338f5c9f8bdSJason M. Bills                 return;
339f5c9f8bdSJason M. Bills             }
340f5c9f8bdSJason M. Bills 
341f5c9f8bdSJason M. Bills             // Check if this function exists by looking for a device ID
342f5c9f8bdSJason M. Bills             std::string devIDProperty = "Function" + function + "DeviceId";
343f5c9f8bdSJason M. Bills             if (std::string* property =
3448d78b7a9SPatrick Williams                     std::get_if<std::string>(&pcieDevProperties[devIDProperty]);
345f5c9f8bdSJason M. Bills                 property && property->empty())
346f5c9f8bdSJason M. Bills             {
347f5c9f8bdSJason M. Bills                 messages::resourceNotFound(asyncResp->res, "PCIeFunction",
348f5c9f8bdSJason M. Bills                                            function);
349f5c9f8bdSJason M. Bills                 return;
350f5c9f8bdSJason M. Bills             }
351f5c9f8bdSJason M. Bills 
352f5c9f8bdSJason M. Bills             asyncResp->res.jsonValue = {
353f5c9f8bdSJason M. Bills                 {"@odata.type", "#PCIeFunction.v1_2_0.PCIeFunction"},
354f5c9f8bdSJason M. Bills                 {"@odata.id", "/redfish/v1/Systems/system/PCIeDevices/" +
355f5c9f8bdSJason M. Bills                                   device + "/PCIeFunctions/" + function},
356f5c9f8bdSJason M. Bills                 {"Name", "PCIe Function"},
357f5c9f8bdSJason M. Bills                 {"Id", function},
358f5c9f8bdSJason M. Bills                 {"FunctionId", std::stoi(function)},
359f5c9f8bdSJason M. Bills                 {"Links",
360f5c9f8bdSJason M. Bills                  {{"PCIeDevice",
361f5c9f8bdSJason M. Bills                    {{"@odata.id",
3628d78b7a9SPatrick Williams                      "/redfish/v1/Systems/system/PCIeDevices/" + device}}}}}};
363f5c9f8bdSJason M. Bills 
3648d78b7a9SPatrick Williams             if (std::string* property = std::get_if<std::string>(
3658d78b7a9SPatrick Williams                     &pcieDevProperties["Function" + function + "DeviceId"]);
366f5c9f8bdSJason M. Bills                 property)
367f5c9f8bdSJason M. Bills             {
368f5c9f8bdSJason M. Bills                 asyncResp->res.jsonValue["DeviceId"] = *property;
369f5c9f8bdSJason M. Bills             }
370f5c9f8bdSJason M. Bills 
3718d78b7a9SPatrick Williams             if (std::string* property = std::get_if<std::string>(
3728d78b7a9SPatrick Williams                     &pcieDevProperties["Function" + function + "VendorId"]);
373f5c9f8bdSJason M. Bills                 property)
374f5c9f8bdSJason M. Bills             {
375f5c9f8bdSJason M. Bills                 asyncResp->res.jsonValue["VendorId"] = *property;
376f5c9f8bdSJason M. Bills             }
377f5c9f8bdSJason M. Bills 
3788d78b7a9SPatrick Williams             if (std::string* property = std::get_if<std::string>(
3798d78b7a9SPatrick Williams                     &pcieDevProperties["Function" + function + "FunctionType"]);
380f5c9f8bdSJason M. Bills                 property)
381f5c9f8bdSJason M. Bills             {
382f5c9f8bdSJason M. Bills                 asyncResp->res.jsonValue["FunctionType"] = *property;
383f5c9f8bdSJason M. Bills             }
384f5c9f8bdSJason M. Bills 
3858d78b7a9SPatrick Williams             if (std::string* property = std::get_if<std::string>(
3868d78b7a9SPatrick Williams                     &pcieDevProperties["Function" + function + "DeviceClass"]);
387f5c9f8bdSJason M. Bills                 property)
388f5c9f8bdSJason M. Bills             {
389f5c9f8bdSJason M. Bills                 asyncResp->res.jsonValue["DeviceClass"] = *property;
390f5c9f8bdSJason M. Bills             }
391f5c9f8bdSJason M. Bills 
3928d78b7a9SPatrick Williams             if (std::string* property = std::get_if<std::string>(
3938d78b7a9SPatrick Williams                     &pcieDevProperties["Function" + function + "ClassCode"]);
394f5c9f8bdSJason M. Bills                 property)
395f5c9f8bdSJason M. Bills             {
396f5c9f8bdSJason M. Bills                 asyncResp->res.jsonValue["ClassCode"] = *property;
397f5c9f8bdSJason M. Bills             }
398f5c9f8bdSJason M. Bills 
3998d78b7a9SPatrick Williams             if (std::string* property = std::get_if<std::string>(
4008d78b7a9SPatrick Williams                     &pcieDevProperties["Function" + function + "RevisionId"]);
401f5c9f8bdSJason M. Bills                 property)
402f5c9f8bdSJason M. Bills             {
403f5c9f8bdSJason M. Bills                 asyncResp->res.jsonValue["RevisionId"] = *property;
404f5c9f8bdSJason M. Bills             }
405f5c9f8bdSJason M. Bills 
4068d78b7a9SPatrick Williams             if (std::string* property = std::get_if<std::string>(
4078d78b7a9SPatrick Williams                     &pcieDevProperties["Function" + function + "SubsystemId"]);
408f5c9f8bdSJason M. Bills                 property)
409f5c9f8bdSJason M. Bills             {
410f5c9f8bdSJason M. Bills                 asyncResp->res.jsonValue["SubsystemId"] = *property;
411f5c9f8bdSJason M. Bills             }
412f5c9f8bdSJason M. Bills 
4138d78b7a9SPatrick Williams             if (std::string* property = std::get_if<std::string>(
414f5c9f8bdSJason M. Bills                     &pcieDevProperties["Function" + function +
415f5c9f8bdSJason M. Bills                                        "SubsystemVendorId"]);
416f5c9f8bdSJason M. Bills                 property)
417f5c9f8bdSJason M. Bills             {
418f5c9f8bdSJason M. Bills                 asyncResp->res.jsonValue["SubsystemVendorId"] = *property;
419f5c9f8bdSJason M. Bills             }
420f5c9f8bdSJason M. Bills         };
421f5c9f8bdSJason M. Bills         std::string escapedPath = std::string(pciePath) + "/" + device;
422f5c9f8bdSJason M. Bills         dbus::utility::escapePathForDbus(escapedPath);
423f5c9f8bdSJason M. Bills         crow::connections::systemBus->async_method_call(
424f5c9f8bdSJason M. Bills             std::move(getPCIeDeviceCallback), pcieService, escapedPath,
425f5c9f8bdSJason M. Bills             "org.freedesktop.DBus.Properties", "GetAll", pcieDeviceInterface);
426f5c9f8bdSJason M. Bills     }
427f5c9f8bdSJason M. Bills };
428f5c9f8bdSJason M. Bills 
429f5c9f8bdSJason M. Bills } // namespace redfish
430