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