xref: /openbmc/bmcweb/features/redfish/lib/pcie.hpp (revision a818d15aa2c5cf583e708c2117a43a7e0bf70914)
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 {
36adbe192aSJason M. Bills     auto getPCIeMapCallback = [asyncResp, name](
37adbe192aSJason M. Bills                                   const boost::system::error_code ec,
38f5c9f8bdSJason M. Bills                                   std::vector<std::string>& pcieDevicePaths) {
39f5c9f8bdSJason M. Bills         if (ec)
40f5c9f8bdSJason M. Bills         {
41a2730f01SAndrew Geissler             BMCWEB_LOG_DEBUG << "no PCIe device paths found ec: "
42f5c9f8bdSJason M. Bills                              << ec.message();
43a2730f01SAndrew Geissler             // Not an error, system just doesn't have PCIe info
44f5c9f8bdSJason M. Bills             return;
45f5c9f8bdSJason M. Bills         }
46adbe192aSJason M. Bills         nlohmann::json& pcieDeviceList = asyncResp->res.jsonValue[name];
47f5c9f8bdSJason M. Bills         pcieDeviceList = nlohmann::json::array();
48f5c9f8bdSJason M. Bills         for (const std::string& pcieDevicePath : pcieDevicePaths)
49f5c9f8bdSJason M. Bills         {
503174e4dfSEd Tanous             size_t devStart = pcieDevicePath.rfind('/');
51f5c9f8bdSJason M. Bills             if (devStart == std::string::npos)
52f5c9f8bdSJason M. Bills             {
53f5c9f8bdSJason M. Bills                 continue;
54f5c9f8bdSJason M. Bills             }
55f5c9f8bdSJason M. Bills 
56f5c9f8bdSJason M. Bills             std::string devName = pcieDevicePath.substr(devStart + 1);
57f5c9f8bdSJason M. Bills             if (devName.empty())
58f5c9f8bdSJason M. Bills             {
59f5c9f8bdSJason M. Bills                 continue;
60f5c9f8bdSJason M. Bills             }
61f5c9f8bdSJason M. Bills             pcieDeviceList.push_back(
62f5c9f8bdSJason M. Bills                 {{"@odata.id",
63f5c9f8bdSJason M. Bills                   "/redfish/v1/Systems/system/PCIeDevices/" + devName}});
64f5c9f8bdSJason M. Bills         }
65adbe192aSJason M. Bills         asyncResp->res.jsonValue[name + "@odata.count"] = pcieDeviceList.size();
66f5c9f8bdSJason M. Bills     };
67f5c9f8bdSJason M. Bills     crow::connections::systemBus->async_method_call(
68f5c9f8bdSJason M. Bills         std::move(getPCIeMapCallback), "xyz.openbmc_project.ObjectMapper",
69f5c9f8bdSJason M. Bills         "/xyz/openbmc_project/object_mapper",
70f5c9f8bdSJason M. Bills         "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths",
71f5c9f8bdSJason M. Bills         std::string(pciePath) + "/", 1, std::array<std::string, 0>());
72f5c9f8bdSJason M. Bills }
73f5c9f8bdSJason M. Bills 
747e860f15SJohn Edward Broadbent inline void requestRoutesSystemPCIeDeviceCollection(App& app)
75adbe192aSJason M. Bills {
76adbe192aSJason M. Bills     /**
77adbe192aSJason M. Bills      * Functions triggers appropriate requests on DBus
78adbe192aSJason M. Bills      */
797e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/PCIeDevices/")
80ed398213SEd Tanous         .privileges(redfish::privileges::getPCIeDeviceCollection)
817e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
827e860f15SJohn Edward Broadbent             [](const crow::Request&,
837e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
847e860f15SJohn Edward Broadbent 
85adbe192aSJason M. Bills             {
86adbe192aSJason M. Bills                 asyncResp->res.jsonValue = {
877e860f15SJohn Edward Broadbent                     {"@odata.type",
887e860f15SJohn Edward Broadbent                      "#PCIeDeviceCollection.PCIeDeviceCollection"},
89adbe192aSJason M. Bills                     {"@odata.id", "/redfish/v1/Systems/system/PCIeDevices"},
90adbe192aSJason M. Bills                     {"Name", "PCIe Device Collection"},
91adbe192aSJason M. Bills                     {"Description", "Collection of PCIe Devices"},
92adbe192aSJason M. Bills                     {"Members", nlohmann::json::array()},
93adbe192aSJason M. Bills                     {"Members@odata.count", 0}};
94adbe192aSJason M. Bills                 getPCIeDeviceList(asyncResp, "Members");
957e860f15SJohn Edward Broadbent             });
96f5c9f8bdSJason M. Bills }
97f5c9f8bdSJason M. Bills 
9862cd45afSSpencer Ku inline std::optional<std::string>
9962cd45afSSpencer Ku     redfishPcieGenerationFromDbus(const std::string& generationInUse)
10062cd45afSSpencer Ku {
10162cd45afSSpencer Ku     if (generationInUse ==
10262cd45afSSpencer Ku         "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen1")
10362cd45afSSpencer Ku     {
10462cd45afSSpencer Ku         return "Gen1";
10562cd45afSSpencer Ku     }
10662cd45afSSpencer Ku     if (generationInUse ==
10762cd45afSSpencer Ku         "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen2")
10862cd45afSSpencer Ku     {
10962cd45afSSpencer Ku         return "Gen2";
11062cd45afSSpencer Ku     }
11162cd45afSSpencer Ku     if (generationInUse ==
11262cd45afSSpencer Ku         "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen3")
11362cd45afSSpencer Ku     {
11462cd45afSSpencer Ku         return "Gen3";
11562cd45afSSpencer Ku     }
11662cd45afSSpencer Ku     if (generationInUse ==
11762cd45afSSpencer Ku         "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen4")
11862cd45afSSpencer Ku     {
11962cd45afSSpencer Ku         return "Gen4";
12062cd45afSSpencer Ku     }
12162cd45afSSpencer Ku     if (generationInUse ==
12262cd45afSSpencer Ku         "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen5")
12362cd45afSSpencer Ku     {
12462cd45afSSpencer Ku         return "Gen5";
12562cd45afSSpencer Ku     }
12662cd45afSSpencer Ku     if (generationInUse.empty() ||
12762cd45afSSpencer Ku         generationInUse ==
12862cd45afSSpencer Ku             "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Unknown")
12962cd45afSSpencer Ku     {
13062cd45afSSpencer Ku         return "";
13162cd45afSSpencer Ku     }
13262cd45afSSpencer Ku 
13362cd45afSSpencer Ku     // The value is not unknown or Gen1-5, need return an internal error.
13462cd45afSSpencer Ku     return std::nullopt;
13562cd45afSSpencer Ku }
13662cd45afSSpencer Ku 
1377e860f15SJohn Edward Broadbent inline void requestRoutesSystemPCIeDevice(App& app)
138f5c9f8bdSJason M. Bills {
1397e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/PCIeDevices/<str>/")
140ed398213SEd Tanous         .privileges(redfish::privileges::getPCIeDevice)
1417e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
1427e860f15SJohn Edward Broadbent             [](const crow::Request&,
1437e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1447e860f15SJohn Edward Broadbent                const std::string& device)
145f5c9f8bdSJason M. Bills 
1467e860f15SJohn Edward Broadbent             {
147168e20c1SEd Tanous                 auto getPCIeDeviceCallback =
148168e20c1SEd Tanous                     [asyncResp,
149168e20c1SEd Tanous                      device](const boost::system::error_code ec,
1507e860f15SJohn Edward Broadbent                              boost::container::flat_map<
151168e20c1SEd Tanous                                  std::string, dbus::utility::DbusVariantType>&
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}};
178f5c9f8bdSJason M. Bills 
1798d78b7a9SPatrick Williams                         if (std::string* property = std::get_if<std::string>(
180f5c9f8bdSJason M. Bills                                 &pcieDevProperties["Manufacturer"]);
181f5c9f8bdSJason M. Bills                             property)
182f5c9f8bdSJason M. Bills                         {
183168e20c1SEd Tanous                             asyncResp->res.jsonValue["Manufacturer"] =
184168e20c1SEd Tanous                                 *property;
185168e20c1SEd Tanous                         }
186168e20c1SEd Tanous 
187168e20c1SEd Tanous                         if (std::string* property = std::get_if<std::string>(
188168e20c1SEd Tanous                                 &pcieDevProperties["DeviceType"]);
189168e20c1SEd Tanous                             property)
190168e20c1SEd Tanous                         {
191168e20c1SEd Tanous                             asyncResp->res.jsonValue["DeviceType"] = *property;
192168e20c1SEd Tanous                         }
193168e20c1SEd Tanous 
194168e20c1SEd Tanous                         if (std::string* property = std::get_if<std::string>(
195168e20c1SEd Tanous                                 &pcieDevProperties["Manufacturer"]);
196168e20c1SEd Tanous                             property)
197168e20c1SEd Tanous                         {
198168e20c1SEd Tanous                             asyncResp->res.jsonValue["Manufacturer"] =
199168e20c1SEd Tanous                                 *property;
200f5c9f8bdSJason M. Bills                         }
201f5c9f8bdSJason M. Bills 
2028d78b7a9SPatrick Williams                         if (std::string* property = std::get_if<std::string>(
203f5c9f8bdSJason M. Bills                                 &pcieDevProperties["DeviceType"]);
204f5c9f8bdSJason M. Bills                             property)
205f5c9f8bdSJason M. Bills                         {
206f5c9f8bdSJason M. Bills                             asyncResp->res.jsonValue["DeviceType"] = *property;
207f5c9f8bdSJason M. Bills                         }
208f5c9f8bdSJason M. Bills 
20962cd45afSSpencer Ku                         if (std::string* property = std::get_if<std::string>(
21062cd45afSSpencer Ku                                 &pcieDevProperties["GenerationInUse"]);
21162cd45afSSpencer Ku                             property)
21262cd45afSSpencer Ku                         {
21362cd45afSSpencer Ku                             std::optional<std::string> generationInUse =
21462cd45afSSpencer Ku                                 redfishPcieGenerationFromDbus(*property);
21562cd45afSSpencer Ku                             if (!generationInUse)
21662cd45afSSpencer Ku                             {
21762cd45afSSpencer Ku                                 messages::internalError(asyncResp->res);
21862cd45afSSpencer Ku                                 return;
21962cd45afSSpencer Ku                             }
22062cd45afSSpencer Ku                             if (*generationInUse == "")
22162cd45afSSpencer Ku                             {
22262cd45afSSpencer Ku                                 // unknown, no need to handle
22362cd45afSSpencer Ku                                 return;
22462cd45afSSpencer Ku                             }
225168e20c1SEd Tanous                             asyncResp->res
226168e20c1SEd Tanous                                 .jsonValue["PCIeInterface"]["PcieType"] =
22762cd45afSSpencer Ku                                 *generationInUse;
22862cd45afSSpencer Ku                         }
229dede6a98SJason M. Bills                         asyncResp->res.jsonValue["PCIeFunctions"] = {
2307e860f15SJohn Edward Broadbent                             {"@odata.id",
231168e20c1SEd Tanous                              "/redfish/v1/Systems/system/PCIeDevices/" +
232168e20c1SEd Tanous                                  device + "/PCIeFunctions"}};
233dede6a98SJason M. Bills                     };
234dede6a98SJason M. Bills                 std::string escapedPath = std::string(pciePath) + "/" + device;
235dede6a98SJason M. Bills                 dbus::utility::escapePathForDbus(escapedPath);
236dede6a98SJason M. Bills                 crow::connections::systemBus->async_method_call(
237dede6a98SJason M. Bills                     std::move(getPCIeDeviceCallback), pcieService, escapedPath,
2387e860f15SJohn Edward Broadbent                     "org.freedesktop.DBus.Properties", "GetAll",
2397e860f15SJohn Edward Broadbent                     pcieDeviceInterface);
2407e860f15SJohn Edward Broadbent             });
241dede6a98SJason M. Bills }
242dede6a98SJason M. Bills 
2437e860f15SJohn Edward Broadbent inline void requestRoutesSystemPCIeFunctionCollection(App& app)
2447e860f15SJohn Edward Broadbent {
245dede6a98SJason M. Bills     /**
246dede6a98SJason M. Bills      * Functions triggers appropriate requests on DBus
247dede6a98SJason M. Bills      */
2487e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app,
2497e860f15SJohn Edward Broadbent                  "/redfish/v1/Systems/system/PCIeDevices/<str>/PCIeFunctions/")
250ed398213SEd Tanous         .privileges(redfish::privileges::getPCIeFunctionCollection)
2517e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
2527e860f15SJohn Edward Broadbent             [](const crow::Request&,
2537e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2547e860f15SJohn Edward Broadbent                const std::string& device)
2557e860f15SJohn Edward Broadbent 
256dede6a98SJason M. Bills             {
257dede6a98SJason M. Bills                 asyncResp->res.jsonValue = {
2587e860f15SJohn Edward Broadbent                     {"@odata.type",
2597e860f15SJohn Edward Broadbent                      "#PCIeFunctionCollection.PCIeFunctionCollection"},
2607e860f15SJohn Edward Broadbent                     {"@odata.id", "/redfish/v1/Systems/system/PCIeDevices/" +
2617e860f15SJohn Edward Broadbent                                       device + "/PCIeFunctions"},
262dede6a98SJason M. Bills                     {"Name", "PCIe Function Collection"},
263dede6a98SJason M. Bills                     {"Description",
264dede6a98SJason M. Bills                      "Collection of PCIe Functions for PCIe Device " + device}};
265dede6a98SJason M. Bills 
2667e860f15SJohn Edward Broadbent                 auto getPCIeDeviceCallback = [asyncResp, device](
2677e860f15SJohn Edward Broadbent                                                  const boost::system::error_code
2687e860f15SJohn Edward Broadbent                                                      ec,
2697e860f15SJohn Edward Broadbent                                                  boost::container::flat_map<
2707e860f15SJohn Edward Broadbent                                                      std::string,
271168e20c1SEd Tanous                                                      dbus::utility::
272168e20c1SEd Tanous                                                          DbusVariantType>&
2737e860f15SJohn Edward Broadbent                                                      pcieDevProperties) {
2747e860f15SJohn Edward Broadbent                     if (ec)
2757e860f15SJohn Edward Broadbent                     {
2767e860f15SJohn Edward Broadbent                         BMCWEB_LOG_DEBUG
2777e860f15SJohn Edward Broadbent                             << "failed to get PCIe Device properties ec: "
2787e860f15SJohn Edward Broadbent                             << ec.value() << ": " << ec.message();
2797e860f15SJohn Edward Broadbent                         if (ec.value() ==
2807e860f15SJohn Edward Broadbent                             boost::system::linux_error::bad_request_descriptor)
2817e860f15SJohn Edward Broadbent                         {
2827e860f15SJohn Edward Broadbent                             messages::resourceNotFound(asyncResp->res,
2837e860f15SJohn Edward Broadbent                                                        "PCIeDevice", device);
2847e860f15SJohn Edward Broadbent                         }
2857e860f15SJohn Edward Broadbent                         else
2867e860f15SJohn Edward Broadbent                         {
2877e860f15SJohn Edward Broadbent                             messages::internalError(asyncResp->res);
2887e860f15SJohn Edward Broadbent                         }
2897e860f15SJohn Edward Broadbent                         return;
2907e860f15SJohn Edward Broadbent                     }
2917e860f15SJohn Edward Broadbent 
2927e860f15SJohn Edward Broadbent                     nlohmann::json& pcieFunctionList =
2937e860f15SJohn Edward Broadbent                         asyncResp->res.jsonValue["Members"];
2947e860f15SJohn Edward Broadbent                     pcieFunctionList = nlohmann::json::array();
2957e860f15SJohn Edward Broadbent                     static constexpr const int maxPciFunctionNum = 8;
2967e860f15SJohn Edward Broadbent                     for (int functionNum = 0; functionNum < maxPciFunctionNum;
2977e860f15SJohn Edward Broadbent                          functionNum++)
2987e860f15SJohn Edward Broadbent                     {
2997e860f15SJohn Edward Broadbent                         // Check if this function exists by looking for a device
3007e860f15SJohn Edward Broadbent                         // ID
3017e860f15SJohn Edward Broadbent                         std::string devIDProperty =
3027e860f15SJohn Edward Broadbent                             "Function" + std::to_string(functionNum) +
3037e860f15SJohn Edward Broadbent                             "DeviceId";
3047e860f15SJohn Edward Broadbent                         std::string* property = std::get_if<std::string>(
3057e860f15SJohn Edward Broadbent                             &pcieDevProperties[devIDProperty]);
3067e860f15SJohn Edward Broadbent                         if (property && !property->empty())
3077e860f15SJohn Edward Broadbent                         {
3087e860f15SJohn Edward Broadbent                             pcieFunctionList.push_back(
3097e860f15SJohn Edward Broadbent                                 {{"@odata.id",
3107e860f15SJohn Edward Broadbent                                   "/redfish/v1/Systems/system/PCIeDevices/" +
3117e860f15SJohn Edward Broadbent                                       device + "/PCIeFunctions/" +
3127e860f15SJohn Edward Broadbent                                       std::to_string(functionNum)}});
3137e860f15SJohn Edward Broadbent                         }
3147e860f15SJohn Edward Broadbent                     }
315*a818d15aSJiaqing Zhao                     asyncResp->res.jsonValue["Members@odata.count"] =
3167e860f15SJohn Edward Broadbent                         pcieFunctionList.size();
3177e860f15SJohn Edward Broadbent                 };
3187e860f15SJohn Edward Broadbent                 std::string escapedPath = std::string(pciePath) + "/" + device;
3197e860f15SJohn Edward Broadbent                 dbus::utility::escapePathForDbus(escapedPath);
3207e860f15SJohn Edward Broadbent                 crow::connections::systemBus->async_method_call(
3217e860f15SJohn Edward Broadbent                     std::move(getPCIeDeviceCallback), pcieService, escapedPath,
3227e860f15SJohn Edward Broadbent                     "org.freedesktop.DBus.Properties", "GetAll",
3237e860f15SJohn Edward Broadbent                     pcieDeviceInterface);
3247e860f15SJohn Edward Broadbent             });
3257e860f15SJohn Edward Broadbent }
3267e860f15SJohn Edward Broadbent 
3277e860f15SJohn Edward Broadbent inline void requestRoutesSystemPCIeFunction(App& app)
3287e860f15SJohn Edward Broadbent {
3297e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(
3307e860f15SJohn Edward Broadbent         app,
3317e860f15SJohn Edward Broadbent         "/redfish/v1/Systems/system/PCIeDevices/<str>/PCIeFunctions/<str>/")
332ed398213SEd Tanous         .privileges(redfish::privileges::getPCIeFunction)
3337e860f15SJohn Edward Broadbent         .methods(
3347e860f15SJohn Edward Broadbent             boost::beast::http::verb::get)([](const crow::Request&,
3357e860f15SJohn Edward Broadbent                                               const std::shared_ptr<
3367e860f15SJohn Edward Broadbent                                                   bmcweb::AsyncResp>& asyncResp,
3377e860f15SJohn Edward Broadbent                                               const std::string& device,
3387e860f15SJohn Edward Broadbent                                               const std::string& function) {
339168e20c1SEd Tanous             auto getPCIeDeviceCallback =
340168e20c1SEd Tanous                 [asyncResp, device, function](
3417e860f15SJohn Edward Broadbent                     const boost::system::error_code ec,
342168e20c1SEd Tanous                     boost::container::flat_map<std::string,
343168e20c1SEd Tanous                                                dbus::utility::DbusVariantType>&
3441214b7e7SGunnar Mills                         pcieDevProperties) {
345dede6a98SJason M. Bills                     if (ec)
346dede6a98SJason M. Bills                     {
347dede6a98SJason M. Bills                         BMCWEB_LOG_DEBUG
348dede6a98SJason M. Bills                             << "failed to get PCIe Device properties ec: "
349dede6a98SJason M. Bills                             << ec.value() << ": " << ec.message();
350dede6a98SJason M. Bills                         if (ec.value() ==
351dede6a98SJason M. Bills                             boost::system::linux_error::bad_request_descriptor)
352dede6a98SJason M. Bills                         {
353168e20c1SEd Tanous                             messages::resourceNotFound(asyncResp->res,
354168e20c1SEd Tanous                                                        "PCIeDevice", device);
355dede6a98SJason M. Bills                         }
356dede6a98SJason M. Bills                         else
357dede6a98SJason M. Bills                         {
358dede6a98SJason M. Bills                             messages::internalError(asyncResp->res);
359dede6a98SJason M. Bills                         }
360dede6a98SJason M. Bills                         return;
361dede6a98SJason M. Bills                     }
362dede6a98SJason M. Bills 
363f5c9f8bdSJason M. Bills                     // Check if this function exists by looking for a device ID
364168e20c1SEd Tanous                     std::string devIDProperty =
365168e20c1SEd Tanous                         "Function" + function + "DeviceId";
3667e860f15SJohn Edward Broadbent                     if (std::string* property = std::get_if<std::string>(
3677e860f15SJohn Edward Broadbent                             &pcieDevProperties[devIDProperty]);
368f5c9f8bdSJason M. Bills                         property && property->empty())
369f5c9f8bdSJason M. Bills                     {
370168e20c1SEd Tanous                         messages::resourceNotFound(asyncResp->res,
371168e20c1SEd Tanous                                                    "PCIeFunction", function);
372f5c9f8bdSJason M. Bills                         return;
373f5c9f8bdSJason M. Bills                     }
374f5c9f8bdSJason M. Bills 
375f5c9f8bdSJason M. Bills                     asyncResp->res.jsonValue = {
376f5c9f8bdSJason M. Bills                         {"@odata.type", "#PCIeFunction.v1_2_0.PCIeFunction"},
377168e20c1SEd Tanous                         {"@odata.id",
378168e20c1SEd Tanous                          "/redfish/v1/Systems/system/PCIeDevices/" + device +
379168e20c1SEd Tanous                              "/PCIeFunctions/" + function},
380f5c9f8bdSJason M. Bills                         {"Name", "PCIe Function"},
381f5c9f8bdSJason M. Bills                         {"Id", function},
382f5c9f8bdSJason M. Bills                         {"FunctionId", std::stoi(function)},
383f5c9f8bdSJason M. Bills                         {"Links",
384f5c9f8bdSJason M. Bills                          {{"PCIeDevice",
385f5c9f8bdSJason M. Bills                            {{"@odata.id",
3867e860f15SJohn Edward Broadbent                              "/redfish/v1/Systems/system/PCIeDevices/" +
3877e860f15SJohn Edward Broadbent                                  device}}}}}};
388f5c9f8bdSJason M. Bills 
3898d78b7a9SPatrick Williams                     if (std::string* property = std::get_if<std::string>(
390168e20c1SEd Tanous                             &pcieDevProperties["Function" + function +
391168e20c1SEd Tanous                                                "DeviceId"]);
392f5c9f8bdSJason M. Bills                         property)
393f5c9f8bdSJason M. Bills                     {
394f5c9f8bdSJason M. Bills                         asyncResp->res.jsonValue["DeviceId"] = *property;
395f5c9f8bdSJason M. Bills                     }
396f5c9f8bdSJason M. Bills 
3978d78b7a9SPatrick Williams                     if (std::string* property = std::get_if<std::string>(
398168e20c1SEd Tanous                             &pcieDevProperties["Function" + function +
399168e20c1SEd Tanous                                                "VendorId"]);
400f5c9f8bdSJason M. Bills                         property)
401f5c9f8bdSJason M. Bills                     {
402f5c9f8bdSJason M. Bills                         asyncResp->res.jsonValue["VendorId"] = *property;
403f5c9f8bdSJason M. Bills                     }
404f5c9f8bdSJason M. Bills 
4058d78b7a9SPatrick Williams                     if (std::string* property = std::get_if<std::string>(
4067e860f15SJohn Edward Broadbent                             &pcieDevProperties["Function" + function +
4077e860f15SJohn Edward Broadbent                                                "FunctionType"]);
408f5c9f8bdSJason M. Bills                         property)
409f5c9f8bdSJason M. Bills                     {
410f5c9f8bdSJason M. Bills                         asyncResp->res.jsonValue["FunctionType"] = *property;
411f5c9f8bdSJason M. Bills                     }
412f5c9f8bdSJason M. Bills 
4138d78b7a9SPatrick Williams                     if (std::string* property = std::get_if<std::string>(
4147e860f15SJohn Edward Broadbent                             &pcieDevProperties["Function" + function +
4157e860f15SJohn Edward Broadbent                                                "DeviceClass"]);
416f5c9f8bdSJason M. Bills                         property)
417f5c9f8bdSJason M. Bills                     {
418f5c9f8bdSJason M. Bills                         asyncResp->res.jsonValue["DeviceClass"] = *property;
419f5c9f8bdSJason M. Bills                     }
420f5c9f8bdSJason M. Bills 
4218d78b7a9SPatrick Williams                     if (std::string* property = std::get_if<std::string>(
4227e860f15SJohn Edward Broadbent                             &pcieDevProperties["Function" + function +
4237e860f15SJohn Edward Broadbent                                                "ClassCode"]);
424f5c9f8bdSJason M. Bills                         property)
425f5c9f8bdSJason M. Bills                     {
426f5c9f8bdSJason M. Bills                         asyncResp->res.jsonValue["ClassCode"] = *property;
427f5c9f8bdSJason M. Bills                     }
428f5c9f8bdSJason M. Bills 
4298d78b7a9SPatrick Williams                     if (std::string* property = std::get_if<std::string>(
4307e860f15SJohn Edward Broadbent                             &pcieDevProperties["Function" + function +
4317e860f15SJohn Edward Broadbent                                                "RevisionId"]);
432f5c9f8bdSJason M. Bills                         property)
433f5c9f8bdSJason M. Bills                     {
434f5c9f8bdSJason M. Bills                         asyncResp->res.jsonValue["RevisionId"] = *property;
435f5c9f8bdSJason M. Bills                     }
436f5c9f8bdSJason M. Bills 
4378d78b7a9SPatrick Williams                     if (std::string* property = std::get_if<std::string>(
4387e860f15SJohn Edward Broadbent                             &pcieDevProperties["Function" + function +
4397e860f15SJohn Edward Broadbent                                                "SubsystemId"]);
440f5c9f8bdSJason M. Bills                         property)
441f5c9f8bdSJason M. Bills                     {
442f5c9f8bdSJason M. Bills                         asyncResp->res.jsonValue["SubsystemId"] = *property;
443f5c9f8bdSJason M. Bills                     }
444f5c9f8bdSJason M. Bills 
4458d78b7a9SPatrick Williams                     if (std::string* property = std::get_if<std::string>(
446f5c9f8bdSJason M. Bills                             &pcieDevProperties["Function" + function +
447f5c9f8bdSJason M. Bills                                                "SubsystemVendorId"]);
448f5c9f8bdSJason M. Bills                         property)
449f5c9f8bdSJason M. Bills                     {
450168e20c1SEd Tanous                         asyncResp->res.jsonValue["SubsystemVendorId"] =
451168e20c1SEd Tanous                             *property;
452f5c9f8bdSJason M. Bills                     }
453f5c9f8bdSJason M. Bills                 };
454f5c9f8bdSJason M. Bills             std::string escapedPath = std::string(pciePath) + "/" + device;
455f5c9f8bdSJason M. Bills             dbus::utility::escapePathForDbus(escapedPath);
456f5c9f8bdSJason M. Bills             crow::connections::systemBus->async_method_call(
457f5c9f8bdSJason M. Bills                 std::move(getPCIeDeviceCallback), pcieService, escapedPath,
4587e860f15SJohn Edward Broadbent                 "org.freedesktop.DBus.Properties", "GetAll",
4597e860f15SJohn Edward Broadbent                 pcieDeviceInterface);
4607e860f15SJohn Edward Broadbent         });
461f5c9f8bdSJason M. Bills }
462f5c9f8bdSJason M. Bills 
463f5c9f8bdSJason M. Bills } // namespace redfish
464