xref: /openbmc/bmcweb/features/redfish/lib/pcie.hpp (revision cf3b484e14fe9754c1812d9871d77b5b1ac9f620)
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 
193ccb3adbSEd Tanous #include "app.hpp"
207a1dbc48SGeorge Liu #include "dbus_utility.hpp"
213ccb3adbSEd Tanous #include "query.hpp"
223ccb3adbSEd Tanous #include "registries/privilege_registry.hpp"
23b38fa2abSLakshmi Yadlapati #include "utils/collection.hpp"
243ccb3adbSEd Tanous #include "utils/dbus_utils.hpp"
25c49c329dSLakshmi Yadlapati #include "utils/pcie_util.hpp"
260ec8b83dSEd Tanous 
27f5c9f8bdSJason M. Bills #include <boost/system/linux_error.hpp>
28ef4c65b7SEd Tanous #include <boost/url/format.hpp>
29d1bde9e5SKrzysztof Grobelny #include <sdbusplus/asio/property.hpp>
30d1bde9e5SKrzysztof Grobelny #include <sdbusplus/unpack_properties.hpp>
31f5c9f8bdSJason M. Bills 
32f5c9f8bdSJason M. Bills namespace redfish
33f5c9f8bdSJason M. Bills {
34f5c9f8bdSJason M. Bills 
3589492a15SPatrick Williams static constexpr const char* inventoryPath = "/xyz/openbmc_project/inventory";
3694c3a10bSLakshmi Yadlapati static constexpr std::array<std::string_view, 1> pcieDeviceInterface = {
3794c3a10bSLakshmi Yadlapati     "xyz.openbmc_project.Inventory.Item.PCIeDevice"};
38f5c9f8bdSJason M. Bills 
39543f9a75SLakshmi Yadlapati static inline void handlePCIeDevicePath(
40543f9a75SLakshmi Yadlapati     const std::string& pcieDeviceId,
41ac106bf6SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
42543f9a75SLakshmi Yadlapati     const dbus::utility::MapperGetSubTreePathsResponse& pcieDevicePaths,
43543f9a75SLakshmi Yadlapati     const std::function<void(const std::string& pcieDevicePath,
44543f9a75SLakshmi Yadlapati                              const std::string& service)>& callback)
45543f9a75SLakshmi Yadlapati 
46543f9a75SLakshmi Yadlapati {
47543f9a75SLakshmi Yadlapati     for (const std::string& pcieDevicePath : pcieDevicePaths)
48543f9a75SLakshmi Yadlapati     {
49543f9a75SLakshmi Yadlapati         std::string pciecDeviceName =
50543f9a75SLakshmi Yadlapati             sdbusplus::message::object_path(pcieDevicePath).filename();
51543f9a75SLakshmi Yadlapati         if (pciecDeviceName.empty() || pciecDeviceName != pcieDeviceId)
52543f9a75SLakshmi Yadlapati         {
53543f9a75SLakshmi Yadlapati             continue;
54543f9a75SLakshmi Yadlapati         }
55543f9a75SLakshmi Yadlapati 
56543f9a75SLakshmi Yadlapati         dbus::utility::getDbusObject(
57543f9a75SLakshmi Yadlapati             pcieDevicePath, {},
58ac106bf6SEd Tanous             [pcieDevicePath, asyncResp,
59543f9a75SLakshmi Yadlapati              callback](const boost::system::error_code& ec,
60543f9a75SLakshmi Yadlapati                        const dbus::utility::MapperGetObject& object) {
61543f9a75SLakshmi Yadlapati             if (ec || object.empty())
62543f9a75SLakshmi Yadlapati             {
63543f9a75SLakshmi Yadlapati                 BMCWEB_LOG_ERROR << "DBUS response error " << ec;
64ac106bf6SEd Tanous                 messages::internalError(asyncResp->res);
65543f9a75SLakshmi Yadlapati                 return;
66543f9a75SLakshmi Yadlapati             }
67543f9a75SLakshmi Yadlapati             callback(pcieDevicePath, object.begin()->first);
68543f9a75SLakshmi Yadlapati             });
69543f9a75SLakshmi Yadlapati         return;
70543f9a75SLakshmi Yadlapati     }
71543f9a75SLakshmi Yadlapati 
72543f9a75SLakshmi Yadlapati     BMCWEB_LOG_WARNING << "PCIe Device not found";
73ac106bf6SEd Tanous     messages::resourceNotFound(asyncResp->res, "PCIeDevice", pcieDeviceId);
74543f9a75SLakshmi Yadlapati }
75543f9a75SLakshmi Yadlapati 
76543f9a75SLakshmi Yadlapati static inline void getValidPCIeDevicePath(
77543f9a75SLakshmi Yadlapati     const std::string& pcieDeviceId,
78ac106bf6SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
79543f9a75SLakshmi Yadlapati     const std::function<void(const std::string& pcieDevicePath,
80543f9a75SLakshmi Yadlapati                              const std::string& service)>& callback)
81543f9a75SLakshmi Yadlapati {
82543f9a75SLakshmi Yadlapati     dbus::utility::getSubTreePaths(
8394c3a10bSLakshmi Yadlapati         inventoryPath, 0, pcieDeviceInterface,
84ac106bf6SEd Tanous         [pcieDeviceId, asyncResp,
85543f9a75SLakshmi Yadlapati          callback](const boost::system::error_code& ec,
86543f9a75SLakshmi Yadlapati                    const dbus::utility::MapperGetSubTreePathsResponse&
87543f9a75SLakshmi Yadlapati                        pcieDevicePaths) {
88543f9a75SLakshmi Yadlapati         if (ec)
89543f9a75SLakshmi Yadlapati         {
90543f9a75SLakshmi Yadlapati             BMCWEB_LOG_ERROR << "D-Bus response error on GetSubTree " << ec;
91ac106bf6SEd Tanous             messages::internalError(asyncResp->res);
92543f9a75SLakshmi Yadlapati             return;
93543f9a75SLakshmi Yadlapati         }
94ac106bf6SEd Tanous         handlePCIeDevicePath(pcieDeviceId, asyncResp, pcieDevicePaths,
95ac106bf6SEd Tanous                              callback);
96543f9a75SLakshmi Yadlapati         return;
97543f9a75SLakshmi Yadlapati         });
98543f9a75SLakshmi Yadlapati }
99543f9a75SLakshmi Yadlapati 
100b38fa2abSLakshmi Yadlapati static inline void handlePCIeDeviceCollectionGet(
101b38fa2abSLakshmi Yadlapati     crow::App& app, const crow::Request& req,
102ac106bf6SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
103b38fa2abSLakshmi Yadlapati     const std::string& systemName)
104b38fa2abSLakshmi Yadlapati {
105ac106bf6SEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
106b38fa2abSLakshmi Yadlapati     {
107b38fa2abSLakshmi Yadlapati         return;
108b38fa2abSLakshmi Yadlapati     }
1097f3e84a1SEd Tanous     if constexpr (bmcwebEnableMultiHost)
1107f3e84a1SEd Tanous     {
1117f3e84a1SEd Tanous         // Option currently returns no systems.  TBD
1127f3e84a1SEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1137f3e84a1SEd Tanous                                    systemName);
1147f3e84a1SEd Tanous         return;
1157f3e84a1SEd Tanous     }
116b38fa2abSLakshmi Yadlapati     if (systemName != "system")
117b38fa2abSLakshmi Yadlapati     {
118ac106bf6SEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
119ac106bf6SEd Tanous                                    systemName);
120b38fa2abSLakshmi Yadlapati         return;
121b38fa2abSLakshmi Yadlapati     }
122543f9a75SLakshmi Yadlapati 
123ac106bf6SEd Tanous     asyncResp->res.addHeader(boost::beast::http::field::link,
124b38fa2abSLakshmi Yadlapati                              "</redfish/v1/JsonSchemas/PCIeDeviceCollection/"
125b38fa2abSLakshmi Yadlapati                              "PCIeDeviceCollection.json>; rel=describedby");
126ac106bf6SEd Tanous     asyncResp->res.jsonValue["@odata.type"] =
127b38fa2abSLakshmi Yadlapati         "#PCIeDeviceCollection.PCIeDeviceCollection";
128ac106bf6SEd Tanous     asyncResp->res.jsonValue["@odata.id"] =
129b38fa2abSLakshmi Yadlapati         "/redfish/v1/Systems/system/PCIeDevices";
130ac106bf6SEd Tanous     asyncResp->res.jsonValue["Name"] = "PCIe Device Collection";
131ac106bf6SEd Tanous     asyncResp->res.jsonValue["Description"] = "Collection of PCIe Devices";
132ac106bf6SEd Tanous     asyncResp->res.jsonValue["Members"] = nlohmann::json::array();
133ac106bf6SEd Tanous     asyncResp->res.jsonValue["Members@odata.count"] = 0;
134b38fa2abSLakshmi Yadlapati 
1359e9325e6SLakshmi Yadlapati     pcie_util::getPCIeDeviceList(asyncResp, "Members");
136b38fa2abSLakshmi Yadlapati }
137b38fa2abSLakshmi Yadlapati 
1387e860f15SJohn Edward Broadbent inline void requestRoutesSystemPCIeDeviceCollection(App& app)
139adbe192aSJason M. Bills {
140adbe192aSJason M. Bills     /**
141adbe192aSJason M. Bills      * Functions triggers appropriate requests on DBus
142adbe192aSJason M. Bills      */
14322d268cbSEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/PCIeDevices/")
144ed398213SEd Tanous         .privileges(redfish::privileges::getPCIeDeviceCollection)
1457e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
146b38fa2abSLakshmi Yadlapati             std::bind_front(handlePCIeDeviceCollectionGet, std::ref(app)));
147f5c9f8bdSJason M. Bills }
148f5c9f8bdSJason M. Bills 
149ac106bf6SEd Tanous inline void
150e164f1b6SLakshmi Yadlapati     getPCIeDeviceHealth(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
151e164f1b6SLakshmi Yadlapati                         const std::string& pcieDevicePath,
152e164f1b6SLakshmi Yadlapati                         const std::string& service)
153e164f1b6SLakshmi Yadlapati {
154e164f1b6SLakshmi Yadlapati     sdbusplus::asio::getProperty<bool>(
155e164f1b6SLakshmi Yadlapati         *crow::connections::systemBus, service, pcieDevicePath,
156e164f1b6SLakshmi Yadlapati         "xyz.openbmc_project.State.Decorator.OperationalStatus", "Functional",
157e164f1b6SLakshmi Yadlapati         [asyncResp](const boost::system::error_code& ec, const bool value) {
158e164f1b6SLakshmi Yadlapati         if (ec)
159e164f1b6SLakshmi Yadlapati         {
160e164f1b6SLakshmi Yadlapati             if (ec.value() != EBADR)
161e164f1b6SLakshmi Yadlapati             {
162e164f1b6SLakshmi Yadlapati                 BMCWEB_LOG_ERROR << "DBUS response error for Health "
163e164f1b6SLakshmi Yadlapati                                  << ec.value();
164e164f1b6SLakshmi Yadlapati                 messages::internalError(asyncResp->res);
165e164f1b6SLakshmi Yadlapati             }
166e164f1b6SLakshmi Yadlapati             return;
167e164f1b6SLakshmi Yadlapati         }
168e164f1b6SLakshmi Yadlapati 
169e164f1b6SLakshmi Yadlapati         if (!value)
170e164f1b6SLakshmi Yadlapati         {
171e164f1b6SLakshmi Yadlapati             asyncResp->res.jsonValue["Status"]["Health"] = "Critical";
172e164f1b6SLakshmi Yadlapati         }
173e164f1b6SLakshmi Yadlapati         });
174e164f1b6SLakshmi Yadlapati }
175e164f1b6SLakshmi Yadlapati 
176e164f1b6SLakshmi Yadlapati inline void
177ac106bf6SEd Tanous     getPCIeDeviceState(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
178c6bb3285SLakshmi Yadlapati                        const std::string& pcieDevicePath,
179c6bb3285SLakshmi Yadlapati                        const std::string& service)
180c6bb3285SLakshmi Yadlapati {
181c6bb3285SLakshmi Yadlapati     sdbusplus::asio::getProperty<bool>(
182c6bb3285SLakshmi Yadlapati         *crow::connections::systemBus, service, pcieDevicePath,
183c6bb3285SLakshmi Yadlapati         "xyz.openbmc_project.Inventory.Item", "Present",
184ac106bf6SEd Tanous         [asyncResp](const boost::system::error_code& ec, const bool value) {
185c6bb3285SLakshmi Yadlapati         if (ec)
186c6bb3285SLakshmi Yadlapati         {
187c6bb3285SLakshmi Yadlapati             if (ec.value() != EBADR)
188c6bb3285SLakshmi Yadlapati             {
189c6bb3285SLakshmi Yadlapati                 BMCWEB_LOG_ERROR << "DBUS response error for State";
190ac106bf6SEd Tanous                 messages::internalError(asyncResp->res);
191c6bb3285SLakshmi Yadlapati             }
192c6bb3285SLakshmi Yadlapati             return;
193c6bb3285SLakshmi Yadlapati         }
194c6bb3285SLakshmi Yadlapati 
195c6bb3285SLakshmi Yadlapati         if (!value)
196c6bb3285SLakshmi Yadlapati         {
197ac106bf6SEd Tanous             asyncResp->res.jsonValue["Status"]["State"] = "Absent";
198c6bb3285SLakshmi Yadlapati         }
199c6bb3285SLakshmi Yadlapati         });
200c6bb3285SLakshmi Yadlapati }
201c6bb3285SLakshmi Yadlapati 
202ac106bf6SEd Tanous inline void
203ac106bf6SEd Tanous     getPCIeDeviceAsset(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
204913e7732SSunnySrivastava1984                        const std::string& pcieDevicePath,
205913e7732SSunnySrivastava1984                        const std::string& service)
206913e7732SSunnySrivastava1984 {
207913e7732SSunnySrivastava1984     sdbusplus::asio::getAllProperties(
208913e7732SSunnySrivastava1984         *crow::connections::systemBus, service, pcieDevicePath,
209913e7732SSunnySrivastava1984         "xyz.openbmc_project.Inventory.Decorator.Asset",
210ac106bf6SEd Tanous         [pcieDevicePath, asyncResp{asyncResp}](
211ac106bf6SEd Tanous             const boost::system::error_code& ec,
212913e7732SSunnySrivastava1984             const dbus::utility::DBusPropertiesMap& assetList) {
213913e7732SSunnySrivastava1984         if (ec)
214913e7732SSunnySrivastava1984         {
215913e7732SSunnySrivastava1984             if (ec.value() != EBADR)
216913e7732SSunnySrivastava1984             {
217913e7732SSunnySrivastava1984                 BMCWEB_LOG_ERROR << "DBUS response error for Properties"
218913e7732SSunnySrivastava1984                                  << ec.value();
219ac106bf6SEd Tanous                 messages::internalError(asyncResp->res);
220913e7732SSunnySrivastava1984             }
221913e7732SSunnySrivastava1984             return;
222913e7732SSunnySrivastava1984         }
223913e7732SSunnySrivastava1984 
224913e7732SSunnySrivastava1984         const std::string* manufacturer = nullptr;
225913e7732SSunnySrivastava1984         const std::string* model = nullptr;
226913e7732SSunnySrivastava1984         const std::string* partNumber = nullptr;
227913e7732SSunnySrivastava1984         const std::string* serialNumber = nullptr;
228913e7732SSunnySrivastava1984         const std::string* sparePartNumber = nullptr;
229913e7732SSunnySrivastava1984 
230913e7732SSunnySrivastava1984         const bool success = sdbusplus::unpackPropertiesNoThrow(
231913e7732SSunnySrivastava1984             dbus_utils::UnpackErrorPrinter(), assetList, "Manufacturer",
232913e7732SSunnySrivastava1984             manufacturer, "Model", model, "PartNumber", partNumber,
233913e7732SSunnySrivastava1984             "SerialNumber", serialNumber, "SparePartNumber", sparePartNumber);
234913e7732SSunnySrivastava1984 
235913e7732SSunnySrivastava1984         if (!success)
236913e7732SSunnySrivastava1984         {
237ac106bf6SEd Tanous             messages::internalError(asyncResp->res);
238913e7732SSunnySrivastava1984             return;
239913e7732SSunnySrivastava1984         }
240913e7732SSunnySrivastava1984 
241913e7732SSunnySrivastava1984         if (manufacturer != nullptr)
242913e7732SSunnySrivastava1984         {
243ac106bf6SEd Tanous             asyncResp->res.jsonValue["Manufacturer"] = *manufacturer;
244913e7732SSunnySrivastava1984         }
245913e7732SSunnySrivastava1984         if (model != nullptr)
246913e7732SSunnySrivastava1984         {
247ac106bf6SEd Tanous             asyncResp->res.jsonValue["Model"] = *model;
248913e7732SSunnySrivastava1984         }
249913e7732SSunnySrivastava1984 
250913e7732SSunnySrivastava1984         if (partNumber != nullptr)
251913e7732SSunnySrivastava1984         {
252ac106bf6SEd Tanous             asyncResp->res.jsonValue["PartNumber"] = *partNumber;
253913e7732SSunnySrivastava1984         }
254913e7732SSunnySrivastava1984 
255913e7732SSunnySrivastava1984         if (serialNumber != nullptr)
256913e7732SSunnySrivastava1984         {
257ac106bf6SEd Tanous             asyncResp->res.jsonValue["SerialNumber"] = *serialNumber;
258913e7732SSunnySrivastava1984         }
259913e7732SSunnySrivastava1984 
260913e7732SSunnySrivastava1984         if (sparePartNumber != nullptr && !sparePartNumber->empty())
261913e7732SSunnySrivastava1984         {
262ac106bf6SEd Tanous             asyncResp->res.jsonValue["SparePartNumber"] = *sparePartNumber;
263913e7732SSunnySrivastava1984         }
264913e7732SSunnySrivastava1984         });
265913e7732SSunnySrivastava1984 }
266913e7732SSunnySrivastava1984 
267543f9a75SLakshmi Yadlapati inline void addPCIeDeviceProperties(
26835ad613dSLakshmi Yadlapati     crow::Response& resp, const std::string& pcieDeviceId,
269543f9a75SLakshmi Yadlapati     const dbus::utility::DBusPropertiesMap& pcieDevProperties)
270f5c9f8bdSJason M. Bills {
271d1bde9e5SKrzysztof Grobelny     const std::string* deviceType = nullptr;
272d1bde9e5SKrzysztof Grobelny     const std::string* generationInUse = nullptr;
273543f9a75SLakshmi Yadlapati     const int64_t* lanesInUse = nullptr;
274d1bde9e5SKrzysztof Grobelny 
275d1bde9e5SKrzysztof Grobelny     const bool success = sdbusplus::unpackPropertiesNoThrow(
276543f9a75SLakshmi Yadlapati         dbus_utils::UnpackErrorPrinter(), pcieDevProperties, "DeviceType",
277543f9a75SLakshmi Yadlapati         deviceType, "GenerationInUse", generationInUse, "LanesInUse",
278bad2c4a9SLakshmi Yadlapati         lanesInUse);
279d1bde9e5SKrzysztof Grobelny 
280d1bde9e5SKrzysztof Grobelny     if (!success)
281d1bde9e5SKrzysztof Grobelny     {
282543f9a75SLakshmi Yadlapati         messages::internalError(resp);
283d1bde9e5SKrzysztof Grobelny         return;
284d1bde9e5SKrzysztof Grobelny     }
285d1bde9e5SKrzysztof Grobelny 
286543f9a75SLakshmi Yadlapati     if (deviceType != nullptr && !deviceType->empty())
287703f6741SMyung Bae     {
288543f9a75SLakshmi Yadlapati         resp.jsonValue["PCIeInterface"]["DeviceType"] = *deviceType;
289703f6741SMyung Bae     }
290703f6741SMyung Bae 
291d1bde9e5SKrzysztof Grobelny     if (generationInUse != nullptr)
292d1bde9e5SKrzysztof Grobelny     {
2930ec8b83dSEd Tanous         std::optional<pcie_device::PCIeTypes> redfishGenerationInUse =
294c49c329dSLakshmi Yadlapati             pcie_util::redfishPcieGenerationFromDbus(*generationInUse);
295543f9a75SLakshmi Yadlapati 
296d1bde9e5SKrzysztof Grobelny         if (!redfishGenerationInUse)
297d1bde9e5SKrzysztof Grobelny         {
298*cf3b484eSLakshmi Yadlapati             BMCWEB_LOG_WARNING << "Unknown PCIe Device Generation: "
299*cf3b484eSLakshmi Yadlapati                                << *generationInUse;
300*cf3b484eSLakshmi Yadlapati         }
301*cf3b484eSLakshmi Yadlapati         else
302*cf3b484eSLakshmi Yadlapati         {
303*cf3b484eSLakshmi Yadlapati             if (*redfishGenerationInUse == pcie_device::PCIeTypes::Invalid)
304*cf3b484eSLakshmi Yadlapati             {
305*cf3b484eSLakshmi Yadlapati                 BMCWEB_LOG_ERROR << "Invalid PCIe Device Generation: "
306*cf3b484eSLakshmi Yadlapati                                  << *generationInUse;
307543f9a75SLakshmi Yadlapati                 messages::internalError(resp);
308d1bde9e5SKrzysztof Grobelny                 return;
309d1bde9e5SKrzysztof Grobelny             }
310543f9a75SLakshmi Yadlapati             resp.jsonValue["PCIeInterface"]["PCIeType"] =
311d1bde9e5SKrzysztof Grobelny                 *redfishGenerationInUse;
312d1bde9e5SKrzysztof Grobelny         }
313a9f68bb5STony Lee     }
314d1bde9e5SKrzysztof Grobelny 
315543f9a75SLakshmi Yadlapati     // The default value of LanesInUse is 0, and the field will be
316543f9a75SLakshmi Yadlapati     // left as off if it is a default value.
317543f9a75SLakshmi Yadlapati     if (lanesInUse != nullptr && *lanesInUse != 0)
318543f9a75SLakshmi Yadlapati     {
319543f9a75SLakshmi Yadlapati         resp.jsonValue["PCIeInterface"]["LanesInUse"] = *lanesInUse;
320543f9a75SLakshmi Yadlapati     }
321543f9a75SLakshmi Yadlapati 
322ef4c65b7SEd Tanous     resp.jsonValue["PCIeFunctions"]["@odata.id"] = boost::urls::format(
323ef4c65b7SEd Tanous         "/redfish/v1/Systems/system/PCIeDevices/{}/PCIeFunctions",
324ef4c65b7SEd Tanous         pcieDeviceId);
325d1bde9e5SKrzysztof Grobelny }
326d1bde9e5SKrzysztof Grobelny 
327543f9a75SLakshmi Yadlapati inline void getPCIeDeviceProperties(
328ac106bf6SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
329543f9a75SLakshmi Yadlapati     const std::string& pcieDevicePath, const std::string& service,
330543f9a75SLakshmi Yadlapati     const std::function<void(
331543f9a75SLakshmi Yadlapati         const dbus::utility::DBusPropertiesMap& pcieDevProperties)>&& callback)
332d1bde9e5SKrzysztof Grobelny {
333543f9a75SLakshmi Yadlapati     sdbusplus::asio::getAllProperties(
334543f9a75SLakshmi Yadlapati         *crow::connections::systemBus, service, pcieDevicePath,
335543f9a75SLakshmi Yadlapati         "xyz.openbmc_project.Inventory.Item.PCIeDevice",
336ac106bf6SEd Tanous         [asyncResp,
337543f9a75SLakshmi Yadlapati          callback](const boost::system::error_code& ec,
338543f9a75SLakshmi Yadlapati                    const dbus::utility::DBusPropertiesMap& pcieDevProperties) {
339543f9a75SLakshmi Yadlapati         if (ec)
340543f9a75SLakshmi Yadlapati         {
341543f9a75SLakshmi Yadlapati             if (ec.value() != EBADR)
342543f9a75SLakshmi Yadlapati             {
343543f9a75SLakshmi Yadlapati                 BMCWEB_LOG_ERROR << "DBUS response error for Properties";
344ac106bf6SEd Tanous                 messages::internalError(asyncResp->res);
345543f9a75SLakshmi Yadlapati             }
346543f9a75SLakshmi Yadlapati             return;
347543f9a75SLakshmi Yadlapati         }
348543f9a75SLakshmi Yadlapati         callback(pcieDevProperties);
349543f9a75SLakshmi Yadlapati         });
350d1bde9e5SKrzysztof Grobelny }
351d1bde9e5SKrzysztof Grobelny 
352543f9a75SLakshmi Yadlapati inline void addPCIeDeviceCommonProperties(
353ac106bf6SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
354543f9a75SLakshmi Yadlapati     const std::string& pcieDeviceId)
355543f9a75SLakshmi Yadlapati {
356ac106bf6SEd Tanous     asyncResp->res.addHeader(
357543f9a75SLakshmi Yadlapati         boost::beast::http::field::link,
358543f9a75SLakshmi Yadlapati         "</redfish/v1/JsonSchemas/PCIeDevice/PCIeDevice.json>; rel=describedby");
359ac106bf6SEd Tanous     asyncResp->res.jsonValue["@odata.type"] = "#PCIeDevice.v1_9_0.PCIeDevice";
360ac106bf6SEd Tanous     asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
361ef4c65b7SEd Tanous         "/redfish/v1/Systems/system/PCIeDevices/{}", pcieDeviceId);
362ac106bf6SEd Tanous     asyncResp->res.jsonValue["Name"] = "PCIe Device";
363ac106bf6SEd Tanous     asyncResp->res.jsonValue["Id"] = pcieDeviceId;
364ac106bf6SEd Tanous     asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
365e164f1b6SLakshmi Yadlapati     asyncResp->res.jsonValue["Status"]["Health"] = "OK";
366543f9a75SLakshmi Yadlapati }
3671476687dSEd Tanous 
368ac106bf6SEd Tanous inline void
369ac106bf6SEd Tanous     handlePCIeDeviceGet(App& app, const crow::Request& req,
370ac106bf6SEd Tanous                         const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
371543f9a75SLakshmi Yadlapati                         const std::string& systemName,
372543f9a75SLakshmi Yadlapati                         const std::string& pcieDeviceId)
373543f9a75SLakshmi Yadlapati {
374ac106bf6SEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
375543f9a75SLakshmi Yadlapati     {
376543f9a75SLakshmi Yadlapati         return;
377543f9a75SLakshmi Yadlapati     }
3787f3e84a1SEd Tanous     if constexpr (bmcwebEnableMultiHost)
3797f3e84a1SEd Tanous     {
3807f3e84a1SEd Tanous         // Option currently returns no systems.  TBD
3817f3e84a1SEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3827f3e84a1SEd Tanous                                    systemName);
3837f3e84a1SEd Tanous         return;
3847f3e84a1SEd Tanous     }
385543f9a75SLakshmi Yadlapati     if (systemName != "system")
386543f9a75SLakshmi Yadlapati     {
387ac106bf6SEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
388ac106bf6SEd Tanous                                    systemName);
389543f9a75SLakshmi Yadlapati         return;
390543f9a75SLakshmi Yadlapati     }
391543f9a75SLakshmi Yadlapati 
392543f9a75SLakshmi Yadlapati     getValidPCIeDevicePath(
393ac106bf6SEd Tanous         pcieDeviceId, asyncResp,
394ac106bf6SEd Tanous         [asyncResp, pcieDeviceId](const std::string& pcieDevicePath,
395543f9a75SLakshmi Yadlapati                                   const std::string& service) {
396ac106bf6SEd Tanous         addPCIeDeviceCommonProperties(asyncResp, pcieDeviceId);
397ac106bf6SEd Tanous         getPCIeDeviceAsset(asyncResp, pcieDevicePath, service);
398ac106bf6SEd Tanous         getPCIeDeviceState(asyncResp, pcieDevicePath, service);
399e164f1b6SLakshmi Yadlapati         getPCIeDeviceHealth(asyncResp, pcieDevicePath, service);
400543f9a75SLakshmi Yadlapati         getPCIeDeviceProperties(
401ac106bf6SEd Tanous             asyncResp, pcieDevicePath, service,
402ac106bf6SEd Tanous             [asyncResp, pcieDeviceId](
40335ad613dSLakshmi Yadlapati                 const dbus::utility::DBusPropertiesMap& pcieDevProperties) {
404ac106bf6SEd Tanous             addPCIeDeviceProperties(asyncResp->res, pcieDeviceId,
40535ad613dSLakshmi Yadlapati                                     pcieDevProperties);
4067e860f15SJohn Edward Broadbent             });
407543f9a75SLakshmi Yadlapati         });
408543f9a75SLakshmi Yadlapati }
409543f9a75SLakshmi Yadlapati 
410543f9a75SLakshmi Yadlapati inline void requestRoutesSystemPCIeDevice(App& app)
411543f9a75SLakshmi Yadlapati {
412543f9a75SLakshmi Yadlapati     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/PCIeDevices/<str>/")
413543f9a75SLakshmi Yadlapati         .privileges(redfish::privileges::getPCIeDevice)
414543f9a75SLakshmi Yadlapati         .methods(boost::beast::http::verb::get)(
415543f9a75SLakshmi Yadlapati             std::bind_front(handlePCIeDeviceGet, std::ref(app)));
416dede6a98SJason M. Bills }
417dede6a98SJason M. Bills 
41835ad613dSLakshmi Yadlapati inline void addPCIeFunctionList(
41935ad613dSLakshmi Yadlapati     crow::Response& res, const std::string& pcieDeviceId,
42035ad613dSLakshmi Yadlapati     const dbus::utility::DBusPropertiesMap& pcieDevProperties)
42135ad613dSLakshmi Yadlapati {
42235ad613dSLakshmi Yadlapati     nlohmann::json& pcieFunctionList = res.jsonValue["Members"];
42335ad613dSLakshmi Yadlapati     pcieFunctionList = nlohmann::json::array();
42435ad613dSLakshmi Yadlapati     static constexpr const int maxPciFunctionNum = 8;
42535ad613dSLakshmi Yadlapati 
42635ad613dSLakshmi Yadlapati     for (int functionNum = 0; functionNum < maxPciFunctionNum; functionNum++)
42735ad613dSLakshmi Yadlapati     {
42835ad613dSLakshmi Yadlapati         // Check if this function exists by
42935ad613dSLakshmi Yadlapati         // looking for a device ID
43089492a15SPatrick Williams         std::string devIDProperty = "Function" + std::to_string(functionNum) +
43189492a15SPatrick Williams                                     "DeviceId";
43235ad613dSLakshmi Yadlapati         const std::string* property = nullptr;
43335ad613dSLakshmi Yadlapati         for (const auto& propEntry : pcieDevProperties)
43435ad613dSLakshmi Yadlapati         {
43535ad613dSLakshmi Yadlapati             if (propEntry.first == devIDProperty)
43635ad613dSLakshmi Yadlapati             {
43735ad613dSLakshmi Yadlapati                 property = std::get_if<std::string>(&propEntry.second);
43835ad613dSLakshmi Yadlapati                 break;
43935ad613dSLakshmi Yadlapati             }
44035ad613dSLakshmi Yadlapati         }
44135ad613dSLakshmi Yadlapati         if (property == nullptr || property->empty())
44235ad613dSLakshmi Yadlapati         {
44335ad613dSLakshmi Yadlapati             continue;
44435ad613dSLakshmi Yadlapati         }
44535ad613dSLakshmi Yadlapati 
44635ad613dSLakshmi Yadlapati         nlohmann::json::object_t pcieFunction;
447ef4c65b7SEd Tanous         pcieFunction["@odata.id"] = boost::urls::format(
448ef4c65b7SEd Tanous             "/redfish/v1/Systems/system/PCIeDevices/{}/PCIeFunctions/{}",
449ef4c65b7SEd Tanous             pcieDeviceId, std::to_string(functionNum));
450b2ba3072SPatrick Williams         pcieFunctionList.emplace_back(std::move(pcieFunction));
45135ad613dSLakshmi Yadlapati     }
45235ad613dSLakshmi Yadlapati     res.jsonValue["PCIeFunctions@odata.count"] = pcieFunctionList.size();
45335ad613dSLakshmi Yadlapati }
45435ad613dSLakshmi Yadlapati 
45535ad613dSLakshmi Yadlapati inline void handlePCIeFunctionCollectionGet(
45635ad613dSLakshmi Yadlapati     App& app, const crow::Request& req,
457ac106bf6SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
4587f3e84a1SEd Tanous     const std::string& systemName, const std::string& pcieDeviceId)
45935ad613dSLakshmi Yadlapati {
460ac106bf6SEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
46135ad613dSLakshmi Yadlapati     {
46235ad613dSLakshmi Yadlapati         return;
46335ad613dSLakshmi Yadlapati     }
4647f3e84a1SEd Tanous     if constexpr (bmcwebEnableMultiHost)
4657f3e84a1SEd Tanous     {
4667f3e84a1SEd Tanous         // Option currently returns no systems.  TBD
4677f3e84a1SEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
4687f3e84a1SEd Tanous                                    systemName);
4697f3e84a1SEd Tanous         return;
4707f3e84a1SEd Tanous     }
47135ad613dSLakshmi Yadlapati 
47235ad613dSLakshmi Yadlapati     getValidPCIeDevicePath(
473ac106bf6SEd Tanous         pcieDeviceId, asyncResp,
474ac106bf6SEd Tanous         [asyncResp, pcieDeviceId](const std::string& pcieDevicePath,
47535ad613dSLakshmi Yadlapati                                   const std::string& service) {
476ac106bf6SEd Tanous         asyncResp->res.addHeader(
47735ad613dSLakshmi Yadlapati             boost::beast::http::field::link,
47835ad613dSLakshmi Yadlapati             "</redfish/v1/JsonSchemas/PCIeFunctionCollection/PCIeFunctionCollection.json>; rel=describedby");
479ac106bf6SEd Tanous         asyncResp->res.jsonValue["@odata.type"] =
48035ad613dSLakshmi Yadlapati             "#PCIeFunctionCollection.PCIeFunctionCollection";
481ac106bf6SEd Tanous         asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
482ef4c65b7SEd Tanous             "/redfish/v1/Systems/system/PCIeDevices/{}/PCIeFunctions",
483ef4c65b7SEd Tanous             pcieDeviceId);
484ac106bf6SEd Tanous         asyncResp->res.jsonValue["Name"] = "PCIe Function Collection";
485ac106bf6SEd Tanous         asyncResp->res.jsonValue["Description"] =
48635ad613dSLakshmi Yadlapati             "Collection of PCIe Functions for PCIe Device " + pcieDeviceId;
48735ad613dSLakshmi Yadlapati         getPCIeDeviceProperties(
488ac106bf6SEd Tanous             asyncResp, pcieDevicePath, service,
489ac106bf6SEd Tanous             [asyncResp, pcieDeviceId](
49035ad613dSLakshmi Yadlapati                 const dbus::utility::DBusPropertiesMap& pcieDevProperties) {
491ac106bf6SEd Tanous             addPCIeFunctionList(asyncResp->res, pcieDeviceId,
492ac106bf6SEd Tanous                                 pcieDevProperties);
49335ad613dSLakshmi Yadlapati             });
49435ad613dSLakshmi Yadlapati         });
49535ad613dSLakshmi Yadlapati }
49635ad613dSLakshmi Yadlapati 
4977e860f15SJohn Edward Broadbent inline void requestRoutesSystemPCIeFunctionCollection(App& app)
4987e860f15SJohn Edward Broadbent {
499dede6a98SJason M. Bills     /**
500dede6a98SJason M. Bills      * Functions triggers appropriate requests on DBus
501dede6a98SJason M. Bills      */
5027e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app,
5037f3e84a1SEd Tanous                  "/redfish/v1/Systems/<str>/PCIeDevices/<str>/PCIeFunctions/")
504ed398213SEd Tanous         .privileges(redfish::privileges::getPCIeFunctionCollection)
505002d39b4SEd Tanous         .methods(boost::beast::http::verb::get)(
50635ad613dSLakshmi Yadlapati             std::bind_front(handlePCIeFunctionCollectionGet, std::ref(app)));
5077e860f15SJohn Edward Broadbent }
5087e860f15SJohn Edward Broadbent 
509727a046cSLakshmi Yadlapati inline bool validatePCIeFunctionId(
510d5e74b80SMyung Bae     uint64_t pcieFunctionId,
511727a046cSLakshmi Yadlapati     const dbus::utility::DBusPropertiesMap& pcieDevProperties)
5127e860f15SJohn Edward Broadbent {
513d5e74b80SMyung Bae     std::string functionName = "Function" + std::to_string(pcieFunctionId);
514b9d36b47SEd Tanous     std::string devIDProperty = functionName + "DeviceId";
515b9d36b47SEd Tanous 
516b9d36b47SEd Tanous     const std::string* devIdProperty = nullptr;
517b9d36b47SEd Tanous     for (const auto& property : pcieDevProperties)
518b9d36b47SEd Tanous     {
519b9d36b47SEd Tanous         if (property.first == devIDProperty)
520b9d36b47SEd Tanous         {
521002d39b4SEd Tanous             devIdProperty = std::get_if<std::string>(&property.second);
522727a046cSLakshmi Yadlapati             break;
523b9d36b47SEd Tanous         }
524b9d36b47SEd Tanous     }
525727a046cSLakshmi Yadlapati     return (devIdProperty != nullptr && !devIdProperty->empty());
526727a046cSLakshmi Yadlapati }
527727a046cSLakshmi Yadlapati 
528727a046cSLakshmi Yadlapati inline void addPCIeFunctionProperties(
529e14742caSEd Tanous     crow::Response& resp, uint64_t pcieFunctionId,
530727a046cSLakshmi Yadlapati     const dbus::utility::DBusPropertiesMap& pcieDevProperties)
531f5c9f8bdSJason M. Bills {
532e14742caSEd Tanous     std::string functionName = "Function" + std::to_string(pcieFunctionId);
533b9d36b47SEd Tanous     for (const auto& property : pcieDevProperties)
534f5c9f8bdSJason M. Bills     {
535b9d36b47SEd Tanous         const std::string* strProperty =
536b9d36b47SEd Tanous             std::get_if<std::string>(&property.second);
537727a046cSLakshmi Yadlapati 
538b9d36b47SEd Tanous         if (property.first == functionName + "DeviceId")
539f5c9f8bdSJason M. Bills         {
540727a046cSLakshmi Yadlapati             resp.jsonValue["DeviceId"] = *strProperty;
541f5c9f8bdSJason M. Bills         }
542b9d36b47SEd Tanous         if (property.first == functionName + "VendorId")
543f5c9f8bdSJason M. Bills         {
544727a046cSLakshmi Yadlapati             resp.jsonValue["VendorId"] = *strProperty;
545f5c9f8bdSJason M. Bills         }
546727a046cSLakshmi Yadlapati         // TODO: FunctionType and DeviceClass are Redfish enums. The D-Bus
547727a046cSLakshmi Yadlapati         // property strings should be mapped correctly to ensure these
548727a046cSLakshmi Yadlapati         // strings are Redfish enum values. For now just check for empty.
549b9d36b47SEd Tanous         if (property.first == functionName + "FunctionType")
550f5c9f8bdSJason M. Bills         {
551727a046cSLakshmi Yadlapati             if (!strProperty->empty())
552727a046cSLakshmi Yadlapati             {
553727a046cSLakshmi Yadlapati                 resp.jsonValue["FunctionType"] = *strProperty;
554727a046cSLakshmi Yadlapati             }
555f5c9f8bdSJason M. Bills         }
556b9d36b47SEd Tanous         if (property.first == functionName + "DeviceClass")
557f5c9f8bdSJason M. Bills         {
558727a046cSLakshmi Yadlapati             if (!strProperty->empty())
559727a046cSLakshmi Yadlapati             {
560727a046cSLakshmi Yadlapati                 resp.jsonValue["DeviceClass"] = *strProperty;
561727a046cSLakshmi Yadlapati             }
562f5c9f8bdSJason M. Bills         }
563b9d36b47SEd Tanous         if (property.first == functionName + "ClassCode")
564f5c9f8bdSJason M. Bills         {
565727a046cSLakshmi Yadlapati             resp.jsonValue["ClassCode"] = *strProperty;
566f5c9f8bdSJason M. Bills         }
567b9d36b47SEd Tanous         if (property.first == functionName + "RevisionId")
568f5c9f8bdSJason M. Bills         {
569727a046cSLakshmi Yadlapati             resp.jsonValue["RevisionId"] = *strProperty;
570f5c9f8bdSJason M. Bills         }
571b9d36b47SEd Tanous         if (property.first == functionName + "SubsystemId")
572b9d36b47SEd Tanous         {
573727a046cSLakshmi Yadlapati             resp.jsonValue["SubsystemId"] = *strProperty;
574b9d36b47SEd Tanous         }
575002d39b4SEd Tanous         if (property.first == functionName + "SubsystemVendorId")
576f5c9f8bdSJason M. Bills         {
577727a046cSLakshmi Yadlapati             resp.jsonValue["SubsystemVendorId"] = *strProperty;
578b9d36b47SEd Tanous         }
579f5c9f8bdSJason M. Bills     }
580727a046cSLakshmi Yadlapati }
581727a046cSLakshmi Yadlapati 
582727a046cSLakshmi Yadlapati inline void addPCIeFunctionCommonProperties(crow::Response& resp,
583727a046cSLakshmi Yadlapati                                             const std::string& pcieDeviceId,
584e14742caSEd Tanous                                             uint64_t pcieFunctionId)
585727a046cSLakshmi Yadlapati {
586727a046cSLakshmi Yadlapati     resp.addHeader(
587727a046cSLakshmi Yadlapati         boost::beast::http::field::link,
588727a046cSLakshmi Yadlapati         "</redfish/v1/JsonSchemas/PCIeFunction/PCIeFunction.json>; rel=describedby");
589727a046cSLakshmi Yadlapati     resp.jsonValue["@odata.type"] = "#PCIeFunction.v1_2_3.PCIeFunction";
590ef4c65b7SEd Tanous     resp.jsonValue["@odata.id"] = boost::urls::format(
591ef4c65b7SEd Tanous         "/redfish/v1/Systems/system/PCIeDevices/{}/PCIeFunctions/{}",
592768a143dSLakshmi Yadlapati         pcieDeviceId, std::to_string(pcieFunctionId));
593727a046cSLakshmi Yadlapati     resp.jsonValue["Name"] = "PCIe Function";
594e14742caSEd Tanous     resp.jsonValue["Id"] = std::to_string(pcieFunctionId);
595e14742caSEd Tanous     resp.jsonValue["FunctionId"] = pcieFunctionId;
596ef4c65b7SEd Tanous     resp.jsonValue["Links"]["PCIeDevice"]["@odata.id"] = boost::urls::format(
597ef4c65b7SEd Tanous         "/redfish/v1/Systems/system/PCIeDevices/{}", pcieDeviceId);
598727a046cSLakshmi Yadlapati }
599727a046cSLakshmi Yadlapati 
600727a046cSLakshmi Yadlapati inline void
601727a046cSLakshmi Yadlapati     handlePCIeFunctionGet(App& app, const crow::Request& req,
602ac106bf6SEd Tanous                           const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
6037f3e84a1SEd Tanous                           const std::string& systemName,
604727a046cSLakshmi Yadlapati                           const std::string& pcieDeviceId,
605e14742caSEd Tanous                           const std::string& pcieFunctionIdStr)
606727a046cSLakshmi Yadlapati {
607ac106bf6SEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
608727a046cSLakshmi Yadlapati     {
609727a046cSLakshmi Yadlapati         return;
610727a046cSLakshmi Yadlapati     }
6117f3e84a1SEd Tanous     if constexpr (bmcwebEnableMultiHost)
6127f3e84a1SEd Tanous     {
6137f3e84a1SEd Tanous         // Option currently returns no systems.  TBD
6147f3e84a1SEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
6157f3e84a1SEd Tanous                                    systemName);
6167f3e84a1SEd Tanous         return;
6177f3e84a1SEd Tanous     }
6187f3e84a1SEd Tanous     if (systemName != "system")
6197f3e84a1SEd Tanous     {
6207f3e84a1SEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
6217f3e84a1SEd Tanous                                    systemName);
6227f3e84a1SEd Tanous         return;
6237f3e84a1SEd Tanous     }
6247f3e84a1SEd Tanous 
625e14742caSEd Tanous     uint64_t pcieFunctionId = 0;
626e14742caSEd Tanous     std::from_chars_result result = std::from_chars(
627e14742caSEd Tanous         &*pcieFunctionIdStr.begin(), &*pcieFunctionIdStr.end(), pcieFunctionId);
628e14742caSEd Tanous     if (result.ec != std::errc{} || result.ptr != &*pcieFunctionIdStr.end())
629e14742caSEd Tanous     {
630ac106bf6SEd Tanous         messages::resourceNotFound(asyncResp->res, "PCIeFunction",
631e14742caSEd Tanous                                    pcieFunctionIdStr);
632e14742caSEd Tanous         return;
633e14742caSEd Tanous     }
634727a046cSLakshmi Yadlapati 
635ac106bf6SEd Tanous     getValidPCIeDevicePath(pcieDeviceId, asyncResp,
636ac106bf6SEd Tanous                            [asyncResp, pcieDeviceId,
637ac106bf6SEd Tanous                             pcieFunctionId](const std::string& pcieDevicePath,
638727a046cSLakshmi Yadlapati                                             const std::string& service) {
639727a046cSLakshmi Yadlapati         getPCIeDeviceProperties(
640ac106bf6SEd Tanous             asyncResp, pcieDevicePath, service,
641ac106bf6SEd Tanous             [asyncResp, pcieDeviceId, pcieFunctionId](
642727a046cSLakshmi Yadlapati                 const dbus::utility::DBusPropertiesMap& pcieDevProperties) {
643ac106bf6SEd Tanous             addPCIeFunctionCommonProperties(asyncResp->res, pcieDeviceId,
644727a046cSLakshmi Yadlapati                                             pcieFunctionId);
645ac106bf6SEd Tanous             addPCIeFunctionProperties(asyncResp->res, pcieFunctionId,
646727a046cSLakshmi Yadlapati                                       pcieDevProperties);
6477e860f15SJohn Edward Broadbent             });
648727a046cSLakshmi Yadlapati     });
649727a046cSLakshmi Yadlapati }
650727a046cSLakshmi Yadlapati 
651727a046cSLakshmi Yadlapati inline void requestRoutesSystemPCIeFunction(App& app)
652727a046cSLakshmi Yadlapati {
653727a046cSLakshmi Yadlapati     BMCWEB_ROUTE(
6547f3e84a1SEd Tanous         app, "/redfish/v1/Systems/<str>/PCIeDevices/<str>/PCIeFunctions/<str>/")
655727a046cSLakshmi Yadlapati         .privileges(redfish::privileges::getPCIeFunction)
656727a046cSLakshmi Yadlapati         .methods(boost::beast::http::verb::get)(
657727a046cSLakshmi Yadlapati             std::bind_front(handlePCIeFunctionGet, std::ref(app)));
658f5c9f8bdSJason M. Bills }
659f5c9f8bdSJason M. Bills 
660f5c9f8bdSJason M. Bills } // namespace redfish
661