xref: /openbmc/bmcweb/features/redfish/lib/pcie.hpp (revision 1476687deb1697d865b20458a0097c9ab5fd44e2)
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 
197e860f15SJohn Edward Broadbent #include <app.hpp>
20f5c9f8bdSJason M. Bills #include <boost/system/linux_error.hpp>
21168e20c1SEd Tanous #include <dbus_utility.hpp>
2245ca1b86SEd Tanous #include <query.hpp>
23ed398213SEd Tanous #include <registries/privilege_registry.hpp>
24f5c9f8bdSJason M. Bills 
25f5c9f8bdSJason M. Bills namespace redfish
26f5c9f8bdSJason M. Bills {
27f5c9f8bdSJason M. Bills 
28f5c9f8bdSJason M. Bills static constexpr char const* pcieService = "xyz.openbmc_project.PCIe";
29f5c9f8bdSJason M. Bills static constexpr char const* pciePath = "/xyz/openbmc_project/PCIe";
30f5c9f8bdSJason M. Bills static constexpr char const* pcieDeviceInterface =
31f5c9f8bdSJason M. Bills     "xyz.openbmc_project.PCIe.Device";
32f5c9f8bdSJason M. Bills 
33b5a76932SEd Tanous static inline void
348d1b46d7Szhanghch05     getPCIeDeviceList(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
35adbe192aSJason M. Bills                       const std::string& name)
36f5c9f8bdSJason M. Bills {
37b9d36b47SEd Tanous     auto getPCIeMapCallback =
38b9d36b47SEd Tanous         [asyncResp, name](const boost::system::error_code ec,
39b9d36b47SEd Tanous                           const dbus::utility::MapperGetSubTreePathsResponse&
40b9d36b47SEd Tanous                               pcieDevicePaths) {
41f5c9f8bdSJason M. Bills             if (ec)
42f5c9f8bdSJason M. Bills             {
43a2730f01SAndrew Geissler                 BMCWEB_LOG_DEBUG << "no PCIe device paths found ec: "
44f5c9f8bdSJason M. Bills                                  << ec.message();
45a2730f01SAndrew Geissler                 // Not an error, system just doesn't have PCIe info
46f5c9f8bdSJason M. Bills                 return;
47f5c9f8bdSJason M. Bills             }
48adbe192aSJason M. Bills             nlohmann::json& pcieDeviceList = asyncResp->res.jsonValue[name];
49f5c9f8bdSJason M. Bills             pcieDeviceList = nlohmann::json::array();
50f5c9f8bdSJason M. Bills             for (const std::string& pcieDevicePath : pcieDevicePaths)
51f5c9f8bdSJason M. Bills             {
523174e4dfSEd Tanous                 size_t devStart = pcieDevicePath.rfind('/');
53f5c9f8bdSJason M. Bills                 if (devStart == std::string::npos)
54f5c9f8bdSJason M. Bills                 {
55f5c9f8bdSJason M. Bills                     continue;
56f5c9f8bdSJason M. Bills                 }
57f5c9f8bdSJason M. Bills 
58f5c9f8bdSJason M. Bills                 std::string devName = pcieDevicePath.substr(devStart + 1);
59f5c9f8bdSJason M. Bills                 if (devName.empty())
60f5c9f8bdSJason M. Bills                 {
61f5c9f8bdSJason M. Bills                     continue;
62f5c9f8bdSJason M. Bills                 }
63*1476687dSEd Tanous                 nlohmann::json::object_t pcieDevice;
64*1476687dSEd Tanous                 pcieDevice["@odata.id"] =
65*1476687dSEd Tanous                     "/redfish/v1/Systems/system/PCIeDevices/" + devName;
66*1476687dSEd Tanous                 pcieDeviceList.push_back(std::move(pcieDevice));
67f5c9f8bdSJason M. Bills             }
68b9d36b47SEd Tanous             asyncResp->res.jsonValue[name + "@odata.count"] =
69b9d36b47SEd Tanous                 pcieDeviceList.size();
70f5c9f8bdSJason M. Bills         };
71f5c9f8bdSJason M. Bills     crow::connections::systemBus->async_method_call(
72f5c9f8bdSJason M. Bills         std::move(getPCIeMapCallback), "xyz.openbmc_project.ObjectMapper",
73f5c9f8bdSJason M. Bills         "/xyz/openbmc_project/object_mapper",
74f5c9f8bdSJason M. Bills         "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths",
75f5c9f8bdSJason M. Bills         std::string(pciePath) + "/", 1, std::array<std::string, 0>());
76f5c9f8bdSJason M. Bills }
77f5c9f8bdSJason M. Bills 
787e860f15SJohn Edward Broadbent inline void requestRoutesSystemPCIeDeviceCollection(App& app)
79adbe192aSJason M. Bills {
80adbe192aSJason M. Bills     /**
81adbe192aSJason M. Bills      * Functions triggers appropriate requests on DBus
82adbe192aSJason M. Bills      */
837e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/PCIeDevices/")
84ed398213SEd Tanous         .privileges(redfish::privileges::getPCIeDeviceCollection)
857e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
8645ca1b86SEd Tanous             [&app](const crow::Request& req,
8745ca1b86SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
8845ca1b86SEd Tanous                 if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
89adbe192aSJason M. Bills                 {
9045ca1b86SEd Tanous                     return;
9145ca1b86SEd Tanous                 }
92*1476687dSEd Tanous 
93*1476687dSEd Tanous                 asyncResp->res.jsonValue["@odata.type"] =
94*1476687dSEd Tanous                     "#PCIeDeviceCollection.PCIeDeviceCollection";
95*1476687dSEd Tanous                 asyncResp->res.jsonValue["@odata.id"] =
96*1476687dSEd Tanous                     "/redfish/v1/Systems/system/PCIeDevices";
97*1476687dSEd Tanous                 asyncResp->res.jsonValue["Name"] = "PCIe Device Collection";
98*1476687dSEd Tanous                 asyncResp->res.jsonValue["Description"] =
99*1476687dSEd Tanous                     "Collection of PCIe Devices";
100*1476687dSEd Tanous                 asyncResp->res.jsonValue["Members"] = nlohmann::json::array();
101*1476687dSEd Tanous                 asyncResp->res.jsonValue["Members@odata.count"] = 0;
102adbe192aSJason M. Bills                 getPCIeDeviceList(asyncResp, "Members");
1037e860f15SJohn Edward Broadbent             });
104f5c9f8bdSJason M. Bills }
105f5c9f8bdSJason M. Bills 
10662cd45afSSpencer Ku inline std::optional<std::string>
10762cd45afSSpencer Ku     redfishPcieGenerationFromDbus(const std::string& generationInUse)
10862cd45afSSpencer Ku {
10962cd45afSSpencer Ku     if (generationInUse ==
11062cd45afSSpencer Ku         "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen1")
11162cd45afSSpencer Ku     {
11262cd45afSSpencer Ku         return "Gen1";
11362cd45afSSpencer Ku     }
11462cd45afSSpencer Ku     if (generationInUse ==
11562cd45afSSpencer Ku         "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen2")
11662cd45afSSpencer Ku     {
11762cd45afSSpencer Ku         return "Gen2";
11862cd45afSSpencer Ku     }
11962cd45afSSpencer Ku     if (generationInUse ==
12062cd45afSSpencer Ku         "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen3")
12162cd45afSSpencer Ku     {
12262cd45afSSpencer Ku         return "Gen3";
12362cd45afSSpencer Ku     }
12462cd45afSSpencer Ku     if (generationInUse ==
12562cd45afSSpencer Ku         "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen4")
12662cd45afSSpencer Ku     {
12762cd45afSSpencer Ku         return "Gen4";
12862cd45afSSpencer Ku     }
12962cd45afSSpencer Ku     if (generationInUse ==
13062cd45afSSpencer Ku         "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen5")
13162cd45afSSpencer Ku     {
13262cd45afSSpencer Ku         return "Gen5";
13362cd45afSSpencer Ku     }
13462cd45afSSpencer Ku     if (generationInUse.empty() ||
13562cd45afSSpencer Ku         generationInUse ==
13662cd45afSSpencer Ku             "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Unknown")
13762cd45afSSpencer Ku     {
13862cd45afSSpencer Ku         return "";
13962cd45afSSpencer Ku     }
14062cd45afSSpencer Ku 
14162cd45afSSpencer Ku     // The value is not unknown or Gen1-5, need return an internal error.
14262cd45afSSpencer Ku     return std::nullopt;
14362cd45afSSpencer Ku }
14462cd45afSSpencer Ku 
1457e860f15SJohn Edward Broadbent inline void requestRoutesSystemPCIeDevice(App& app)
146f5c9f8bdSJason M. Bills {
1477e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/PCIeDevices/<str>/")
148ed398213SEd Tanous         .privileges(redfish::privileges::getPCIeDevice)
14945ca1b86SEd Tanous         .methods(
15045ca1b86SEd Tanous             boost::beast::http::verb::
15145ca1b86SEd Tanous                 get)([&app](const crow::Request& req,
1527e860f15SJohn Edward Broadbent                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
15345ca1b86SEd Tanous                             const std::string& device) {
15445ca1b86SEd Tanous             if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
1557e860f15SJohn Edward Broadbent             {
15645ca1b86SEd Tanous                 return;
15745ca1b86SEd Tanous             }
158168e20c1SEd Tanous             auto getPCIeDeviceCallback =
15945ca1b86SEd Tanous                 [asyncResp, device](
16045ca1b86SEd Tanous                     const boost::system::error_code ec,
16145ca1b86SEd Tanous                     const dbus::utility::DBusPropertiesMap& pcieDevProperties) {
162f5c9f8bdSJason M. Bills                     if (ec)
163f5c9f8bdSJason M. Bills                     {
164f5c9f8bdSJason M. Bills                         BMCWEB_LOG_DEBUG
165f5c9f8bdSJason M. Bills                             << "failed to get PCIe Device properties ec: "
166271584abSEd Tanous                             << ec.value() << ": " << ec.message();
16745ca1b86SEd Tanous                         if (ec.value() ==
16845ca1b86SEd Tanous                             boost::system::linux_error::bad_request_descriptor)
169f5c9f8bdSJason M. Bills                         {
17045ca1b86SEd Tanous                             messages::resourceNotFound(asyncResp->res,
17145ca1b86SEd Tanous                                                        "PCIeDevice", device);
172f5c9f8bdSJason M. Bills                         }
173f5c9f8bdSJason M. Bills                         else
174f5c9f8bdSJason M. Bills                         {
175f5c9f8bdSJason M. Bills                             messages::internalError(asyncResp->res);
176f5c9f8bdSJason M. Bills                         }
177f5c9f8bdSJason M. Bills                         return;
178f5c9f8bdSJason M. Bills                     }
179f5c9f8bdSJason M. Bills 
180*1476687dSEd Tanous                     asyncResp->res.jsonValue["@odata.type"] =
181*1476687dSEd Tanous                         "#PCIeDevice.v1_4_0.PCIeDevice";
182*1476687dSEd Tanous                     asyncResp->res.jsonValue["@odata.id"] =
183*1476687dSEd Tanous                         "/redfish/v1/Systems/system/PCIeDevices/" + device;
184*1476687dSEd Tanous                     asyncResp->res.jsonValue["Name"] = "PCIe Device";
185*1476687dSEd Tanous                     asyncResp->res.jsonValue["Id"] = device;
186*1476687dSEd Tanous 
187*1476687dSEd Tanous                     asyncResp->res.jsonValue["PCIeFunctions"]["@odata.id"] =
18845ca1b86SEd Tanous                         "/redfish/v1/Systems/system/PCIeDevices/" + device +
189*1476687dSEd Tanous                         "/PCIeFunctions";
190b9d36b47SEd Tanous                     for (const auto& property : pcieDevProperties)
191f5c9f8bdSJason M. Bills                     {
192b9d36b47SEd Tanous                         const std::string* propertyString =
193b9d36b47SEd Tanous                             std::get_if<std::string>(&property.second);
194b9d36b47SEd Tanous                         if (property.first == "Manufacturer")
195b9d36b47SEd Tanous                         {
196b9d36b47SEd Tanous                             if (propertyString == nullptr)
197b9d36b47SEd Tanous                             {
198b9d36b47SEd Tanous                                 messages::internalError(asyncResp->res);
199b9d36b47SEd Tanous                                 return;
200b9d36b47SEd Tanous                             }
201168e20c1SEd Tanous                             asyncResp->res.jsonValue["Manufacturer"] =
202b9d36b47SEd Tanous                                 *propertyString;
203168e20c1SEd Tanous                         }
204b9d36b47SEd Tanous                         if (property.first == "DeviceType")
205168e20c1SEd Tanous                         {
206b9d36b47SEd Tanous                             if (propertyString == nullptr)
207b9d36b47SEd Tanous                             {
208b9d36b47SEd Tanous                                 messages::internalError(asyncResp->res);
209b9d36b47SEd Tanous                                 return;
210168e20c1SEd Tanous                             }
211b9d36b47SEd Tanous                             asyncResp->res.jsonValue["DeviceType"] =
212b9d36b47SEd Tanous                                 *propertyString;
213f5c9f8bdSJason M. Bills                         }
214b9d36b47SEd Tanous                         if (property.first == "GenerationInUse")
21562cd45afSSpencer Ku                         {
216b9d36b47SEd Tanous                             if (propertyString == nullptr)
217b9d36b47SEd Tanous                             {
218b9d36b47SEd Tanous                                 messages::internalError(asyncResp->res);
219b9d36b47SEd Tanous                                 return;
220b9d36b47SEd Tanous                             }
22162cd45afSSpencer Ku                             std::optional<std::string> generationInUse =
22245ca1b86SEd Tanous                                 redfishPcieGenerationFromDbus(*propertyString);
22362cd45afSSpencer Ku                             if (!generationInUse)
22462cd45afSSpencer Ku                             {
22562cd45afSSpencer Ku                                 messages::internalError(asyncResp->res);
22662cd45afSSpencer Ku                                 return;
22762cd45afSSpencer Ku                             }
22826f6976fSEd Tanous                             if (generationInUse->empty())
22962cd45afSSpencer Ku                             {
23062cd45afSSpencer Ku                                 // unknown, no need to handle
23162cd45afSSpencer Ku                                 return;
23262cd45afSSpencer Ku                             }
233168e20c1SEd Tanous                             asyncResp->res
234213ffc70SAnjaliintel-21                                 .jsonValue["PCIeInterface"]["PCIeType"] =
23562cd45afSSpencer Ku                                 *generationInUse;
23662cd45afSSpencer Ku                         }
237b9d36b47SEd Tanous                     }
238dede6a98SJason M. Bills                 };
239dede6a98SJason M. Bills             std::string escapedPath = std::string(pciePath) + "/" + device;
240dede6a98SJason M. Bills             dbus::utility::escapePathForDbus(escapedPath);
241dede6a98SJason M. Bills             crow::connections::systemBus->async_method_call(
242dede6a98SJason M. Bills                 std::move(getPCIeDeviceCallback), pcieService, escapedPath,
2437e860f15SJohn Edward Broadbent                 "org.freedesktop.DBus.Properties", "GetAll",
2447e860f15SJohn Edward Broadbent                 pcieDeviceInterface);
2457e860f15SJohn Edward Broadbent         });
246dede6a98SJason M. Bills }
247dede6a98SJason M. Bills 
2487e860f15SJohn Edward Broadbent inline void requestRoutesSystemPCIeFunctionCollection(App& app)
2497e860f15SJohn Edward Broadbent {
250dede6a98SJason M. Bills     /**
251dede6a98SJason M. Bills      * Functions triggers appropriate requests on DBus
252dede6a98SJason M. Bills      */
2537e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app,
2547e860f15SJohn Edward Broadbent                  "/redfish/v1/Systems/system/PCIeDevices/<str>/PCIeFunctions/")
255ed398213SEd Tanous         .privileges(redfish::privileges::getPCIeFunctionCollection)
25645ca1b86SEd Tanous         .methods(
25745ca1b86SEd Tanous             boost::beast::http::verb::
25845ca1b86SEd Tanous                 get)([&app](const crow::Request& req,
2597e860f15SJohn Edward Broadbent                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
26045ca1b86SEd Tanous                             const std::string& device) {
26145ca1b86SEd Tanous             if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
262dede6a98SJason M. Bills             {
26345ca1b86SEd Tanous                 return;
26445ca1b86SEd Tanous             }
265*1476687dSEd Tanous 
266*1476687dSEd Tanous             asyncResp->res.jsonValue["@odata.type"] =
267*1476687dSEd Tanous                 "#PCIeFunctionCollection.PCIeFunctionCollection";
268*1476687dSEd Tanous             asyncResp->res.jsonValue["@odata.id"] =
269*1476687dSEd Tanous                 "/redfish/v1/Systems/system/PCIeDevices/" + device +
270*1476687dSEd Tanous                 "/PCIeFunctions";
271*1476687dSEd Tanous             asyncResp->res.jsonValue["Name"] = "PCIe Function Collection";
272*1476687dSEd Tanous             asyncResp->res.jsonValue["Description"] =
273*1476687dSEd Tanous                 "Collection of PCIe Functions for PCIe Device " + device;
274dede6a98SJason M. Bills 
275b9d36b47SEd Tanous             auto getPCIeDeviceCallback =
27645ca1b86SEd Tanous                 [asyncResp, device](
27745ca1b86SEd Tanous                     const boost::system::error_code ec,
27845ca1b86SEd Tanous                     const dbus::utility::DBusPropertiesMap& pcieDevProperties) {
2797e860f15SJohn Edward Broadbent                     if (ec)
2807e860f15SJohn Edward Broadbent                     {
2817e860f15SJohn Edward Broadbent                         BMCWEB_LOG_DEBUG
2827e860f15SJohn Edward Broadbent                             << "failed to get PCIe Device properties ec: "
2837e860f15SJohn Edward Broadbent                             << ec.value() << ": " << ec.message();
28445ca1b86SEd Tanous                         if (ec.value() ==
28545ca1b86SEd Tanous                             boost::system::linux_error::bad_request_descriptor)
2867e860f15SJohn Edward Broadbent                         {
28745ca1b86SEd Tanous                             messages::resourceNotFound(asyncResp->res,
28845ca1b86SEd Tanous                                                        "PCIeDevice", device);
2897e860f15SJohn Edward Broadbent                         }
2907e860f15SJohn Edward Broadbent                         else
2917e860f15SJohn Edward Broadbent                         {
2927e860f15SJohn Edward Broadbent                             messages::internalError(asyncResp->res);
2937e860f15SJohn Edward Broadbent                         }
2947e860f15SJohn Edward Broadbent                         return;
2957e860f15SJohn Edward Broadbent                     }
2967e860f15SJohn Edward Broadbent 
2977e860f15SJohn Edward Broadbent                     nlohmann::json& pcieFunctionList =
2987e860f15SJohn Edward Broadbent                         asyncResp->res.jsonValue["Members"];
2997e860f15SJohn Edward Broadbent                     pcieFunctionList = nlohmann::json::array();
3007e860f15SJohn Edward Broadbent                     static constexpr const int maxPciFunctionNum = 8;
30145ca1b86SEd Tanous                     for (int functionNum = 0; functionNum < maxPciFunctionNum;
30245ca1b86SEd Tanous                          functionNum++)
3037e860f15SJohn Edward Broadbent                     {
304b9d36b47SEd Tanous                         // Check if this function exists by looking for a
305b9d36b47SEd Tanous                         // device ID
3067e860f15SJohn Edward Broadbent                         std::string devIDProperty =
3077e860f15SJohn Edward Broadbent                             "Function" + std::to_string(functionNum) +
3087e860f15SJohn Edward Broadbent                             "DeviceId";
309b9d36b47SEd Tanous                         const std::string* property = nullptr;
310b9d36b47SEd Tanous                         for (const auto& propEntry : pcieDevProperties)
3117e860f15SJohn Edward Broadbent                         {
312b9d36b47SEd Tanous                             if (propEntry.first == devIDProperty)
313b9d36b47SEd Tanous                             {
31445ca1b86SEd Tanous                                 property =
31545ca1b86SEd Tanous                                     std::get_if<std::string>(&propEntry.second);
316b9d36b47SEd Tanous                             }
317b9d36b47SEd Tanous                         }
318b9d36b47SEd Tanous                         if (property == nullptr || !property->empty())
319b9d36b47SEd Tanous                         {
320b9d36b47SEd Tanous                             return;
321b9d36b47SEd Tanous                         }
322*1476687dSEd Tanous                         nlohmann::json::object_t pcieFunction;
323*1476687dSEd Tanous                         pcieFunction["@odata.id"] =
324*1476687dSEd Tanous                             "/redfish/v1/Systems/system/PCIeDevices/" + device +
325*1476687dSEd Tanous                             "/PCIeFunctions/" + std::to_string(functionNum);
326*1476687dSEd Tanous                         pcieFunctionList.push_back(std::move(pcieFunction));
3277e860f15SJohn Edward Broadbent                     }
328a818d15aSJiaqing Zhao                     asyncResp->res.jsonValue["Members@odata.count"] =
3297e860f15SJohn Edward Broadbent                         pcieFunctionList.size();
3307e860f15SJohn Edward Broadbent                 };
3317e860f15SJohn Edward Broadbent             std::string escapedPath = std::string(pciePath) + "/" + device;
3327e860f15SJohn Edward Broadbent             dbus::utility::escapePathForDbus(escapedPath);
3337e860f15SJohn Edward Broadbent             crow::connections::systemBus->async_method_call(
3347e860f15SJohn Edward Broadbent                 std::move(getPCIeDeviceCallback), pcieService, escapedPath,
3357e860f15SJohn Edward Broadbent                 "org.freedesktop.DBus.Properties", "GetAll",
3367e860f15SJohn Edward Broadbent                 pcieDeviceInterface);
3377e860f15SJohn Edward Broadbent         });
3387e860f15SJohn Edward Broadbent }
3397e860f15SJohn Edward Broadbent 
3407e860f15SJohn Edward Broadbent inline void requestRoutesSystemPCIeFunction(App& app)
3417e860f15SJohn Edward Broadbent {
3427e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(
3437e860f15SJohn Edward Broadbent         app,
3447e860f15SJohn Edward Broadbent         "/redfish/v1/Systems/system/PCIeDevices/<str>/PCIeFunctions/<str>/")
345ed398213SEd Tanous         .privileges(redfish::privileges::getPCIeFunction)
3467e860f15SJohn Edward Broadbent         .methods(
34745ca1b86SEd Tanous             boost::beast::http::verb::
34845ca1b86SEd Tanous                 get)([&app](const crow::Request& req,
34945ca1b86SEd Tanous                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3507e860f15SJohn Edward Broadbent                             const std::string& device,
3517e860f15SJohn Edward Broadbent                             const std::string& function) {
35245ca1b86SEd Tanous             if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
35345ca1b86SEd Tanous             {
35445ca1b86SEd Tanous                 return;
35545ca1b86SEd Tanous             }
356168e20c1SEd Tanous             auto getPCIeDeviceCallback =
357168e20c1SEd Tanous                 [asyncResp, device, function](
3587e860f15SJohn Edward Broadbent                     const boost::system::error_code ec,
359b9d36b47SEd Tanous                     const dbus::utility::DBusPropertiesMap& pcieDevProperties) {
360dede6a98SJason M. Bills                     if (ec)
361dede6a98SJason M. Bills                     {
362dede6a98SJason M. Bills                         BMCWEB_LOG_DEBUG
363dede6a98SJason M. Bills                             << "failed to get PCIe Device properties ec: "
364dede6a98SJason M. Bills                             << ec.value() << ": " << ec.message();
365dede6a98SJason M. Bills                         if (ec.value() ==
366dede6a98SJason M. Bills                             boost::system::linux_error::bad_request_descriptor)
367dede6a98SJason M. Bills                         {
368168e20c1SEd Tanous                             messages::resourceNotFound(asyncResp->res,
369168e20c1SEd Tanous                                                        "PCIeDevice", device);
370dede6a98SJason M. Bills                         }
371dede6a98SJason M. Bills                         else
372dede6a98SJason M. Bills                         {
373dede6a98SJason M. Bills                             messages::internalError(asyncResp->res);
374dede6a98SJason M. Bills                         }
375dede6a98SJason M. Bills                         return;
376dede6a98SJason M. Bills                     }
377dede6a98SJason M. Bills 
378*1476687dSEd Tanous                     // Check if this function exists by looking for a device
379*1476687dSEd Tanous                     // ID
380b9d36b47SEd Tanous                     std::string functionName = "Function" + function;
381b9d36b47SEd Tanous                     std::string devIDProperty = functionName + "DeviceId";
382b9d36b47SEd Tanous 
383b9d36b47SEd Tanous                     const std::string* devIdProperty = nullptr;
384b9d36b47SEd Tanous                     for (const auto& property : pcieDevProperties)
385b9d36b47SEd Tanous                     {
386b9d36b47SEd Tanous                         if (property.first == devIDProperty)
387b9d36b47SEd Tanous                         {
388b9d36b47SEd Tanous                             devIdProperty =
389b9d36b47SEd Tanous                                 std::get_if<std::string>(&property.second);
390b9d36b47SEd Tanous                             continue;
391b9d36b47SEd Tanous                         }
392b9d36b47SEd Tanous                     }
393b9d36b47SEd Tanous                     if (devIdProperty == nullptr || !devIdProperty->empty())
394f5c9f8bdSJason M. Bills                     {
395168e20c1SEd Tanous                         messages::resourceNotFound(asyncResp->res,
396168e20c1SEd Tanous                                                    "PCIeFunction", function);
397f5c9f8bdSJason M. Bills                         return;
398f5c9f8bdSJason M. Bills                     }
399f5c9f8bdSJason M. Bills 
400*1476687dSEd Tanous                     asyncResp->res.jsonValue["@odata.type"] =
401*1476687dSEd Tanous                         "#PCIeFunction.v1_2_0.PCIeFunction";
402*1476687dSEd Tanous                     asyncResp->res.jsonValue["@odata.id"] =
403168e20c1SEd Tanous                         "/redfish/v1/Systems/system/PCIeDevices/" + device +
404*1476687dSEd Tanous                         "/PCIeFunctions/" + function;
405*1476687dSEd Tanous                     asyncResp->res.jsonValue["Name"] = "PCIe Function";
406*1476687dSEd Tanous                     asyncResp->res.jsonValue["Id"] = function;
407*1476687dSEd Tanous                     asyncResp->res.jsonValue["FunctionId"] =
408*1476687dSEd Tanous                         std::stoi(function);
409*1476687dSEd Tanous                     asyncResp->res
410*1476687dSEd Tanous                         .jsonValue["Links"]["PCIeDevice"]["@odata.id"] =
411*1476687dSEd Tanous                         "/redfish/v1/Systems/system/PCIeDevices/" + device;
412f5c9f8bdSJason M. Bills 
413b9d36b47SEd Tanous                     for (const auto& property : pcieDevProperties)
414f5c9f8bdSJason M. Bills                     {
415b9d36b47SEd Tanous                         const std::string* strProperty =
416b9d36b47SEd Tanous                             std::get_if<std::string>(&property.second);
417b9d36b47SEd Tanous                         if (property.first == functionName + "DeviceId")
418f5c9f8bdSJason M. Bills                         {
419b9d36b47SEd Tanous                             asyncResp->res.jsonValue["DeviceId"] = *strProperty;
420f5c9f8bdSJason M. Bills                         }
421b9d36b47SEd Tanous                         if (property.first == functionName + "VendorId")
422f5c9f8bdSJason M. Bills                         {
423b9d36b47SEd Tanous                             asyncResp->res.jsonValue["VendorId"] = *strProperty;
424f5c9f8bdSJason M. Bills                         }
425b9d36b47SEd Tanous                         if (property.first == functionName + "FunctionType")
426f5c9f8bdSJason M. Bills                         {
427b9d36b47SEd Tanous                             asyncResp->res.jsonValue["FunctionType"] =
428b9d36b47SEd Tanous                                 *strProperty;
429f5c9f8bdSJason M. Bills                         }
430b9d36b47SEd Tanous                         if (property.first == functionName + "DeviceClass")
431f5c9f8bdSJason M. Bills                         {
432b9d36b47SEd Tanous                             asyncResp->res.jsonValue["DeviceClass"] =
433b9d36b47SEd Tanous                                 *strProperty;
434f5c9f8bdSJason M. Bills                         }
435b9d36b47SEd Tanous                         if (property.first == functionName + "ClassCode")
436f5c9f8bdSJason M. Bills                         {
437b9d36b47SEd Tanous                             asyncResp->res.jsonValue["ClassCode"] =
438b9d36b47SEd Tanous                                 *strProperty;
439f5c9f8bdSJason M. Bills                         }
440b9d36b47SEd Tanous                         if (property.first == functionName + "RevisionId")
441f5c9f8bdSJason M. Bills                         {
442b9d36b47SEd Tanous                             asyncResp->res.jsonValue["RevisionId"] =
443b9d36b47SEd Tanous                                 *strProperty;
444f5c9f8bdSJason M. Bills                         }
445b9d36b47SEd Tanous                         if (property.first == functionName + "SubsystemId")
446b9d36b47SEd Tanous                         {
447b9d36b47SEd Tanous                             asyncResp->res.jsonValue["SubsystemId"] =
448b9d36b47SEd Tanous                                 *strProperty;
449b9d36b47SEd Tanous                         }
450b9d36b47SEd Tanous                         if (property.first ==
451b9d36b47SEd Tanous                             functionName + "SubsystemVendorId")
452f5c9f8bdSJason M. Bills                         {
453168e20c1SEd Tanous                             asyncResp->res.jsonValue["SubsystemVendorId"] =
454b9d36b47SEd Tanous                                 *strProperty;
455b9d36b47SEd Tanous                         }
456f5c9f8bdSJason M. Bills                     }
457f5c9f8bdSJason M. Bills                 };
458f5c9f8bdSJason M. Bills             std::string escapedPath = std::string(pciePath) + "/" + device;
459f5c9f8bdSJason M. Bills             dbus::utility::escapePathForDbus(escapedPath);
460f5c9f8bdSJason M. Bills             crow::connections::systemBus->async_method_call(
461f5c9f8bdSJason M. Bills                 std::move(getPCIeDeviceCallback), pcieService, escapedPath,
4627e860f15SJohn Edward Broadbent                 "org.freedesktop.DBus.Properties", "GetAll",
4637e860f15SJohn Edward Broadbent                 pcieDeviceInterface);
4647e860f15SJohn Edward Broadbent         });
465f5c9f8bdSJason M. Bills }
466f5c9f8bdSJason M. Bills 
467f5c9f8bdSJason M. Bills } // namespace redfish
468