blob: 3860216a1d4c5ad1f74bcfdad78fb8d3e4a27ed9 [file] [log] [blame]
Ed Tanous40e9b922024-09-10 13:50:16 -07001// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright OpenBMC Authors
3// SPDX-FileCopyrightText: Copyright 2018 Intel Corporation
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -08004
5#pragma once
6
Ed Tanousd7857202025-01-28 15:32:26 -08007#include "bmcweb_config.h"
8
Ed Tanous3ccb3ad2023-01-13 17:40:03 -08009#include "app.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -080010#include "async_resp.hpp"
George Liu7a1dbc42022-12-07 16:03:22 +080011#include "dbus_utility.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -080012#include "error_messages.hpp"
13#include "generated/enums/pcie_device.hpp"
14#include "generated/enums/pcie_slots.hpp"
Ed Tanous539d8c62024-06-19 14:38:27 -070015#include "generated/enums/resource.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -080016#include "http_request.hpp"
17#include "logging.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080018#include "query.hpp"
19#include "registries/privilege_registry.hpp"
Myung Baef7e62c12025-09-07 14:02:08 -050020#include "utils/asset_utils.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080021#include "utils/dbus_utils.hpp"
Lakshmi Yadlapatic49c3292023-04-19 16:42:35 -050022#include "utils/pcie_util.hpp"
Ed Tanous0ec8b832022-03-14 14:56:47 -070023
Ed Tanousd7857202025-01-28 15:32:26 -080024#include <asm-generic/errno.h>
25
26#include <boost/beast/http/field.hpp>
27#include <boost/beast/http/verb.hpp>
Ed Tanousef4c65b2023-04-24 15:28:50 -070028#include <boost/url/format.hpp>
Krzysztof Grobelnyd1bde9e2022-09-07 10:40:51 +020029#include <sdbusplus/unpack_properties.hpp>
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -080030
Ed Tanousd7857202025-01-28 15:32:26 -080031#include <array>
32#include <charconv>
33#include <cstddef>
34#include <cstdint>
35#include <format>
36#include <functional>
Myung Bae8c1d0542024-03-12 17:50:48 -050037#include <limits>
Ed Tanousd7857202025-01-28 15:32:26 -080038#include <memory>
39#include <optional>
40#include <string>
41#include <string_view>
42#include <system_error>
43#include <utility>
44#include <variant>
Myung Bae8c1d0542024-03-12 17:50:48 -050045
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -080046namespace redfish
47{
48
Patrick Williams89492a12023-05-10 07:51:34 -050049static constexpr const char* inventoryPath = "/xyz/openbmc_project/inventory";
Lakshmi Yadlapati94c3a102023-04-05 18:11:22 -050050static constexpr std::array<std::string_view, 1> pcieDeviceInterface = {
51 "xyz.openbmc_project.Inventory.Item.PCIeDevice"};
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -050052static constexpr std::array<std::string_view, 1> pcieSlotInterface = {
53 "xyz.openbmc_project.Inventory.Item.PCIeSlot"};
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -080054
Ed Tanous4ff0f1f2024-09-04 17:27:37 -070055inline void handlePCIeDevicePath(
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060056 const std::string& pcieDeviceId,
Ed Tanousac106bf2023-06-07 09:24:59 -070057 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060058 const dbus::utility::MapperGetSubTreePathsResponse& pcieDevicePaths,
59 const std::function<void(const std::string& pcieDevicePath,
60 const std::string& service)>& callback)
61
62{
63 for (const std::string& pcieDevicePath : pcieDevicePaths)
64 {
65 std::string pciecDeviceName =
66 sdbusplus::message::object_path(pcieDevicePath).filename();
67 if (pciecDeviceName.empty() || pciecDeviceName != pcieDeviceId)
68 {
69 continue;
70 }
71
72 dbus::utility::getDbusObject(
Konstantin Aladyshev3a58c5a2024-08-05 12:57:13 +030073 pcieDevicePath, pcieDeviceInterface,
Ed Tanousac106bf2023-06-07 09:24:59 -070074 [pcieDevicePath, asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060075 callback](const boost::system::error_code& ec,
76 const dbus::utility::MapperGetObject& object) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -040077 if (ec || object.empty())
78 {
79 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
80 messages::internalError(asyncResp->res);
81 return;
82 }
83 callback(pcieDevicePath, object.begin()->first);
84 });
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060085 return;
86 }
87
Ed Tanous62598e32023-07-17 17:06:25 -070088 BMCWEB_LOG_WARNING("PCIe Device not found");
Ed Tanousac106bf2023-06-07 09:24:59 -070089 messages::resourceNotFound(asyncResp->res, "PCIeDevice", pcieDeviceId);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060090}
91
Ed Tanous4ff0f1f2024-09-04 17:27:37 -070092inline void getValidPCIeDevicePath(
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060093 const std::string& pcieDeviceId,
Ed Tanousac106bf2023-06-07 09:24:59 -070094 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060095 const std::function<void(const std::string& pcieDevicePath,
96 const std::string& service)>& callback)
97{
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060098 dbus::utility::getSubTreePaths(
Lakshmi Yadlapati94c3a102023-04-05 18:11:22 -050099 inventoryPath, 0, pcieDeviceInterface,
Ed Tanousac106bf2023-06-07 09:24:59 -0700100 [pcieDeviceId, asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600101 callback](const boost::system::error_code& ec,
102 const dbus::utility::MapperGetSubTreePathsResponse&
103 pcieDevicePaths) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400104 if (ec)
105 {
106 BMCWEB_LOG_ERROR("D-Bus response error on GetSubTree {}", ec);
107 messages::internalError(asyncResp->res);
108 return;
109 }
110 handlePCIeDevicePath(pcieDeviceId, asyncResp, pcieDevicePaths,
111 callback);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600112 return;
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400113 });
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600114}
115
Ed Tanous4ff0f1f2024-09-04 17:27:37 -0700116inline void handlePCIeDeviceCollectionGet(
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600117 crow::App& app, const crow::Request& req,
Ed Tanousac106bf2023-06-07 09:24:59 -0700118 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600119 const std::string& systemName)
120{
Ed Tanousac106bf2023-06-07 09:24:59 -0700121 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600122 {
123 return;
124 }
Ed Tanous25b54db2024-04-17 15:40:31 -0700125 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800126 {
127 // Option currently returns no systems. TBD
128 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
129 systemName);
130 return;
131 }
Ed Tanous253f11b2024-05-16 09:38:31 -0700132 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600133 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700134 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
135 systemName);
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600136 return;
137 }
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600138
Ed Tanousac106bf2023-06-07 09:24:59 -0700139 asyncResp->res.addHeader(boost::beast::http::field::link,
140 "</redfish/v1/JsonSchemas/PCIeDeviceCollection/"
141 "PCIeDeviceCollection.json>; rel=describedby");
142 asyncResp->res.jsonValue["@odata.type"] =
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600143 "#PCIeDeviceCollection.PCIeDeviceCollection";
Ed Tanous253f11b2024-05-16 09:38:31 -0700144 asyncResp->res.jsonValue["@odata.id"] = std::format(
145 "/redfish/v1/Systems/{}/PCIeDevices", BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanousac106bf2023-06-07 09:24:59 -0700146 asyncResp->res.jsonValue["Name"] = "PCIe Device Collection";
147 asyncResp->res.jsonValue["Description"] = "Collection of PCIe Devices";
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600148
Lakshmi Yadlapati70c4d542023-06-08 04:37:18 -0500149 pcie_util::getPCIeDeviceList(asyncResp,
150 nlohmann::json::json_pointer("/Members"));
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600151}
152
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700153inline void requestRoutesSystemPCIeDeviceCollection(App& app)
Jason M. Billsadbe1922019-10-14 15:44:35 -0700154{
Jason M. Billsadbe1922019-10-14 15:44:35 -0700155 /**
156 * Functions triggers appropriate requests on DBus
157 */
Ed Tanous22d268c2022-05-19 09:39:07 -0700158 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/PCIeDevices/")
Ed Tanoused398212021-06-09 17:05:54 -0700159 .privileges(redfish::privileges::getPCIeDeviceCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700160 .methods(boost::beast::http::verb::get)(
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600161 std::bind_front(handlePCIeDeviceCollectionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700162}
163
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500164inline void addPCIeSlotProperties(
165 crow::Response& res, const boost::system::error_code& ec,
166 const dbus::utility::DBusPropertiesMap& pcieSlotProperties)
167{
168 if (ec)
169 {
Ed Tanous62598e32023-07-17 17:06:25 -0700170 BMCWEB_LOG_ERROR("DBUS response error for getAllProperties{}",
171 ec.value());
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500172 messages::internalError(res);
173 return;
174 }
175 std::string generation;
176 size_t lanes = 0;
177 std::string slotType;
178
179 bool success = sdbusplus::unpackPropertiesNoThrow(
180 dbus_utils::UnpackErrorPrinter(), pcieSlotProperties, "Generation",
181 generation, "Lanes", lanes, "SlotType", slotType);
182
183 if (!success)
184 {
185 messages::internalError(res);
186 return;
187 }
188
189 std::optional<pcie_device::PCIeTypes> pcieType =
190 pcie_util::redfishPcieGenerationFromDbus(generation);
191 if (!pcieType)
192 {
Ed Tanous62598e32023-07-17 17:06:25 -0700193 BMCWEB_LOG_WARNING("Unknown PCIeType: {}", generation);
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500194 }
195 else
196 {
197 if (*pcieType == pcie_device::PCIeTypes::Invalid)
198 {
Ed Tanous62598e32023-07-17 17:06:25 -0700199 BMCWEB_LOG_ERROR("Invalid PCIeType: {}", generation);
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500200 messages::internalError(res);
201 return;
202 }
203 res.jsonValue["Slot"]["PCIeType"] = *pcieType;
204 }
205
Konstantin Aladyshev82f80322023-07-10 15:00:38 +0300206 if (lanes != 0)
207 {
208 res.jsonValue["Slot"]["Lanes"] = lanes;
209 }
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500210
211 std::optional<pcie_slots::SlotTypes> redfishSlotType =
212 pcie_util::dbusSlotTypeToRf(slotType);
213 if (!redfishSlotType)
214 {
Ed Tanous62598e32023-07-17 17:06:25 -0700215 BMCWEB_LOG_WARNING("Unknown PCIeSlot Type: {}", slotType);
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500216 }
217 else
218 {
219 if (*redfishSlotType == pcie_slots::SlotTypes::Invalid)
220 {
Ed Tanous62598e32023-07-17 17:06:25 -0700221 BMCWEB_LOG_ERROR("Invalid PCIeSlot type: {}", slotType);
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500222 messages::internalError(res);
223 return;
224 }
225 res.jsonValue["Slot"]["SlotType"] = *redfishSlotType;
226 }
227}
228
229inline void getPCIeDeviceSlotPath(
230 const std::string& pcieDevicePath,
231 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
232 std::function<void(const std::string& pcieDeviceSlot)>&& callback)
233{
234 std::string associationPath = pcieDevicePath + "/contained_by";
235 dbus::utility::getAssociatedSubTreePaths(
236 associationPath, sdbusplus::message::object_path(inventoryPath), 0,
237 pcieSlotInterface,
Ed Tanous8cb2c022024-03-27 16:31:46 -0700238 [callback = std::move(callback), asyncResp, pcieDevicePath](
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500239 const boost::system::error_code& ec,
240 const dbus::utility::MapperGetSubTreePathsResponse& endpoints) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400241 if (ec)
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500242 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400243 if (ec.value() == EBADR)
244 {
245 // Missing association is not an error
246 return;
247 }
248 BMCWEB_LOG_ERROR(
249 "DBUS response error for getAssociatedSubTreePaths {}",
250 ec.value());
251 messages::internalError(asyncResp->res);
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500252 return;
253 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400254 if (endpoints.size() > 1)
255 {
256 BMCWEB_LOG_ERROR(
Gunnar Millsa6bd55b2025-01-13 11:24:00 -0600257 "PCIeDevice {} is associated with more than one PCIeSlot: {}",
258 pcieDevicePath, endpoints.size());
Myung Bae67f0b9c2025-06-23 09:52:37 -0400259 for (const std::string& slotPath : endpoints)
260 {
261 BMCWEB_LOG_ERROR("Invalid PCIeSlotPath: {}", slotPath);
262 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400263 messages::internalError(asyncResp->res);
264 return;
265 }
266 if (endpoints.empty())
267 {
268 // If the device doesn't have an association, return without
269 // PCIe Slot properties
270 BMCWEB_LOG_DEBUG("PCIeDevice is not associated with PCIeSlot");
271 return;
272 }
273 callback(endpoints[0]);
274 });
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500275}
276
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400277inline void afterGetDbusObject(
278 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
279 const std::string& pcieDeviceSlot, const boost::system::error_code& ec,
280 const dbus::utility::MapperGetObject& object)
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500281{
282 if (ec || object.empty())
283 {
Ed Tanous62598e32023-07-17 17:06:25 -0700284 BMCWEB_LOG_ERROR("DBUS response error for getDbusObject {}",
285 ec.value());
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500286 messages::internalError(asyncResp->res);
287 return;
288 }
Ed Tanousdeae6a72024-11-11 21:58:57 -0800289 dbus::utility::getAllProperties(
290 object.begin()->first, pcieDeviceSlot,
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500291 "xyz.openbmc_project.Inventory.Item.PCIeSlot",
292 [asyncResp](
293 const boost::system::error_code& ec2,
294 const dbus::utility::DBusPropertiesMap& pcieSlotProperties) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400295 addPCIeSlotProperties(asyncResp->res, ec2, pcieSlotProperties);
296 });
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500297}
298
299inline void afterGetPCIeDeviceSlotPath(
300 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
301 const std::string& pcieDeviceSlot)
302{
303 dbus::utility::getDbusObject(
304 pcieDeviceSlot, pcieSlotInterface,
305 [asyncResp,
306 pcieDeviceSlot](const boost::system::error_code& ec,
307 const dbus::utility::MapperGetObject& object) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400308 afterGetDbusObject(asyncResp, pcieDeviceSlot, ec, object);
309 });
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500310}
311
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400312inline void getPCIeDeviceHealth(
313 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
314 const std::string& pcieDevicePath, const std::string& service)
Lakshmi Yadlapatie164f1b2023-04-12 17:01:34 -0500315{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800316 dbus::utility::getProperty<bool>(
317 service, pcieDevicePath,
Lakshmi Yadlapatie164f1b2023-04-12 17:01:34 -0500318 "xyz.openbmc_project.State.Decorator.OperationalStatus", "Functional",
319 [asyncResp](const boost::system::error_code& ec, const bool value) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400320 if (ec)
Lakshmi Yadlapatie164f1b2023-04-12 17:01:34 -0500321 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400322 if (ec.value() != EBADR)
323 {
324 BMCWEB_LOG_ERROR("DBUS response error for Health {}",
325 ec.value());
326 messages::internalError(asyncResp->res);
327 }
328 return;
Lakshmi Yadlapatie164f1b2023-04-12 17:01:34 -0500329 }
Lakshmi Yadlapatie164f1b2023-04-12 17:01:34 -0500330
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400331 if (!value)
332 {
333 asyncResp->res.jsonValue["Status"]["Health"] =
334 resource::Health::Critical;
335 }
336 });
Lakshmi Yadlapatie164f1b2023-04-12 17:01:34 -0500337}
338
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400339inline void getPCIeDeviceState(
340 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
341 const std::string& pcieDevicePath, const std::string& service)
Lakshmi Yadlapatic6bb3282023-04-12 16:56:49 -0500342{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800343 dbus::utility::getProperty<bool>(
344 service, pcieDevicePath, "xyz.openbmc_project.Inventory.Item",
345 "Present",
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500346 [asyncResp](const boost::system::error_code& ec, bool value) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400347 if (ec)
Lakshmi Yadlapatic6bb3282023-04-12 16:56:49 -0500348 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400349 if (ec.value() != EBADR)
350 {
351 BMCWEB_LOG_ERROR("DBUS response error for State");
352 messages::internalError(asyncResp->res);
353 }
354 return;
Lakshmi Yadlapatic6bb3282023-04-12 16:56:49 -0500355 }
Lakshmi Yadlapatic6bb3282023-04-12 16:56:49 -0500356
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400357 if (!value)
358 {
359 asyncResp->res.jsonValue["Status"]["State"] =
360 resource::State::Absent;
361 }
362 });
Lakshmi Yadlapatic6bb3282023-04-12 16:56:49 -0500363}
364
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600365inline void addPCIeDeviceProperties(
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500366 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
367 const std::string& pcieDeviceId,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600368 const dbus::utility::DBusPropertiesMap& pcieDevProperties)
369{
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600370 const std::string* generationInUse = nullptr;
Konstantin Aladyshev814bf202023-07-04 16:30:10 +0300371 const std::string* generationSupported = nullptr;
Konstantin Aladyshev9bb0a7f2023-07-04 12:59:34 +0300372 const size_t* lanesInUse = nullptr;
Konstantin Aladyshev814bf202023-07-04 16:30:10 +0300373 const size_t* maxLanes = nullptr;
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600374
375 const bool success = sdbusplus::unpackPropertiesNoThrow(
Ed Tanous609ba4c2023-07-11 09:14:24 -0700376 dbus_utils::UnpackErrorPrinter(), pcieDevProperties, "GenerationInUse",
377 generationInUse, "GenerationSupported", generationSupported,
378 "LanesInUse", lanesInUse, "MaxLanes", maxLanes);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600379
380 if (!success)
381 {
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500382 messages::internalError(asyncResp->res);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600383 return;
384 }
385
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600386 if (generationInUse != nullptr)
387 {
388 std::optional<pcie_device::PCIeTypes> redfishGenerationInUse =
Lakshmi Yadlapatic49c3292023-04-19 16:42:35 -0500389 pcie_util::redfishPcieGenerationFromDbus(*generationInUse);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600390
391 if (!redfishGenerationInUse)
392 {
Ed Tanous62598e32023-07-17 17:06:25 -0700393 BMCWEB_LOG_WARNING("Unknown PCIe Device Generation: {}",
394 *generationInUse);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600395 }
Lakshmi Yadlapaticf3b4842023-06-27 02:36:53 -0500396 else
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600397 {
Lakshmi Yadlapaticf3b4842023-06-27 02:36:53 -0500398 if (*redfishGenerationInUse == pcie_device::PCIeTypes::Invalid)
399 {
Ed Tanous62598e32023-07-17 17:06:25 -0700400 BMCWEB_LOG_ERROR("Invalid PCIe Device Generation: {}",
401 *generationInUse);
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500402 messages::internalError(asyncResp->res);
Lakshmi Yadlapaticf3b4842023-06-27 02:36:53 -0500403 return;
404 }
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500405 asyncResp->res.jsonValue["PCIeInterface"]["PCIeType"] =
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600406 *redfishGenerationInUse;
407 }
408 }
409
Konstantin Aladyshev814bf202023-07-04 16:30:10 +0300410 if (generationSupported != nullptr)
411 {
412 std::optional<pcie_device::PCIeTypes> redfishGenerationSupported =
413 pcie_util::redfishPcieGenerationFromDbus(*generationSupported);
414
415 if (!redfishGenerationSupported)
416 {
Ed Tanous62598e32023-07-17 17:06:25 -0700417 BMCWEB_LOG_WARNING("Unknown PCIe Device Generation: {}",
418 *generationSupported);
Konstantin Aladyshev814bf202023-07-04 16:30:10 +0300419 }
420 else
421 {
422 if (*redfishGenerationSupported == pcie_device::PCIeTypes::Invalid)
423 {
Ed Tanous62598e32023-07-17 17:06:25 -0700424 BMCWEB_LOG_ERROR("Invalid PCIe Device Generation: {}",
425 *generationSupported);
Konstantin Aladyshev814bf202023-07-04 16:30:10 +0300426 messages::internalError(asyncResp->res);
427 return;
428 }
429 asyncResp->res.jsonValue["PCIeInterface"]["MaxPCIeType"] =
430 *redfishGenerationSupported;
431 }
432 }
433
Myung Bae8c1d0542024-03-12 17:50:48 -0500434 if (lanesInUse != nullptr)
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600435 {
Myung Bae8c1d0542024-03-12 17:50:48 -0500436 if (*lanesInUse == std::numeric_limits<size_t>::max())
437 {
438 // The default value of LanesInUse is "maxint", and the field will
439 // be null if it is a default value.
440 asyncResp->res.jsonValue["PCIeInterface"]["LanesInUse"] = nullptr;
441 }
442 else
443 {
444 asyncResp->res.jsonValue["PCIeInterface"]["LanesInUse"] =
445 *lanesInUse;
446 }
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600447 }
Konstantin Aladyshev814bf202023-07-04 16:30:10 +0300448 // The default value of MaxLanes is 0, and the field will be
449 // left as off if it is a default value.
450 if (maxLanes != nullptr && *maxLanes != 0)
451 {
452 asyncResp->res.jsonValue["PCIeInterface"]["MaxLanes"] = *maxLanes;
453 }
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600454
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500455 asyncResp->res.jsonValue["PCIeFunctions"]["@odata.id"] =
456 boost::urls::format(
Ed Tanous253f11b2024-05-16 09:38:31 -0700457 "/redfish/v1/Systems/{}/PCIeDevices/{}/PCIeFunctions",
458 BMCWEB_REDFISH_SYSTEM_URI_NAME, pcieDeviceId);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600459}
460
461inline void getPCIeDeviceProperties(
Ed Tanousac106bf2023-06-07 09:24:59 -0700462 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600463 const std::string& pcieDevicePath, const std::string& service,
464 const std::function<void(
465 const dbus::utility::DBusPropertiesMap& pcieDevProperties)>&& callback)
466{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800467 dbus::utility::getAllProperties(
468 service, pcieDevicePath,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600469 "xyz.openbmc_project.Inventory.Item.PCIeDevice",
Ed Tanousac106bf2023-06-07 09:24:59 -0700470 [asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600471 callback](const boost::system::error_code& ec,
472 const dbus::utility::DBusPropertiesMap& pcieDevProperties) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400473 if (ec)
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600474 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400475 if (ec.value() != EBADR)
476 {
477 BMCWEB_LOG_ERROR("DBUS response error for Properties");
478 messages::internalError(asyncResp->res);
479 }
480 return;
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600481 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400482 callback(pcieDevProperties);
483 });
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600484}
485
486inline void addPCIeDeviceCommonProperties(
Ed Tanousac106bf2023-06-07 09:24:59 -0700487 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600488 const std::string& pcieDeviceId)
489{
Ed Tanousac106bf2023-06-07 09:24:59 -0700490 asyncResp->res.addHeader(
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600491 boost::beast::http::field::link,
492 "</redfish/v1/JsonSchemas/PCIeDevice/PCIeDevice.json>; rel=describedby");
Ed Tanousac106bf2023-06-07 09:24:59 -0700493 asyncResp->res.jsonValue["@odata.type"] = "#PCIeDevice.v1_9_0.PCIeDevice";
Ed Tanous253f11b2024-05-16 09:38:31 -0700494 asyncResp->res.jsonValue["@odata.id"] =
495 boost::urls::format("/redfish/v1/Systems/{}/PCIeDevices/{}",
496 BMCWEB_REDFISH_SYSTEM_URI_NAME, pcieDeviceId);
Ed Tanousac106bf2023-06-07 09:24:59 -0700497 asyncResp->res.jsonValue["Name"] = "PCIe Device";
498 asyncResp->res.jsonValue["Id"] = pcieDeviceId;
Ed Tanous539d8c62024-06-19 14:38:27 -0700499 asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled;
500 asyncResp->res.jsonValue["Status"]["Health"] = resource::Health::OK;
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600501}
502
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500503inline void afterGetValidPcieDevicePath(
504 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
505 const std::string& pcieDeviceId, const std::string& pcieDevicePath,
506 const std::string& service)
507{
508 addPCIeDeviceCommonProperties(asyncResp, pcieDeviceId);
Myung Baef7e62c12025-09-07 14:02:08 -0500509 asset_utils::getAssetInfo(asyncResp, service, pcieDevicePath,
510 ""_json_pointer, true);
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500511 getPCIeDeviceState(asyncResp, pcieDevicePath, service);
512 getPCIeDeviceHealth(asyncResp, pcieDevicePath, service);
513 getPCIeDeviceProperties(
514 asyncResp, pcieDevicePath, service,
515 std::bind_front(addPCIeDeviceProperties, asyncResp, pcieDeviceId));
516 getPCIeDeviceSlotPath(
517 pcieDevicePath, asyncResp,
518 std::bind_front(afterGetPCIeDeviceSlotPath, asyncResp));
519}
520
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400521inline void handlePCIeDeviceGet(
522 App& app, const crow::Request& req,
523 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
524 const std::string& systemName, const std::string& pcieDeviceId)
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600525{
Ed Tanousac106bf2023-06-07 09:24:59 -0700526 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600527 {
528 return;
529 }
Ed Tanous25b54db2024-04-17 15:40:31 -0700530 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800531 {
532 // Option currently returns no systems. TBD
533 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
534 systemName);
535 return;
536 }
Ed Tanous253f11b2024-05-16 09:38:31 -0700537 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600538 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700539 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
540 systemName);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600541 return;
542 }
543
544 getValidPCIeDevicePath(
Ed Tanousac106bf2023-06-07 09:24:59 -0700545 pcieDeviceId, asyncResp,
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500546 std::bind_front(afterGetValidPcieDevicePath, asyncResp, pcieDeviceId));
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600547}
548
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700549inline void requestRoutesSystemPCIeDevice(App& app)
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -0800550{
Ed Tanous22d268c2022-05-19 09:39:07 -0700551 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/PCIeDevices/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700552 .privileges(redfish::privileges::getPCIeDevice)
Ed Tanous002d39b2022-05-31 08:59:27 -0700553 .methods(boost::beast::http::verb::get)(
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600554 std::bind_front(handlePCIeDeviceGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700555}
556
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600557inline void addPCIeFunctionList(
558 crow::Response& res, const std::string& pcieDeviceId,
559 const dbus::utility::DBusPropertiesMap& pcieDevProperties)
560{
561 nlohmann::json& pcieFunctionList = res.jsonValue["Members"];
562 pcieFunctionList = nlohmann::json::array();
563 static constexpr const int maxPciFunctionNum = 8;
564
565 for (int functionNum = 0; functionNum < maxPciFunctionNum; functionNum++)
566 {
567 // Check if this function exists by
568 // looking for a device ID
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400569 std::string devIDProperty =
570 "Function" + std::to_string(functionNum) + "DeviceId";
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600571 const std::string* property = nullptr;
572 for (const auto& propEntry : pcieDevProperties)
573 {
574 if (propEntry.first == devIDProperty)
575 {
576 property = std::get_if<std::string>(&propEntry.second);
577 break;
578 }
579 }
580 if (property == nullptr || property->empty())
581 {
582 continue;
583 }
584
585 nlohmann::json::object_t pcieFunction;
Ed Tanousef4c65b2023-04-24 15:28:50 -0700586 pcieFunction["@odata.id"] = boost::urls::format(
Ed Tanous253f11b2024-05-16 09:38:31 -0700587 "/redfish/v1/Systems/{}/PCIeDevices/{}/PCIeFunctions/{}",
588 BMCWEB_REDFISH_SYSTEM_URI_NAME, pcieDeviceId,
589 std::to_string(functionNum));
Patrick Williamsb2ba3072023-05-12 10:27:39 -0500590 pcieFunctionList.emplace_back(std::move(pcieFunction));
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600591 }
592 res.jsonValue["PCIeFunctions@odata.count"] = pcieFunctionList.size();
593}
594
595inline void handlePCIeFunctionCollectionGet(
596 App& app, const crow::Request& req,
Ed Tanousac106bf2023-06-07 09:24:59 -0700597 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800598 const std::string& systemName, const std::string& pcieDeviceId)
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600599{
Ed Tanousac106bf2023-06-07 09:24:59 -0700600 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600601 {
602 return;
603 }
Ed Tanous25b54db2024-04-17 15:40:31 -0700604 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800605 {
606 // Option currently returns no systems. TBD
607 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
608 systemName);
609 return;
610 }
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600611
612 getValidPCIeDevicePath(
Ed Tanousac106bf2023-06-07 09:24:59 -0700613 pcieDeviceId, asyncResp,
614 [asyncResp, pcieDeviceId](const std::string& pcieDevicePath,
615 const std::string& service) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400616 asyncResp->res.addHeader(
617 boost::beast::http::field::link,
618 "</redfish/v1/JsonSchemas/PCIeFunctionCollection/PCIeFunctionCollection.json>; rel=describedby");
619 asyncResp->res.jsonValue["@odata.type"] =
620 "#PCIeFunctionCollection.PCIeFunctionCollection";
621 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
622 "/redfish/v1/Systems/{}/PCIeDevices/{}/PCIeFunctions",
623 BMCWEB_REDFISH_SYSTEM_URI_NAME, pcieDeviceId);
624 asyncResp->res.jsonValue["Name"] = "PCIe Function Collection";
625 asyncResp->res.jsonValue["Description"] =
626 "Collection of PCIe Functions for PCIe Device " + pcieDeviceId;
627 getPCIeDeviceProperties(
628 asyncResp, pcieDevicePath, service,
629 [asyncResp, pcieDeviceId](
630 const dbus::utility::DBusPropertiesMap& pcieDevProperties) {
631 addPCIeFunctionList(asyncResp->res, pcieDeviceId,
632 pcieDevProperties);
633 });
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600634 });
635}
636
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700637inline void requestRoutesSystemPCIeFunctionCollection(App& app)
638{
639 /**
640 * Functions triggers appropriate requests on DBus
641 */
642 BMCWEB_ROUTE(app,
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800643 "/redfish/v1/Systems/<str>/PCIeDevices/<str>/PCIeFunctions/")
Ed Tanoused398212021-06-09 17:05:54 -0700644 .privileges(redfish::privileges::getPCIeFunctionCollection)
Ed Tanous002d39b2022-05-31 08:59:27 -0700645 .methods(boost::beast::http::verb::get)(
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600646 std::bind_front(handlePCIeFunctionCollectionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700647}
648
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600649inline void addPCIeFunctionProperties(
Ed Tanouse14742c2023-05-31 10:27:49 -0700650 crow::Response& resp, uint64_t pcieFunctionId,
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600651 const dbus::utility::DBusPropertiesMap& pcieDevProperties)
652{
Ed Tanouse14742c2023-05-31 10:27:49 -0700653 std::string functionName = "Function" + std::to_string(pcieFunctionId);
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600654 for (const auto& property : pcieDevProperties)
655 {
656 const std::string* strProperty =
657 std::get_if<std::string>(&property.second);
Ed Tanousdc8cfa62024-04-07 13:37:25 -0700658 if (strProperty == nullptr)
659 {
Ed Tanousdc8cfa62024-04-07 13:37:25 -0700660 continue;
661 }
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600662 if (property.first == functionName + "DeviceId")
663 {
664 resp.jsonValue["DeviceId"] = *strProperty;
665 }
666 if (property.first == functionName + "VendorId")
667 {
668 resp.jsonValue["VendorId"] = *strProperty;
669 }
670 // TODO: FunctionType and DeviceClass are Redfish enums. The D-Bus
671 // property strings should be mapped correctly to ensure these
672 // strings are Redfish enum values. For now just check for empty.
673 if (property.first == functionName + "FunctionType")
674 {
675 if (!strProperty->empty())
676 {
677 resp.jsonValue["FunctionType"] = *strProperty;
678 }
679 }
680 if (property.first == functionName + "DeviceClass")
681 {
682 if (!strProperty->empty())
683 {
684 resp.jsonValue["DeviceClass"] = *strProperty;
685 }
686 }
687 if (property.first == functionName + "ClassCode")
688 {
689 resp.jsonValue["ClassCode"] = *strProperty;
690 }
691 if (property.first == functionName + "RevisionId")
692 {
693 resp.jsonValue["RevisionId"] = *strProperty;
694 }
695 if (property.first == functionName + "SubsystemId")
696 {
697 resp.jsonValue["SubsystemId"] = *strProperty;
698 }
699 if (property.first == functionName + "SubsystemVendorId")
700 {
701 resp.jsonValue["SubsystemVendorId"] = *strProperty;
702 }
703 }
704}
705
706inline void addPCIeFunctionCommonProperties(crow::Response& resp,
707 const std::string& pcieDeviceId,
Ed Tanouse14742c2023-05-31 10:27:49 -0700708 uint64_t pcieFunctionId)
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600709{
710 resp.addHeader(
711 boost::beast::http::field::link,
712 "</redfish/v1/JsonSchemas/PCIeFunction/PCIeFunction.json>; rel=describedby");
713 resp.jsonValue["@odata.type"] = "#PCIeFunction.v1_2_3.PCIeFunction";
Ed Tanousef4c65b2023-04-24 15:28:50 -0700714 resp.jsonValue["@odata.id"] = boost::urls::format(
Ed Tanous253f11b2024-05-16 09:38:31 -0700715 "/redfish/v1/Systems/{}/PCIeDevices/{}/PCIeFunctions/{}",
716 BMCWEB_REDFISH_SYSTEM_URI_NAME, pcieDeviceId,
717 std::to_string(pcieFunctionId));
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600718 resp.jsonValue["Name"] = "PCIe Function";
Ed Tanouse14742c2023-05-31 10:27:49 -0700719 resp.jsonValue["Id"] = std::to_string(pcieFunctionId);
720 resp.jsonValue["FunctionId"] = pcieFunctionId;
Ed Tanous253f11b2024-05-16 09:38:31 -0700721 resp.jsonValue["Links"]["PCIeDevice"]["@odata.id"] =
722 boost::urls::format("/redfish/v1/Systems/{}/PCIeDevices/{}",
723 BMCWEB_REDFISH_SYSTEM_URI_NAME, pcieDeviceId);
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600724}
725
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400726inline void handlePCIeFunctionGet(
727 App& app, const crow::Request& req,
728 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
729 const std::string& systemName, const std::string& pcieDeviceId,
730 const std::string& pcieFunctionIdStr)
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600731{
Ed Tanousac106bf2023-06-07 09:24:59 -0700732 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600733 {
734 return;
735 }
Ed Tanous25b54db2024-04-17 15:40:31 -0700736 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800737 {
738 // Option currently returns no systems. TBD
739 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
740 systemName);
741 return;
742 }
Ed Tanous253f11b2024-05-16 09:38:31 -0700743 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800744 {
745 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
746 systemName);
747 return;
748 }
Ed Tanousdc8cfa62024-04-07 13:37:25 -0700749 std::string_view pcieFunctionIdView = pcieFunctionIdStr;
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800750
Ed Tanouse14742c2023-05-31 10:27:49 -0700751 uint64_t pcieFunctionId = 0;
752 std::from_chars_result result = std::from_chars(
Ed Tanousdc8cfa62024-04-07 13:37:25 -0700753 pcieFunctionIdView.begin(), pcieFunctionIdView.end(), pcieFunctionId);
754 if (result.ec != std::errc{} || result.ptr != pcieFunctionIdView.end())
Ed Tanouse14742c2023-05-31 10:27:49 -0700755 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700756 messages::resourceNotFound(asyncResp->res, "PCIeFunction",
Ed Tanouse14742c2023-05-31 10:27:49 -0700757 pcieFunctionIdStr);
758 return;
759 }
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600760
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400761 getValidPCIeDevicePath(
762 pcieDeviceId, asyncResp,
763 [asyncResp, pcieDeviceId, pcieFunctionId](
764 const std::string& pcieDevicePath, const std::string& service) {
765 getPCIeDeviceProperties(
766 asyncResp, pcieDevicePath, service,
767 [asyncResp, pcieDeviceId, pcieFunctionId](
768 const dbus::utility::DBusPropertiesMap& pcieDevProperties) {
769 addPCIeFunctionCommonProperties(
770 asyncResp->res, pcieDeviceId, pcieFunctionId);
771 addPCIeFunctionProperties(asyncResp->res, pcieFunctionId,
772 pcieDevProperties);
773 });
Patrick Williams5a39f772023-10-20 11:20:21 -0500774 });
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600775}
776
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700777inline void requestRoutesSystemPCIeFunction(App& app)
778{
779 BMCWEB_ROUTE(
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800780 app, "/redfish/v1/Systems/<str>/PCIeDevices/<str>/PCIeFunctions/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700781 .privileges(redfish::privileges::getPCIeFunction)
Ed Tanous002d39b2022-05-31 08:59:27 -0700782 .methods(boost::beast::http::verb::get)(
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600783 std::bind_front(handlePCIeFunctionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700784}
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -0800785
786} // namespace redfish