blob: 3831e184a630a94a1376a4e74bb68879641f214c [file] [log] [blame]
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -08001/*
2// Copyright (c) 2018 Intel Corporation
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
16
17#pragma once
18
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080019#include "app.hpp"
George Liu7a1dbc42022-12-07 16:03:22 +080020#include "dbus_utility.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080021#include "query.hpp"
22#include "registries/privilege_registry.hpp"
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -060023#include "utils/collection.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080024#include "utils/dbus_utils.hpp"
Lakshmi Yadlapatic49c3292023-04-19 16:42:35 -050025#include "utils/pcie_util.hpp"
Ed Tanous0ec8b832022-03-14 14:56:47 -070026
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -080027#include <boost/system/linux_error.hpp>
Ed Tanousef4c65b2023-04-24 15:28:50 -070028#include <boost/url/format.hpp>
Krzysztof Grobelnyd1bde9e2022-09-07 10:40:51 +020029#include <sdbusplus/asio/property.hpp>
30#include <sdbusplus/unpack_properties.hpp>
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -080031
32namespace redfish
33{
34
Patrick Williams89492a12023-05-10 07:51:34 -050035static constexpr const char* inventoryPath = "/xyz/openbmc_project/inventory";
Lakshmi Yadlapati94c3a102023-04-05 18:11:22 -050036static constexpr std::array<std::string_view, 1> pcieDeviceInterface = {
37 "xyz.openbmc_project.Inventory.Item.PCIeDevice"};
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -050038static constexpr std::array<std::string_view, 1> pcieSlotInterface = {
39 "xyz.openbmc_project.Inventory.Item.PCIeSlot"};
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -080040
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060041static inline void handlePCIeDevicePath(
42 const std::string& pcieDeviceId,
Ed Tanousac106bf2023-06-07 09:24:59 -070043 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060044 const dbus::utility::MapperGetSubTreePathsResponse& pcieDevicePaths,
45 const std::function<void(const std::string& pcieDevicePath,
46 const std::string& service)>& callback)
47
48{
49 for (const std::string& pcieDevicePath : pcieDevicePaths)
50 {
51 std::string pciecDeviceName =
52 sdbusplus::message::object_path(pcieDevicePath).filename();
53 if (pciecDeviceName.empty() || pciecDeviceName != pcieDeviceId)
54 {
55 continue;
56 }
57
58 dbus::utility::getDbusObject(
59 pcieDevicePath, {},
Ed Tanousac106bf2023-06-07 09:24:59 -070060 [pcieDevicePath, asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060061 callback](const boost::system::error_code& ec,
62 const dbus::utility::MapperGetObject& object) {
63 if (ec || object.empty())
64 {
Ed Tanous62598e32023-07-17 17:06:25 -070065 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
Ed Tanousac106bf2023-06-07 09:24:59 -070066 messages::internalError(asyncResp->res);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060067 return;
68 }
69 callback(pcieDevicePath, object.begin()->first);
70 });
71 return;
72 }
73
Ed Tanous62598e32023-07-17 17:06:25 -070074 BMCWEB_LOG_WARNING("PCIe Device not found");
Ed Tanousac106bf2023-06-07 09:24:59 -070075 messages::resourceNotFound(asyncResp->res, "PCIeDevice", pcieDeviceId);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060076}
77
78static inline void getValidPCIeDevicePath(
79 const std::string& pcieDeviceId,
Ed Tanousac106bf2023-06-07 09:24:59 -070080 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060081 const std::function<void(const std::string& pcieDevicePath,
82 const std::string& service)>& callback)
83{
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060084 dbus::utility::getSubTreePaths(
Lakshmi Yadlapati94c3a102023-04-05 18:11:22 -050085 inventoryPath, 0, pcieDeviceInterface,
Ed Tanousac106bf2023-06-07 09:24:59 -070086 [pcieDeviceId, asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060087 callback](const boost::system::error_code& ec,
88 const dbus::utility::MapperGetSubTreePathsResponse&
89 pcieDevicePaths) {
90 if (ec)
91 {
Ed Tanous62598e32023-07-17 17:06:25 -070092 BMCWEB_LOG_ERROR("D-Bus response error on GetSubTree {}", ec);
Ed Tanousac106bf2023-06-07 09:24:59 -070093 messages::internalError(asyncResp->res);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060094 return;
95 }
Ed Tanousac106bf2023-06-07 09:24:59 -070096 handlePCIeDevicePath(pcieDeviceId, asyncResp, pcieDevicePaths,
97 callback);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060098 return;
99 });
100}
101
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600102static inline void handlePCIeDeviceCollectionGet(
103 crow::App& app, const crow::Request& req,
Ed Tanousac106bf2023-06-07 09:24:59 -0700104 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600105 const std::string& systemName)
106{
Ed Tanousac106bf2023-06-07 09:24:59 -0700107 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600108 {
109 return;
110 }
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800111 if constexpr (bmcwebEnableMultiHost)
112 {
113 // Option currently returns no systems. TBD
114 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
115 systemName);
116 return;
117 }
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600118 if (systemName != "system")
119 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700120 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
121 systemName);
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600122 return;
123 }
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600124
Ed Tanousac106bf2023-06-07 09:24:59 -0700125 asyncResp->res.addHeader(boost::beast::http::field::link,
126 "</redfish/v1/JsonSchemas/PCIeDeviceCollection/"
127 "PCIeDeviceCollection.json>; rel=describedby");
128 asyncResp->res.jsonValue["@odata.type"] =
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600129 "#PCIeDeviceCollection.PCIeDeviceCollection";
Ed Tanousac106bf2023-06-07 09:24:59 -0700130 asyncResp->res.jsonValue["@odata.id"] =
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600131 "/redfish/v1/Systems/system/PCIeDevices";
Ed Tanousac106bf2023-06-07 09:24:59 -0700132 asyncResp->res.jsonValue["Name"] = "PCIe Device Collection";
133 asyncResp->res.jsonValue["Description"] = "Collection of PCIe Devices";
134 asyncResp->res.jsonValue["Members"] = nlohmann::json::array();
135 asyncResp->res.jsonValue["Members@odata.count"] = 0;
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600136
Lakshmi Yadlapati9e9325e2023-05-02 10:30:44 -0500137 pcie_util::getPCIeDeviceList(asyncResp, "Members");
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600138}
139
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700140inline void requestRoutesSystemPCIeDeviceCollection(App& app)
Jason M. Billsadbe1922019-10-14 15:44:35 -0700141{
Jason M. Billsadbe1922019-10-14 15:44:35 -0700142 /**
143 * Functions triggers appropriate requests on DBus
144 */
Ed Tanous22d268c2022-05-19 09:39:07 -0700145 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/PCIeDevices/")
Ed Tanoused398212021-06-09 17:05:54 -0700146 .privileges(redfish::privileges::getPCIeDeviceCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700147 .methods(boost::beast::http::verb::get)(
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600148 std::bind_front(handlePCIeDeviceCollectionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700149}
150
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500151inline void addPCIeSlotProperties(
152 crow::Response& res, const boost::system::error_code& ec,
153 const dbus::utility::DBusPropertiesMap& pcieSlotProperties)
154{
155 if (ec)
156 {
Ed Tanous62598e32023-07-17 17:06:25 -0700157 BMCWEB_LOG_ERROR("DBUS response error for getAllProperties{}",
158 ec.value());
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500159 messages::internalError(res);
160 return;
161 }
162 std::string generation;
163 size_t lanes = 0;
164 std::string slotType;
165
166 bool success = sdbusplus::unpackPropertiesNoThrow(
167 dbus_utils::UnpackErrorPrinter(), pcieSlotProperties, "Generation",
168 generation, "Lanes", lanes, "SlotType", slotType);
169
170 if (!success)
171 {
172 messages::internalError(res);
173 return;
174 }
175
176 std::optional<pcie_device::PCIeTypes> pcieType =
177 pcie_util::redfishPcieGenerationFromDbus(generation);
178 if (!pcieType)
179 {
Ed Tanous62598e32023-07-17 17:06:25 -0700180 BMCWEB_LOG_WARNING("Unknown PCIeType: {}", generation);
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500181 }
182 else
183 {
184 if (*pcieType == pcie_device::PCIeTypes::Invalid)
185 {
Ed Tanous62598e32023-07-17 17:06:25 -0700186 BMCWEB_LOG_ERROR("Invalid PCIeType: {}", generation);
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500187 messages::internalError(res);
188 return;
189 }
190 res.jsonValue["Slot"]["PCIeType"] = *pcieType;
191 }
192
Konstantin Aladyshev82f80322023-07-10 15:00:38 +0300193 if (lanes != 0)
194 {
195 res.jsonValue["Slot"]["Lanes"] = lanes;
196 }
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500197
198 std::optional<pcie_slots::SlotTypes> redfishSlotType =
199 pcie_util::dbusSlotTypeToRf(slotType);
200 if (!redfishSlotType)
201 {
Ed Tanous62598e32023-07-17 17:06:25 -0700202 BMCWEB_LOG_WARNING("Unknown PCIeSlot Type: {}", slotType);
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500203 }
204 else
205 {
206 if (*redfishSlotType == pcie_slots::SlotTypes::Invalid)
207 {
Ed Tanous62598e32023-07-17 17:06:25 -0700208 BMCWEB_LOG_ERROR("Invalid PCIeSlot type: {}", slotType);
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500209 messages::internalError(res);
210 return;
211 }
212 res.jsonValue["Slot"]["SlotType"] = *redfishSlotType;
213 }
214}
215
216inline void getPCIeDeviceSlotPath(
217 const std::string& pcieDevicePath,
218 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
219 std::function<void(const std::string& pcieDeviceSlot)>&& callback)
220{
221 std::string associationPath = pcieDevicePath + "/contained_by";
222 dbus::utility::getAssociatedSubTreePaths(
223 associationPath, sdbusplus::message::object_path(inventoryPath), 0,
224 pcieSlotInterface,
225 [callback, asyncResp, pcieDevicePath](
226 const boost::system::error_code& ec,
227 const dbus::utility::MapperGetSubTreePathsResponse& endpoints) {
228 if (ec)
229 {
230 if (ec.value() == EBADR)
231 {
232 // Missing association is not an error
233 return;
234 }
Ed Tanous62598e32023-07-17 17:06:25 -0700235 BMCWEB_LOG_ERROR(
236 "DBUS response error for getAssociatedSubTreePaths {}",
237 ec.value());
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500238 messages::internalError(asyncResp->res);
239 return;
240 }
241 if (endpoints.size() > 1)
242 {
Ed Tanous62598e32023-07-17 17:06:25 -0700243 BMCWEB_LOG_ERROR(
244 "PCIeDevice is associated with more than one PCIeSlot: {}",
245 endpoints.size());
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500246 messages::internalError(asyncResp->res);
247 return;
248 }
249 if (endpoints.empty())
250 {
251 // If the device doesn't have an association, return without PCIe
252 // Slot properties
Ed Tanous62598e32023-07-17 17:06:25 -0700253 BMCWEB_LOG_DEBUG("PCIeDevice is not associated with PCIeSlot");
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500254 return;
255 }
256 callback(endpoints[0]);
257 });
258}
259
260inline void
261 afterGetDbusObject(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
262 const std::string& pcieDeviceSlot,
263 const boost::system::error_code& ec,
264 const dbus::utility::MapperGetObject& object)
265{
266 if (ec || object.empty())
267 {
Ed Tanous62598e32023-07-17 17:06:25 -0700268 BMCWEB_LOG_ERROR("DBUS response error for getDbusObject {}",
269 ec.value());
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500270 messages::internalError(asyncResp->res);
271 return;
272 }
273 sdbusplus::asio::getAllProperties(
274 *crow::connections::systemBus, object.begin()->first, pcieDeviceSlot,
275 "xyz.openbmc_project.Inventory.Item.PCIeSlot",
276 [asyncResp](
277 const boost::system::error_code& ec2,
278 const dbus::utility::DBusPropertiesMap& pcieSlotProperties) {
279 addPCIeSlotProperties(asyncResp->res, ec2, pcieSlotProperties);
280 });
281}
282
283inline void afterGetPCIeDeviceSlotPath(
284 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
285 const std::string& pcieDeviceSlot)
286{
287 dbus::utility::getDbusObject(
288 pcieDeviceSlot, pcieSlotInterface,
289 [asyncResp,
290 pcieDeviceSlot](const boost::system::error_code& ec,
291 const dbus::utility::MapperGetObject& object) {
292 afterGetDbusObject(asyncResp, pcieDeviceSlot, ec, object);
293 });
294}
295
Ed Tanousac106bf2023-06-07 09:24:59 -0700296inline void
Lakshmi Yadlapatie164f1b2023-04-12 17:01:34 -0500297 getPCIeDeviceHealth(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
298 const std::string& pcieDevicePath,
299 const std::string& service)
300{
301 sdbusplus::asio::getProperty<bool>(
302 *crow::connections::systemBus, service, pcieDevicePath,
303 "xyz.openbmc_project.State.Decorator.OperationalStatus", "Functional",
304 [asyncResp](const boost::system::error_code& ec, const bool value) {
305 if (ec)
306 {
307 if (ec.value() != EBADR)
308 {
Ed Tanous62598e32023-07-17 17:06:25 -0700309 BMCWEB_LOG_ERROR("DBUS response error for Health {}",
310 ec.value());
Lakshmi Yadlapatie164f1b2023-04-12 17:01:34 -0500311 messages::internalError(asyncResp->res);
312 }
313 return;
314 }
315
316 if (!value)
317 {
318 asyncResp->res.jsonValue["Status"]["Health"] = "Critical";
319 }
320 });
321}
322
323inline void
Ed Tanousac106bf2023-06-07 09:24:59 -0700324 getPCIeDeviceState(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
325 const std::string& pcieDevicePath,
326 const std::string& service)
Lakshmi Yadlapatic6bb3282023-04-12 16:56:49 -0500327{
328 sdbusplus::asio::getProperty<bool>(
329 *crow::connections::systemBus, service, pcieDevicePath,
330 "xyz.openbmc_project.Inventory.Item", "Present",
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500331 [asyncResp](const boost::system::error_code& ec, bool value) {
Lakshmi Yadlapatic6bb3282023-04-12 16:56:49 -0500332 if (ec)
333 {
334 if (ec.value() != EBADR)
335 {
Ed Tanous62598e32023-07-17 17:06:25 -0700336 BMCWEB_LOG_ERROR("DBUS response error for State");
Ed Tanousac106bf2023-06-07 09:24:59 -0700337 messages::internalError(asyncResp->res);
Lakshmi Yadlapatic6bb3282023-04-12 16:56:49 -0500338 }
339 return;
340 }
341
342 if (!value)
343 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700344 asyncResp->res.jsonValue["Status"]["State"] = "Absent";
Lakshmi Yadlapatic6bb3282023-04-12 16:56:49 -0500345 }
346 });
347}
348
Ed Tanousac106bf2023-06-07 09:24:59 -0700349inline void
350 getPCIeDeviceAsset(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
351 const std::string& pcieDevicePath,
352 const std::string& service)
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600353{
354 sdbusplus::asio::getAllProperties(
355 *crow::connections::systemBus, service, pcieDevicePath,
356 "xyz.openbmc_project.Inventory.Decorator.Asset",
Ed Tanousac106bf2023-06-07 09:24:59 -0700357 [pcieDevicePath, asyncResp{asyncResp}](
358 const boost::system::error_code& ec,
359 const dbus::utility::DBusPropertiesMap& assetList) {
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600360 if (ec)
361 {
362 if (ec.value() != EBADR)
363 {
Ed Tanous62598e32023-07-17 17:06:25 -0700364 BMCWEB_LOG_ERROR("DBUS response error for Properties{}",
365 ec.value());
Ed Tanousac106bf2023-06-07 09:24:59 -0700366 messages::internalError(asyncResp->res);
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600367 }
368 return;
369 }
370
371 const std::string* manufacturer = nullptr;
372 const std::string* model = nullptr;
373 const std::string* partNumber = nullptr;
374 const std::string* serialNumber = nullptr;
375 const std::string* sparePartNumber = nullptr;
376
377 const bool success = sdbusplus::unpackPropertiesNoThrow(
378 dbus_utils::UnpackErrorPrinter(), assetList, "Manufacturer",
379 manufacturer, "Model", model, "PartNumber", partNumber,
380 "SerialNumber", serialNumber, "SparePartNumber", sparePartNumber);
381
382 if (!success)
383 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700384 messages::internalError(asyncResp->res);
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600385 return;
386 }
387
388 if (manufacturer != nullptr)
389 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700390 asyncResp->res.jsonValue["Manufacturer"] = *manufacturer;
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600391 }
392 if (model != nullptr)
393 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700394 asyncResp->res.jsonValue["Model"] = *model;
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600395 }
396
397 if (partNumber != nullptr)
398 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700399 asyncResp->res.jsonValue["PartNumber"] = *partNumber;
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600400 }
401
402 if (serialNumber != nullptr)
403 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700404 asyncResp->res.jsonValue["SerialNumber"] = *serialNumber;
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600405 }
406
407 if (sparePartNumber != nullptr && !sparePartNumber->empty())
408 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700409 asyncResp->res.jsonValue["SparePartNumber"] = *sparePartNumber;
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600410 }
411 });
412}
413
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600414inline void addPCIeDeviceProperties(
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500415 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
416 const std::string& pcieDeviceId,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600417 const dbus::utility::DBusPropertiesMap& pcieDevProperties)
418{
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600419 const std::string* generationInUse = nullptr;
Konstantin Aladyshev814bf202023-07-04 16:30:10 +0300420 const std::string* generationSupported = nullptr;
Konstantin Aladyshev9bb0a7f2023-07-04 12:59:34 +0300421 const size_t* lanesInUse = nullptr;
Konstantin Aladyshev814bf202023-07-04 16:30:10 +0300422 const size_t* maxLanes = nullptr;
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600423
424 const bool success = sdbusplus::unpackPropertiesNoThrow(
Ed Tanous609ba4c2023-07-11 09:14:24 -0700425 dbus_utils::UnpackErrorPrinter(), pcieDevProperties, "GenerationInUse",
426 generationInUse, "GenerationSupported", generationSupported,
427 "LanesInUse", lanesInUse, "MaxLanes", maxLanes);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600428
429 if (!success)
430 {
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500431 messages::internalError(asyncResp->res);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600432 return;
433 }
434
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600435 if (generationInUse != nullptr)
436 {
437 std::optional<pcie_device::PCIeTypes> redfishGenerationInUse =
Lakshmi Yadlapatic49c3292023-04-19 16:42:35 -0500438 pcie_util::redfishPcieGenerationFromDbus(*generationInUse);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600439
440 if (!redfishGenerationInUse)
441 {
Ed Tanous62598e32023-07-17 17:06:25 -0700442 BMCWEB_LOG_WARNING("Unknown PCIe Device Generation: {}",
443 *generationInUse);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600444 }
Lakshmi Yadlapaticf3b4842023-06-27 02:36:53 -0500445 else
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600446 {
Lakshmi Yadlapaticf3b4842023-06-27 02:36:53 -0500447 if (*redfishGenerationInUse == pcie_device::PCIeTypes::Invalid)
448 {
Ed Tanous62598e32023-07-17 17:06:25 -0700449 BMCWEB_LOG_ERROR("Invalid PCIe Device Generation: {}",
450 *generationInUse);
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500451 messages::internalError(asyncResp->res);
Lakshmi Yadlapaticf3b4842023-06-27 02:36:53 -0500452 return;
453 }
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500454 asyncResp->res.jsonValue["PCIeInterface"]["PCIeType"] =
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600455 *redfishGenerationInUse;
456 }
457 }
458
Konstantin Aladyshev814bf202023-07-04 16:30:10 +0300459 if (generationSupported != nullptr)
460 {
461 std::optional<pcie_device::PCIeTypes> redfishGenerationSupported =
462 pcie_util::redfishPcieGenerationFromDbus(*generationSupported);
463
464 if (!redfishGenerationSupported)
465 {
Ed Tanous62598e32023-07-17 17:06:25 -0700466 BMCWEB_LOG_WARNING("Unknown PCIe Device Generation: {}",
467 *generationSupported);
Konstantin Aladyshev814bf202023-07-04 16:30:10 +0300468 }
469 else
470 {
471 if (*redfishGenerationSupported == pcie_device::PCIeTypes::Invalid)
472 {
Ed Tanous62598e32023-07-17 17:06:25 -0700473 BMCWEB_LOG_ERROR("Invalid PCIe Device Generation: {}",
474 *generationSupported);
Konstantin Aladyshev814bf202023-07-04 16:30:10 +0300475 messages::internalError(asyncResp->res);
476 return;
477 }
478 asyncResp->res.jsonValue["PCIeInterface"]["MaxPCIeType"] =
479 *redfishGenerationSupported;
480 }
481 }
482
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600483 // The default value of LanesInUse is 0, and the field will be
484 // left as off if it is a default value.
485 if (lanesInUse != nullptr && *lanesInUse != 0)
486 {
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500487 asyncResp->res.jsonValue["PCIeInterface"]["LanesInUse"] = *lanesInUse;
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600488 }
Konstantin Aladyshev814bf202023-07-04 16:30:10 +0300489 // The default value of MaxLanes is 0, and the field will be
490 // left as off if it is a default value.
491 if (maxLanes != nullptr && *maxLanes != 0)
492 {
493 asyncResp->res.jsonValue["PCIeInterface"]["MaxLanes"] = *maxLanes;
494 }
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600495
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500496 asyncResp->res.jsonValue["PCIeFunctions"]["@odata.id"] =
497 boost::urls::format(
498 "/redfish/v1/Systems/system/PCIeDevices/{}/PCIeFunctions",
499 pcieDeviceId);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600500}
501
502inline void getPCIeDeviceProperties(
Ed Tanousac106bf2023-06-07 09:24:59 -0700503 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600504 const std::string& pcieDevicePath, const std::string& service,
505 const std::function<void(
506 const dbus::utility::DBusPropertiesMap& pcieDevProperties)>&& callback)
507{
508 sdbusplus::asio::getAllProperties(
509 *crow::connections::systemBus, service, pcieDevicePath,
510 "xyz.openbmc_project.Inventory.Item.PCIeDevice",
Ed Tanousac106bf2023-06-07 09:24:59 -0700511 [asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600512 callback](const boost::system::error_code& ec,
513 const dbus::utility::DBusPropertiesMap& pcieDevProperties) {
514 if (ec)
515 {
516 if (ec.value() != EBADR)
517 {
Ed Tanous62598e32023-07-17 17:06:25 -0700518 BMCWEB_LOG_ERROR("DBUS response error for Properties");
Ed Tanousac106bf2023-06-07 09:24:59 -0700519 messages::internalError(asyncResp->res);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600520 }
521 return;
522 }
523 callback(pcieDevProperties);
524 });
525}
526
527inline void addPCIeDeviceCommonProperties(
Ed Tanousac106bf2023-06-07 09:24:59 -0700528 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600529 const std::string& pcieDeviceId)
530{
Ed Tanousac106bf2023-06-07 09:24:59 -0700531 asyncResp->res.addHeader(
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600532 boost::beast::http::field::link,
533 "</redfish/v1/JsonSchemas/PCIeDevice/PCIeDevice.json>; rel=describedby");
Ed Tanousac106bf2023-06-07 09:24:59 -0700534 asyncResp->res.jsonValue["@odata.type"] = "#PCIeDevice.v1_9_0.PCIeDevice";
535 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
Ed Tanousef4c65b2023-04-24 15:28:50 -0700536 "/redfish/v1/Systems/system/PCIeDevices/{}", pcieDeviceId);
Ed Tanousac106bf2023-06-07 09:24:59 -0700537 asyncResp->res.jsonValue["Name"] = "PCIe Device";
538 asyncResp->res.jsonValue["Id"] = pcieDeviceId;
539 asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
Lakshmi Yadlapatie164f1b2023-04-12 17:01:34 -0500540 asyncResp->res.jsonValue["Status"]["Health"] = "OK";
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600541}
542
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500543inline void afterGetValidPcieDevicePath(
544 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
545 const std::string& pcieDeviceId, const std::string& pcieDevicePath,
546 const std::string& service)
547{
548 addPCIeDeviceCommonProperties(asyncResp, pcieDeviceId);
549 getPCIeDeviceAsset(asyncResp, pcieDevicePath, service);
550 getPCIeDeviceState(asyncResp, pcieDevicePath, service);
551 getPCIeDeviceHealth(asyncResp, pcieDevicePath, service);
552 getPCIeDeviceProperties(
553 asyncResp, pcieDevicePath, service,
554 std::bind_front(addPCIeDeviceProperties, asyncResp, pcieDeviceId));
555 getPCIeDeviceSlotPath(
556 pcieDevicePath, asyncResp,
557 std::bind_front(afterGetPCIeDeviceSlotPath, asyncResp));
558}
559
Ed Tanousac106bf2023-06-07 09:24:59 -0700560inline void
561 handlePCIeDeviceGet(App& app, const crow::Request& req,
562 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
563 const std::string& systemName,
564 const std::string& pcieDeviceId)
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600565{
Ed Tanousac106bf2023-06-07 09:24:59 -0700566 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600567 {
568 return;
569 }
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800570 if constexpr (bmcwebEnableMultiHost)
571 {
572 // Option currently returns no systems. TBD
573 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
574 systemName);
575 return;
576 }
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600577 if (systemName != "system")
578 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700579 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
580 systemName);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600581 return;
582 }
583
584 getValidPCIeDevicePath(
Ed Tanousac106bf2023-06-07 09:24:59 -0700585 pcieDeviceId, asyncResp,
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500586 std::bind_front(afterGetValidPcieDevicePath, asyncResp, pcieDeviceId));
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600587}
588
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700589inline void requestRoutesSystemPCIeDevice(App& app)
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -0800590{
Ed Tanous22d268c2022-05-19 09:39:07 -0700591 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/PCIeDevices/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700592 .privileges(redfish::privileges::getPCIeDevice)
Ed Tanous002d39b2022-05-31 08:59:27 -0700593 .methods(boost::beast::http::verb::get)(
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600594 std::bind_front(handlePCIeDeviceGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700595}
596
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600597inline void addPCIeFunctionList(
598 crow::Response& res, const std::string& pcieDeviceId,
599 const dbus::utility::DBusPropertiesMap& pcieDevProperties)
600{
601 nlohmann::json& pcieFunctionList = res.jsonValue["Members"];
602 pcieFunctionList = nlohmann::json::array();
603 static constexpr const int maxPciFunctionNum = 8;
604
605 for (int functionNum = 0; functionNum < maxPciFunctionNum; functionNum++)
606 {
607 // Check if this function exists by
608 // looking for a device ID
Patrick Williams89492a12023-05-10 07:51:34 -0500609 std::string devIDProperty = "Function" + std::to_string(functionNum) +
610 "DeviceId";
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600611 const std::string* property = nullptr;
612 for (const auto& propEntry : pcieDevProperties)
613 {
614 if (propEntry.first == devIDProperty)
615 {
616 property = std::get_if<std::string>(&propEntry.second);
617 break;
618 }
619 }
620 if (property == nullptr || property->empty())
621 {
622 continue;
623 }
624
625 nlohmann::json::object_t pcieFunction;
Ed Tanousef4c65b2023-04-24 15:28:50 -0700626 pcieFunction["@odata.id"] = boost::urls::format(
627 "/redfish/v1/Systems/system/PCIeDevices/{}/PCIeFunctions/{}",
628 pcieDeviceId, std::to_string(functionNum));
Patrick Williamsb2ba3072023-05-12 10:27:39 -0500629 pcieFunctionList.emplace_back(std::move(pcieFunction));
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600630 }
631 res.jsonValue["PCIeFunctions@odata.count"] = pcieFunctionList.size();
632}
633
634inline void handlePCIeFunctionCollectionGet(
635 App& app, const crow::Request& req,
Ed Tanousac106bf2023-06-07 09:24:59 -0700636 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800637 const std::string& systemName, const std::string& pcieDeviceId)
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600638{
Ed Tanousac106bf2023-06-07 09:24:59 -0700639 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600640 {
641 return;
642 }
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800643 if constexpr (bmcwebEnableMultiHost)
644 {
645 // Option currently returns no systems. TBD
646 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
647 systemName);
648 return;
649 }
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600650
651 getValidPCIeDevicePath(
Ed Tanousac106bf2023-06-07 09:24:59 -0700652 pcieDeviceId, asyncResp,
653 [asyncResp, pcieDeviceId](const std::string& pcieDevicePath,
654 const std::string& service) {
655 asyncResp->res.addHeader(
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600656 boost::beast::http::field::link,
657 "</redfish/v1/JsonSchemas/PCIeFunctionCollection/PCIeFunctionCollection.json>; rel=describedby");
Ed Tanousac106bf2023-06-07 09:24:59 -0700658 asyncResp->res.jsonValue["@odata.type"] =
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600659 "#PCIeFunctionCollection.PCIeFunctionCollection";
Ed Tanousac106bf2023-06-07 09:24:59 -0700660 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
Ed Tanousef4c65b2023-04-24 15:28:50 -0700661 "/redfish/v1/Systems/system/PCIeDevices/{}/PCIeFunctions",
662 pcieDeviceId);
Ed Tanousac106bf2023-06-07 09:24:59 -0700663 asyncResp->res.jsonValue["Name"] = "PCIe Function Collection";
664 asyncResp->res.jsonValue["Description"] =
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600665 "Collection of PCIe Functions for PCIe Device " + pcieDeviceId;
666 getPCIeDeviceProperties(
Ed Tanousac106bf2023-06-07 09:24:59 -0700667 asyncResp, pcieDevicePath, service,
668 [asyncResp, pcieDeviceId](
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600669 const dbus::utility::DBusPropertiesMap& pcieDevProperties) {
Ed Tanousac106bf2023-06-07 09:24:59 -0700670 addPCIeFunctionList(asyncResp->res, pcieDeviceId,
671 pcieDevProperties);
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600672 });
673 });
674}
675
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700676inline void requestRoutesSystemPCIeFunctionCollection(App& app)
677{
678 /**
679 * Functions triggers appropriate requests on DBus
680 */
681 BMCWEB_ROUTE(app,
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800682 "/redfish/v1/Systems/<str>/PCIeDevices/<str>/PCIeFunctions/")
Ed Tanoused398212021-06-09 17:05:54 -0700683 .privileges(redfish::privileges::getPCIeFunctionCollection)
Ed Tanous002d39b2022-05-31 08:59:27 -0700684 .methods(boost::beast::http::verb::get)(
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600685 std::bind_front(handlePCIeFunctionCollectionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700686}
687
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600688inline bool validatePCIeFunctionId(
Myung Baed5e74b82023-05-31 11:28:02 -0500689 uint64_t pcieFunctionId,
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600690 const dbus::utility::DBusPropertiesMap& pcieDevProperties)
691{
Myung Baed5e74b82023-05-31 11:28:02 -0500692 std::string functionName = "Function" + std::to_string(pcieFunctionId);
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600693 std::string devIDProperty = functionName + "DeviceId";
694
695 const std::string* devIdProperty = nullptr;
696 for (const auto& property : pcieDevProperties)
697 {
698 if (property.first == devIDProperty)
699 {
700 devIdProperty = std::get_if<std::string>(&property.second);
701 break;
702 }
703 }
704 return (devIdProperty != nullptr && !devIdProperty->empty());
705}
706
707inline void addPCIeFunctionProperties(
Ed Tanouse14742c2023-05-31 10:27:49 -0700708 crow::Response& resp, uint64_t pcieFunctionId,
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600709 const dbus::utility::DBusPropertiesMap& pcieDevProperties)
710{
Ed Tanouse14742c2023-05-31 10:27:49 -0700711 std::string functionName = "Function" + std::to_string(pcieFunctionId);
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600712 for (const auto& property : pcieDevProperties)
713 {
714 const std::string* strProperty =
715 std::get_if<std::string>(&property.second);
716
717 if (property.first == functionName + "DeviceId")
718 {
719 resp.jsonValue["DeviceId"] = *strProperty;
720 }
721 if (property.first == functionName + "VendorId")
722 {
723 resp.jsonValue["VendorId"] = *strProperty;
724 }
725 // TODO: FunctionType and DeviceClass are Redfish enums. The D-Bus
726 // property strings should be mapped correctly to ensure these
727 // strings are Redfish enum values. For now just check for empty.
728 if (property.first == functionName + "FunctionType")
729 {
730 if (!strProperty->empty())
731 {
732 resp.jsonValue["FunctionType"] = *strProperty;
733 }
734 }
735 if (property.first == functionName + "DeviceClass")
736 {
737 if (!strProperty->empty())
738 {
739 resp.jsonValue["DeviceClass"] = *strProperty;
740 }
741 }
742 if (property.first == functionName + "ClassCode")
743 {
744 resp.jsonValue["ClassCode"] = *strProperty;
745 }
746 if (property.first == functionName + "RevisionId")
747 {
748 resp.jsonValue["RevisionId"] = *strProperty;
749 }
750 if (property.first == functionName + "SubsystemId")
751 {
752 resp.jsonValue["SubsystemId"] = *strProperty;
753 }
754 if (property.first == functionName + "SubsystemVendorId")
755 {
756 resp.jsonValue["SubsystemVendorId"] = *strProperty;
757 }
758 }
759}
760
761inline void addPCIeFunctionCommonProperties(crow::Response& resp,
762 const std::string& pcieDeviceId,
Ed Tanouse14742c2023-05-31 10:27:49 -0700763 uint64_t pcieFunctionId)
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600764{
765 resp.addHeader(
766 boost::beast::http::field::link,
767 "</redfish/v1/JsonSchemas/PCIeFunction/PCIeFunction.json>; rel=describedby");
768 resp.jsonValue["@odata.type"] = "#PCIeFunction.v1_2_3.PCIeFunction";
Ed Tanousef4c65b2023-04-24 15:28:50 -0700769 resp.jsonValue["@odata.id"] = boost::urls::format(
770 "/redfish/v1/Systems/system/PCIeDevices/{}/PCIeFunctions/{}",
Lakshmi Yadlapati768a1432023-06-14 12:45:54 -0500771 pcieDeviceId, std::to_string(pcieFunctionId));
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600772 resp.jsonValue["Name"] = "PCIe Function";
Ed Tanouse14742c2023-05-31 10:27:49 -0700773 resp.jsonValue["Id"] = std::to_string(pcieFunctionId);
774 resp.jsonValue["FunctionId"] = pcieFunctionId;
Ed Tanousef4c65b2023-04-24 15:28:50 -0700775 resp.jsonValue["Links"]["PCIeDevice"]["@odata.id"] = boost::urls::format(
776 "/redfish/v1/Systems/system/PCIeDevices/{}", pcieDeviceId);
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600777}
778
779inline void
780 handlePCIeFunctionGet(App& app, const crow::Request& req,
Ed Tanousac106bf2023-06-07 09:24:59 -0700781 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800782 const std::string& systemName,
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600783 const std::string& pcieDeviceId,
Ed Tanouse14742c2023-05-31 10:27:49 -0700784 const std::string& pcieFunctionIdStr)
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600785{
Ed Tanousac106bf2023-06-07 09:24:59 -0700786 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600787 {
788 return;
789 }
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800790 if constexpr (bmcwebEnableMultiHost)
791 {
792 // Option currently returns no systems. TBD
793 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
794 systemName);
795 return;
796 }
797 if (systemName != "system")
798 {
799 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
800 systemName);
801 return;
802 }
803
Ed Tanouse14742c2023-05-31 10:27:49 -0700804 uint64_t pcieFunctionId = 0;
805 std::from_chars_result result = std::from_chars(
806 &*pcieFunctionIdStr.begin(), &*pcieFunctionIdStr.end(), pcieFunctionId);
807 if (result.ec != std::errc{} || result.ptr != &*pcieFunctionIdStr.end())
808 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700809 messages::resourceNotFound(asyncResp->res, "PCIeFunction",
Ed Tanouse14742c2023-05-31 10:27:49 -0700810 pcieFunctionIdStr);
811 return;
812 }
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600813
Ed Tanousac106bf2023-06-07 09:24:59 -0700814 getValidPCIeDevicePath(pcieDeviceId, asyncResp,
815 [asyncResp, pcieDeviceId,
816 pcieFunctionId](const std::string& pcieDevicePath,
817 const std::string& service) {
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600818 getPCIeDeviceProperties(
Ed Tanousac106bf2023-06-07 09:24:59 -0700819 asyncResp, pcieDevicePath, service,
820 [asyncResp, pcieDeviceId, pcieFunctionId](
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600821 const dbus::utility::DBusPropertiesMap& pcieDevProperties) {
Ed Tanousac106bf2023-06-07 09:24:59 -0700822 addPCIeFunctionCommonProperties(asyncResp->res, pcieDeviceId,
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600823 pcieFunctionId);
Ed Tanousac106bf2023-06-07 09:24:59 -0700824 addPCIeFunctionProperties(asyncResp->res, pcieFunctionId,
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600825 pcieDevProperties);
826 });
Ed Tanousac106bf2023-06-07 09:24:59 -0700827 });
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600828}
829
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700830inline void requestRoutesSystemPCIeFunction(App& app)
831{
832 BMCWEB_ROUTE(
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800833 app, "/redfish/v1/Systems/<str>/PCIeDevices/<str>/PCIeFunctions/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700834 .privileges(redfish::privileges::getPCIeFunction)
Ed Tanous002d39b2022-05-31 08:59:27 -0700835 .methods(boost::beast::http::verb::get)(
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600836 std::bind_front(handlePCIeFunctionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700837}
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -0800838
839} // namespace redfish