xref: /openbmc/bmcweb/features/redfish/lib/pcie.hpp (revision b9d36b4791d77a47e1f3c5c4564fcdf7cc68c115)
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>
22ed398213SEd Tanous #include <registries/privilege_registry.hpp>
23f5c9f8bdSJason M. Bills 
24f5c9f8bdSJason M. Bills namespace redfish
25f5c9f8bdSJason M. Bills {
26f5c9f8bdSJason M. Bills 
27f5c9f8bdSJason M. Bills static constexpr char const* pcieService = "xyz.openbmc_project.PCIe";
28f5c9f8bdSJason M. Bills static constexpr char const* pciePath = "/xyz/openbmc_project/PCIe";
29f5c9f8bdSJason M. Bills static constexpr char const* pcieDeviceInterface =
30f5c9f8bdSJason M. Bills     "xyz.openbmc_project.PCIe.Device";
31f5c9f8bdSJason M. Bills 
32b5a76932SEd Tanous static inline void
338d1b46d7Szhanghch05     getPCIeDeviceList(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
34adbe192aSJason M. Bills                       const std::string& name)
35f5c9f8bdSJason M. Bills {
36*b9d36b47SEd Tanous     auto getPCIeMapCallback =
37*b9d36b47SEd Tanous         [asyncResp, name](const boost::system::error_code ec,
38*b9d36b47SEd Tanous                           const dbus::utility::MapperGetSubTreePathsResponse&
39*b9d36b47SEd Tanous                               pcieDevicePaths) {
40f5c9f8bdSJason M. Bills             if (ec)
41f5c9f8bdSJason M. Bills             {
42a2730f01SAndrew Geissler                 BMCWEB_LOG_DEBUG << "no PCIe device paths found ec: "
43f5c9f8bdSJason M. Bills                                  << ec.message();
44a2730f01SAndrew Geissler                 // Not an error, system just doesn't have PCIe info
45f5c9f8bdSJason M. Bills                 return;
46f5c9f8bdSJason M. Bills             }
47adbe192aSJason M. Bills             nlohmann::json& pcieDeviceList = asyncResp->res.jsonValue[name];
48f5c9f8bdSJason M. Bills             pcieDeviceList = nlohmann::json::array();
49f5c9f8bdSJason M. Bills             for (const std::string& pcieDevicePath : pcieDevicePaths)
50f5c9f8bdSJason M. Bills             {
513174e4dfSEd Tanous                 size_t devStart = pcieDevicePath.rfind('/');
52f5c9f8bdSJason M. Bills                 if (devStart == std::string::npos)
53f5c9f8bdSJason M. Bills                 {
54f5c9f8bdSJason M. Bills                     continue;
55f5c9f8bdSJason M. Bills                 }
56f5c9f8bdSJason M. Bills 
57f5c9f8bdSJason M. Bills                 std::string devName = pcieDevicePath.substr(devStart + 1);
58f5c9f8bdSJason M. Bills                 if (devName.empty())
59f5c9f8bdSJason M. Bills                 {
60f5c9f8bdSJason M. Bills                     continue;
61f5c9f8bdSJason M. Bills                 }
62f5c9f8bdSJason M. Bills                 pcieDeviceList.push_back(
63f5c9f8bdSJason M. Bills                     {{"@odata.id",
64f5c9f8bdSJason M. Bills                       "/redfish/v1/Systems/system/PCIeDevices/" + devName}});
65f5c9f8bdSJason M. Bills             }
66*b9d36b47SEd Tanous             asyncResp->res.jsonValue[name + "@odata.count"] =
67*b9d36b47SEd Tanous                 pcieDeviceList.size();
68f5c9f8bdSJason M. Bills         };
69f5c9f8bdSJason M. Bills     crow::connections::systemBus->async_method_call(
70f5c9f8bdSJason M. Bills         std::move(getPCIeMapCallback), "xyz.openbmc_project.ObjectMapper",
71f5c9f8bdSJason M. Bills         "/xyz/openbmc_project/object_mapper",
72f5c9f8bdSJason M. Bills         "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths",
73f5c9f8bdSJason M. Bills         std::string(pciePath) + "/", 1, std::array<std::string, 0>());
74f5c9f8bdSJason M. Bills }
75f5c9f8bdSJason M. Bills 
767e860f15SJohn Edward Broadbent inline void requestRoutesSystemPCIeDeviceCollection(App& app)
77adbe192aSJason M. Bills {
78adbe192aSJason M. Bills     /**
79adbe192aSJason M. Bills      * Functions triggers appropriate requests on DBus
80adbe192aSJason M. Bills      */
817e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/PCIeDevices/")
82ed398213SEd Tanous         .privileges(redfish::privileges::getPCIeDeviceCollection)
837e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
847e860f15SJohn Edward Broadbent             [](const crow::Request&,
857e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
867e860f15SJohn Edward Broadbent 
87adbe192aSJason M. Bills             {
88adbe192aSJason M. Bills                 asyncResp->res.jsonValue = {
897e860f15SJohn Edward Broadbent                     {"@odata.type",
907e860f15SJohn Edward Broadbent                      "#PCIeDeviceCollection.PCIeDeviceCollection"},
91adbe192aSJason M. Bills                     {"@odata.id", "/redfish/v1/Systems/system/PCIeDevices"},
92adbe192aSJason M. Bills                     {"Name", "PCIe Device Collection"},
93adbe192aSJason M. Bills                     {"Description", "Collection of PCIe Devices"},
94adbe192aSJason M. Bills                     {"Members", nlohmann::json::array()},
95adbe192aSJason M. Bills                     {"Members@odata.count", 0}};
96adbe192aSJason M. Bills                 getPCIeDeviceList(asyncResp, "Members");
977e860f15SJohn Edward Broadbent             });
98f5c9f8bdSJason M. Bills }
99f5c9f8bdSJason M. Bills 
10062cd45afSSpencer Ku inline std::optional<std::string>
10162cd45afSSpencer Ku     redfishPcieGenerationFromDbus(const std::string& generationInUse)
10262cd45afSSpencer Ku {
10362cd45afSSpencer Ku     if (generationInUse ==
10462cd45afSSpencer Ku         "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen1")
10562cd45afSSpencer Ku     {
10662cd45afSSpencer Ku         return "Gen1";
10762cd45afSSpencer Ku     }
10862cd45afSSpencer Ku     if (generationInUse ==
10962cd45afSSpencer Ku         "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen2")
11062cd45afSSpencer Ku     {
11162cd45afSSpencer Ku         return "Gen2";
11262cd45afSSpencer Ku     }
11362cd45afSSpencer Ku     if (generationInUse ==
11462cd45afSSpencer Ku         "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen3")
11562cd45afSSpencer Ku     {
11662cd45afSSpencer Ku         return "Gen3";
11762cd45afSSpencer Ku     }
11862cd45afSSpencer Ku     if (generationInUse ==
11962cd45afSSpencer Ku         "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen4")
12062cd45afSSpencer Ku     {
12162cd45afSSpencer Ku         return "Gen4";
12262cd45afSSpencer Ku     }
12362cd45afSSpencer Ku     if (generationInUse ==
12462cd45afSSpencer Ku         "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen5")
12562cd45afSSpencer Ku     {
12662cd45afSSpencer Ku         return "Gen5";
12762cd45afSSpencer Ku     }
12862cd45afSSpencer Ku     if (generationInUse.empty() ||
12962cd45afSSpencer Ku         generationInUse ==
13062cd45afSSpencer Ku             "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Unknown")
13162cd45afSSpencer Ku     {
13262cd45afSSpencer Ku         return "";
13362cd45afSSpencer Ku     }
13462cd45afSSpencer Ku 
13562cd45afSSpencer Ku     // The value is not unknown or Gen1-5, need return an internal error.
13662cd45afSSpencer Ku     return std::nullopt;
13762cd45afSSpencer Ku }
13862cd45afSSpencer Ku 
1397e860f15SJohn Edward Broadbent inline void requestRoutesSystemPCIeDevice(App& app)
140f5c9f8bdSJason M. Bills {
1417e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/PCIeDevices/<str>/")
142ed398213SEd Tanous         .privileges(redfish::privileges::getPCIeDevice)
1437e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
1447e860f15SJohn Edward Broadbent             [](const crow::Request&,
1457e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1467e860f15SJohn Edward Broadbent                const std::string& device)
147f5c9f8bdSJason M. Bills 
1487e860f15SJohn Edward Broadbent             {
149168e20c1SEd Tanous                 auto getPCIeDeviceCallback =
150*b9d36b47SEd Tanous                     [asyncResp, device](const boost::system::error_code ec,
151*b9d36b47SEd Tanous                                         const dbus::utility::DBusPropertiesMap&
1521214b7e7SGunnar Mills                                             pcieDevProperties) {
153f5c9f8bdSJason M. Bills                         if (ec)
154f5c9f8bdSJason M. Bills                         {
155f5c9f8bdSJason M. Bills                             BMCWEB_LOG_DEBUG
156f5c9f8bdSJason M. Bills                                 << "failed to get PCIe Device properties ec: "
157271584abSEd Tanous                                 << ec.value() << ": " << ec.message();
158168e20c1SEd Tanous                             if (ec.value() == boost::system::linux_error::
159168e20c1SEd Tanous                                                   bad_request_descriptor)
160f5c9f8bdSJason M. Bills                             {
161168e20c1SEd Tanous                                 messages::resourceNotFound(
162168e20c1SEd Tanous                                     asyncResp->res, "PCIeDevice", device);
163f5c9f8bdSJason M. Bills                             }
164f5c9f8bdSJason M. Bills                             else
165f5c9f8bdSJason M. Bills                             {
166f5c9f8bdSJason M. Bills                                 messages::internalError(asyncResp->res);
167f5c9f8bdSJason M. Bills                             }
168f5c9f8bdSJason M. Bills                             return;
169f5c9f8bdSJason M. Bills                         }
170f5c9f8bdSJason M. Bills 
171f5c9f8bdSJason M. Bills                         asyncResp->res.jsonValue = {
172dede6a98SJason M. Bills                             {"@odata.type", "#PCIeDevice.v1_4_0.PCIeDevice"},
173f5c9f8bdSJason M. Bills                             {"@odata.id",
174168e20c1SEd Tanous                              "/redfish/v1/Systems/system/PCIeDevices/" +
175168e20c1SEd Tanous                                  device},
176f5c9f8bdSJason M. Bills                             {"Name", "PCIe Device"},
177f5c9f8bdSJason M. Bills                             {"Id", device}};
178*b9d36b47SEd Tanous                         asyncResp->res.jsonValue["PCIeFunctions"] = {
179*b9d36b47SEd Tanous                             {"@odata.id",
180*b9d36b47SEd Tanous                              "/redfish/v1/Systems/system/PCIeDevices/" +
181*b9d36b47SEd Tanous                                  device + "/PCIeFunctions"}};
182*b9d36b47SEd Tanous                         for (const auto& property : pcieDevProperties)
183f5c9f8bdSJason M. Bills                         {
184*b9d36b47SEd Tanous                             const std::string* propertyString =
185*b9d36b47SEd Tanous                                 std::get_if<std::string>(&property.second);
186*b9d36b47SEd Tanous                             if (property.first == "Manufacturer")
187*b9d36b47SEd Tanous                             {
188*b9d36b47SEd Tanous                                 if (propertyString == nullptr)
189*b9d36b47SEd Tanous                                 {
190*b9d36b47SEd Tanous                                     messages::internalError(asyncResp->res);
191*b9d36b47SEd Tanous                                     return;
192*b9d36b47SEd Tanous                                 }
193168e20c1SEd Tanous                                 asyncResp->res.jsonValue["Manufacturer"] =
194*b9d36b47SEd Tanous                                     *propertyString;
195168e20c1SEd Tanous                             }
196*b9d36b47SEd Tanous                             if (property.first == "DeviceType")
197168e20c1SEd Tanous                             {
198*b9d36b47SEd Tanous                                 if (propertyString == nullptr)
199*b9d36b47SEd Tanous                                 {
200*b9d36b47SEd Tanous                                     messages::internalError(asyncResp->res);
201*b9d36b47SEd Tanous                                     return;
202168e20c1SEd Tanous                                 }
203*b9d36b47SEd Tanous                                 asyncResp->res.jsonValue["DeviceType"] =
204*b9d36b47SEd Tanous                                     *propertyString;
205f5c9f8bdSJason M. Bills                             }
206*b9d36b47SEd Tanous                             if (property.first == "DeviceType")
207f5c9f8bdSJason M. Bills                             {
208*b9d36b47SEd Tanous                                 if (propertyString == nullptr)
209*b9d36b47SEd Tanous                                 {
210*b9d36b47SEd Tanous                                     messages::internalError(asyncResp->res);
211*b9d36b47SEd Tanous                                     return;
212f5c9f8bdSJason M. Bills                                 }
213*b9d36b47SEd Tanous                                 asyncResp->res.jsonValue["DeviceType"] =
214*b9d36b47SEd Tanous                                     *propertyString;
215*b9d36b47SEd Tanous                             }
216*b9d36b47SEd Tanous                             if (property.first == "GenerationInUse")
21762cd45afSSpencer Ku                             {
218*b9d36b47SEd Tanous                                 if (propertyString == nullptr)
219*b9d36b47SEd Tanous                                 {
220*b9d36b47SEd Tanous                                     messages::internalError(asyncResp->res);
221*b9d36b47SEd Tanous                                     return;
222*b9d36b47SEd Tanous                                 }
22362cd45afSSpencer Ku                                 std::optional<std::string> generationInUse =
224*b9d36b47SEd Tanous                                     redfishPcieGenerationFromDbus(
225*b9d36b47SEd Tanous                                         *propertyString);
22662cd45afSSpencer Ku                                 if (!generationInUse)
22762cd45afSSpencer Ku                                 {
22862cd45afSSpencer Ku                                     messages::internalError(asyncResp->res);
22962cd45afSSpencer Ku                                     return;
23062cd45afSSpencer Ku                                 }
23126f6976fSEd Tanous                                 if (generationInUse->empty())
23262cd45afSSpencer Ku                                 {
23362cd45afSSpencer Ku                                     // unknown, no need to handle
23462cd45afSSpencer Ku                                     return;
23562cd45afSSpencer Ku                                 }
236168e20c1SEd Tanous                                 asyncResp->res
237213ffc70SAnjaliintel-21                                     .jsonValue["PCIeInterface"]["PCIeType"] =
23862cd45afSSpencer Ku                                     *generationInUse;
23962cd45afSSpencer Ku                             }
240*b9d36b47SEd Tanous                         }
241dede6a98SJason M. Bills                     };
242dede6a98SJason M. Bills                 std::string escapedPath = std::string(pciePath) + "/" + device;
243dede6a98SJason M. Bills                 dbus::utility::escapePathForDbus(escapedPath);
244dede6a98SJason M. Bills                 crow::connections::systemBus->async_method_call(
245dede6a98SJason M. Bills                     std::move(getPCIeDeviceCallback), pcieService, escapedPath,
2467e860f15SJohn Edward Broadbent                     "org.freedesktop.DBus.Properties", "GetAll",
2477e860f15SJohn Edward Broadbent                     pcieDeviceInterface);
2487e860f15SJohn Edward Broadbent             });
249dede6a98SJason M. Bills }
250dede6a98SJason M. Bills 
2517e860f15SJohn Edward Broadbent inline void requestRoutesSystemPCIeFunctionCollection(App& app)
2527e860f15SJohn Edward Broadbent {
253dede6a98SJason M. Bills     /**
254dede6a98SJason M. Bills      * Functions triggers appropriate requests on DBus
255dede6a98SJason M. Bills      */
2567e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app,
2577e860f15SJohn Edward Broadbent                  "/redfish/v1/Systems/system/PCIeDevices/<str>/PCIeFunctions/")
258ed398213SEd Tanous         .privileges(redfish::privileges::getPCIeFunctionCollection)
2597e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
2607e860f15SJohn Edward Broadbent             [](const crow::Request&,
2617e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2627e860f15SJohn Edward Broadbent                const std::string& device)
2637e860f15SJohn Edward Broadbent 
264dede6a98SJason M. Bills             {
265dede6a98SJason M. Bills                 asyncResp->res.jsonValue = {
2667e860f15SJohn Edward Broadbent                     {"@odata.type",
2677e860f15SJohn Edward Broadbent                      "#PCIeFunctionCollection.PCIeFunctionCollection"},
2687e860f15SJohn Edward Broadbent                     {"@odata.id", "/redfish/v1/Systems/system/PCIeDevices/" +
2697e860f15SJohn Edward Broadbent                                       device + "/PCIeFunctions"},
270dede6a98SJason M. Bills                     {"Name", "PCIe Function Collection"},
271dede6a98SJason M. Bills                     {"Description",
272dede6a98SJason M. Bills                      "Collection of PCIe Functions for PCIe Device " + device}};
273dede6a98SJason M. Bills 
274*b9d36b47SEd Tanous                 auto getPCIeDeviceCallback =
275*b9d36b47SEd Tanous                     [asyncResp, device](const boost::system::error_code ec,
276*b9d36b47SEd Tanous                                         const dbus::utility::DBusPropertiesMap&
2777e860f15SJohn Edward Broadbent                                             pcieDevProperties) {
2787e860f15SJohn Edward Broadbent                         if (ec)
2797e860f15SJohn Edward Broadbent                         {
2807e860f15SJohn Edward Broadbent                             BMCWEB_LOG_DEBUG
2817e860f15SJohn Edward Broadbent                                 << "failed to get PCIe Device properties ec: "
2827e860f15SJohn Edward Broadbent                                 << ec.value() << ": " << ec.message();
283*b9d36b47SEd Tanous                             if (ec.value() == boost::system::linux_error::
284*b9d36b47SEd Tanous                                                   bad_request_descriptor)
2857e860f15SJohn Edward Broadbent                             {
286*b9d36b47SEd Tanous                                 messages::resourceNotFound(
287*b9d36b47SEd Tanous                                     asyncResp->res, "PCIeDevice", device);
2887e860f15SJohn Edward Broadbent                             }
2897e860f15SJohn Edward Broadbent                             else
2907e860f15SJohn Edward Broadbent                             {
2917e860f15SJohn Edward Broadbent                                 messages::internalError(asyncResp->res);
2927e860f15SJohn Edward Broadbent                             }
2937e860f15SJohn Edward Broadbent                             return;
2947e860f15SJohn Edward Broadbent                         }
2957e860f15SJohn Edward Broadbent 
2967e860f15SJohn Edward Broadbent                         nlohmann::json& pcieFunctionList =
2977e860f15SJohn Edward Broadbent                             asyncResp->res.jsonValue["Members"];
2987e860f15SJohn Edward Broadbent                         pcieFunctionList = nlohmann::json::array();
2997e860f15SJohn Edward Broadbent                         static constexpr const int maxPciFunctionNum = 8;
300*b9d36b47SEd Tanous                         for (int functionNum = 0;
301*b9d36b47SEd Tanous                              functionNum < maxPciFunctionNum; functionNum++)
3027e860f15SJohn Edward Broadbent                         {
303*b9d36b47SEd Tanous                             // Check if this function exists by looking for a
304*b9d36b47SEd Tanous                             // device ID
3057e860f15SJohn Edward Broadbent                             std::string devIDProperty =
3067e860f15SJohn Edward Broadbent                                 "Function" + std::to_string(functionNum) +
3077e860f15SJohn Edward Broadbent                                 "DeviceId";
308*b9d36b47SEd Tanous                             const std::string* property = nullptr;
309*b9d36b47SEd Tanous                             for (const auto& propEntry : pcieDevProperties)
3107e860f15SJohn Edward Broadbent                             {
311*b9d36b47SEd Tanous                                 if (propEntry.first == devIDProperty)
312*b9d36b47SEd Tanous                                 {
313*b9d36b47SEd Tanous                                     property = std::get_if<std::string>(
314*b9d36b47SEd Tanous                                         &propEntry.second);
315*b9d36b47SEd Tanous                                 }
316*b9d36b47SEd Tanous                             }
317*b9d36b47SEd Tanous                             if (property == nullptr || !property->empty())
318*b9d36b47SEd Tanous                             {
319*b9d36b47SEd Tanous                                 return;
320*b9d36b47SEd Tanous                             }
3217e860f15SJohn Edward Broadbent                             pcieFunctionList.push_back(
3227e860f15SJohn Edward Broadbent                                 {{"@odata.id",
3237e860f15SJohn Edward Broadbent                                   "/redfish/v1/Systems/system/PCIeDevices/" +
3247e860f15SJohn Edward Broadbent                                       device + "/PCIeFunctions/" +
3257e860f15SJohn Edward Broadbent                                       std::to_string(functionNum)}});
3267e860f15SJohn Edward Broadbent                         }
327a818d15aSJiaqing Zhao                         asyncResp->res.jsonValue["Members@odata.count"] =
3287e860f15SJohn Edward Broadbent                             pcieFunctionList.size();
3297e860f15SJohn Edward Broadbent                     };
3307e860f15SJohn Edward Broadbent                 std::string escapedPath = std::string(pciePath) + "/" + device;
3317e860f15SJohn Edward Broadbent                 dbus::utility::escapePathForDbus(escapedPath);
3327e860f15SJohn Edward Broadbent                 crow::connections::systemBus->async_method_call(
3337e860f15SJohn Edward Broadbent                     std::move(getPCIeDeviceCallback), pcieService, escapedPath,
3347e860f15SJohn Edward Broadbent                     "org.freedesktop.DBus.Properties", "GetAll",
3357e860f15SJohn Edward Broadbent                     pcieDeviceInterface);
3367e860f15SJohn Edward Broadbent             });
3377e860f15SJohn Edward Broadbent }
3387e860f15SJohn Edward Broadbent 
3397e860f15SJohn Edward Broadbent inline void requestRoutesSystemPCIeFunction(App& app)
3407e860f15SJohn Edward Broadbent {
3417e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(
3427e860f15SJohn Edward Broadbent         app,
3437e860f15SJohn Edward Broadbent         "/redfish/v1/Systems/system/PCIeDevices/<str>/PCIeFunctions/<str>/")
344ed398213SEd Tanous         .privileges(redfish::privileges::getPCIeFunction)
3457e860f15SJohn Edward Broadbent         .methods(
3467e860f15SJohn Edward Broadbent             boost::beast::http::verb::get)([](const crow::Request&,
3477e860f15SJohn Edward Broadbent                                               const std::shared_ptr<
3487e860f15SJohn Edward Broadbent                                                   bmcweb::AsyncResp>& asyncResp,
3497e860f15SJohn Edward Broadbent                                               const std::string& device,
3507e860f15SJohn Edward Broadbent                                               const std::string& function) {
351168e20c1SEd Tanous             auto getPCIeDeviceCallback =
352168e20c1SEd Tanous                 [asyncResp, device, function](
3537e860f15SJohn Edward Broadbent                     const boost::system::error_code ec,
354*b9d36b47SEd Tanous                     const dbus::utility::DBusPropertiesMap& pcieDevProperties) {
355dede6a98SJason M. Bills                     if (ec)
356dede6a98SJason M. Bills                     {
357dede6a98SJason M. Bills                         BMCWEB_LOG_DEBUG
358dede6a98SJason M. Bills                             << "failed to get PCIe Device properties ec: "
359dede6a98SJason M. Bills                             << ec.value() << ": " << ec.message();
360dede6a98SJason M. Bills                         if (ec.value() ==
361dede6a98SJason M. Bills                             boost::system::linux_error::bad_request_descriptor)
362dede6a98SJason M. Bills                         {
363168e20c1SEd Tanous                             messages::resourceNotFound(asyncResp->res,
364168e20c1SEd Tanous                                                        "PCIeDevice", device);
365dede6a98SJason M. Bills                         }
366dede6a98SJason M. Bills                         else
367dede6a98SJason M. Bills                         {
368dede6a98SJason M. Bills                             messages::internalError(asyncResp->res);
369dede6a98SJason M. Bills                         }
370dede6a98SJason M. Bills                         return;
371dede6a98SJason M. Bills                     }
372dede6a98SJason M. Bills 
373f5c9f8bdSJason M. Bills                     // Check if this function exists by looking for a device ID
374*b9d36b47SEd Tanous                     std::string functionName = "Function" + function;
375*b9d36b47SEd Tanous                     std::string devIDProperty = functionName + "DeviceId";
376*b9d36b47SEd Tanous 
377*b9d36b47SEd Tanous                     const std::string* devIdProperty = nullptr;
378*b9d36b47SEd Tanous                     for (const auto& property : pcieDevProperties)
379*b9d36b47SEd Tanous                     {
380*b9d36b47SEd Tanous                         if (property.first == devIDProperty)
381*b9d36b47SEd Tanous                         {
382*b9d36b47SEd Tanous                             devIdProperty =
383*b9d36b47SEd Tanous                                 std::get_if<std::string>(&property.second);
384*b9d36b47SEd Tanous                             continue;
385*b9d36b47SEd Tanous                         }
386*b9d36b47SEd Tanous                     }
387*b9d36b47SEd Tanous                     if (devIdProperty == nullptr || !devIdProperty->empty())
388f5c9f8bdSJason M. Bills                     {
389168e20c1SEd Tanous                         messages::resourceNotFound(asyncResp->res,
390168e20c1SEd Tanous                                                    "PCIeFunction", function);
391f5c9f8bdSJason M. Bills                         return;
392f5c9f8bdSJason M. Bills                     }
393f5c9f8bdSJason M. Bills 
394f5c9f8bdSJason M. Bills                     asyncResp->res.jsonValue = {
395f5c9f8bdSJason M. Bills                         {"@odata.type", "#PCIeFunction.v1_2_0.PCIeFunction"},
396168e20c1SEd Tanous                         {"@odata.id",
397168e20c1SEd Tanous                          "/redfish/v1/Systems/system/PCIeDevices/" + device +
398168e20c1SEd Tanous                              "/PCIeFunctions/" + function},
399f5c9f8bdSJason M. Bills                         {"Name", "PCIe Function"},
400f5c9f8bdSJason M. Bills                         {"Id", function},
401f5c9f8bdSJason M. Bills                         {"FunctionId", std::stoi(function)},
402f5c9f8bdSJason M. Bills                         {"Links",
403f5c9f8bdSJason M. Bills                          {{"PCIeDevice",
404f5c9f8bdSJason M. Bills                            {{"@odata.id",
4057e860f15SJohn Edward Broadbent                              "/redfish/v1/Systems/system/PCIeDevices/" +
4067e860f15SJohn Edward Broadbent                                  device}}}}}};
407f5c9f8bdSJason M. Bills 
408*b9d36b47SEd Tanous                     for (const auto& property : pcieDevProperties)
409f5c9f8bdSJason M. Bills                     {
410*b9d36b47SEd Tanous                         const std::string* strProperty =
411*b9d36b47SEd Tanous                             std::get_if<std::string>(&property.second);
412*b9d36b47SEd Tanous                         if (property.first == functionName + "DeviceId")
413f5c9f8bdSJason M. Bills                         {
414*b9d36b47SEd Tanous                             asyncResp->res.jsonValue["DeviceId"] = *strProperty;
415f5c9f8bdSJason M. Bills                         }
416*b9d36b47SEd Tanous                         if (property.first == functionName + "VendorId")
417f5c9f8bdSJason M. Bills                         {
418*b9d36b47SEd Tanous                             asyncResp->res.jsonValue["VendorId"] = *strProperty;
419f5c9f8bdSJason M. Bills                         }
420*b9d36b47SEd Tanous                         if (property.first == functionName + "FunctionType")
421f5c9f8bdSJason M. Bills                         {
422*b9d36b47SEd Tanous                             asyncResp->res.jsonValue["FunctionType"] =
423*b9d36b47SEd Tanous                                 *strProperty;
424f5c9f8bdSJason M. Bills                         }
425*b9d36b47SEd Tanous                         if (property.first == functionName + "DeviceClass")
426f5c9f8bdSJason M. Bills                         {
427*b9d36b47SEd Tanous                             asyncResp->res.jsonValue["DeviceClass"] =
428*b9d36b47SEd Tanous                                 *strProperty;
429f5c9f8bdSJason M. Bills                         }
430*b9d36b47SEd Tanous                         if (property.first == functionName + "ClassCode")
431f5c9f8bdSJason M. Bills                         {
432*b9d36b47SEd Tanous                             asyncResp->res.jsonValue["ClassCode"] =
433*b9d36b47SEd Tanous                                 *strProperty;
434f5c9f8bdSJason M. Bills                         }
435*b9d36b47SEd Tanous                         if (property.first == functionName + "RevisionId")
436f5c9f8bdSJason M. Bills                         {
437*b9d36b47SEd Tanous                             asyncResp->res.jsonValue["RevisionId"] =
438*b9d36b47SEd Tanous                                 *strProperty;
439f5c9f8bdSJason M. Bills                         }
440*b9d36b47SEd Tanous                         if (property.first == functionName + "SubsystemId")
441*b9d36b47SEd Tanous                         {
442*b9d36b47SEd Tanous                             asyncResp->res.jsonValue["SubsystemId"] =
443*b9d36b47SEd Tanous                                 *strProperty;
444*b9d36b47SEd Tanous                         }
445*b9d36b47SEd Tanous                         if (property.first ==
446*b9d36b47SEd Tanous                             functionName + "SubsystemVendorId")
447f5c9f8bdSJason M. Bills                         {
448168e20c1SEd Tanous                             asyncResp->res.jsonValue["SubsystemVendorId"] =
449*b9d36b47SEd Tanous                                 *strProperty;
450*b9d36b47SEd Tanous                         }
451f5c9f8bdSJason M. Bills                     }
452f5c9f8bdSJason M. Bills                 };
453f5c9f8bdSJason M. Bills             std::string escapedPath = std::string(pciePath) + "/" + device;
454f5c9f8bdSJason M. Bills             dbus::utility::escapePathForDbus(escapedPath);
455f5c9f8bdSJason M. Bills             crow::connections::systemBus->async_method_call(
456f5c9f8bdSJason M. Bills                 std::move(getPCIeDeviceCallback), pcieService, escapedPath,
4577e860f15SJohn Edward Broadbent                 "org.freedesktop.DBus.Properties", "GetAll",
4587e860f15SJohn Edward Broadbent                 pcieDeviceInterface);
4597e860f15SJohn Edward Broadbent         });
460f5c9f8bdSJason M. Bills }
461f5c9f8bdSJason M. Bills 
462f5c9f8bdSJason M. Bills } // namespace redfish
463