blob: 75a20b3fc590f0c7df6f38af59f6e900b2bbe421 [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 Tanous3ccb3ad2023-01-13 17:40:03 -08007#include "app.hpp"
George Liu7a1dbc42022-12-07 16:03:22 +08008#include "dbus_utility.hpp"
Ed Tanous539d8c62024-06-19 14:38:27 -07009#include "generated/enums/resource.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080010#include "query.hpp"
11#include "registries/privilege_registry.hpp"
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -060012#include "utils/collection.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080013#include "utils/dbus_utils.hpp"
Lakshmi Yadlapatic49c3292023-04-19 16:42:35 -050014#include "utils/pcie_util.hpp"
Ed Tanous0ec8b832022-03-14 14:56:47 -070015
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -080016#include <boost/system/linux_error.hpp>
Ed Tanousef4c65b2023-04-24 15:28:50 -070017#include <boost/url/format.hpp>
Krzysztof Grobelnyd1bde9e2022-09-07 10:40:51 +020018#include <sdbusplus/asio/property.hpp>
19#include <sdbusplus/unpack_properties.hpp>
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -080020
Myung Bae8c1d0542024-03-12 17:50:48 -050021#include <limits>
22
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -080023namespace redfish
24{
25
Patrick Williams89492a12023-05-10 07:51:34 -050026static constexpr const char* inventoryPath = "/xyz/openbmc_project/inventory";
Lakshmi Yadlapati94c3a102023-04-05 18:11:22 -050027static constexpr std::array<std::string_view, 1> pcieDeviceInterface = {
28 "xyz.openbmc_project.Inventory.Item.PCIeDevice"};
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -050029static constexpr std::array<std::string_view, 1> pcieSlotInterface = {
30 "xyz.openbmc_project.Inventory.Item.PCIeSlot"};
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -080031
Ed Tanous4ff0f1f2024-09-04 17:27:37 -070032inline void handlePCIeDevicePath(
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060033 const std::string& pcieDeviceId,
Ed Tanousac106bf2023-06-07 09:24:59 -070034 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060035 const dbus::utility::MapperGetSubTreePathsResponse& pcieDevicePaths,
36 const std::function<void(const std::string& pcieDevicePath,
37 const std::string& service)>& callback)
38
39{
40 for (const std::string& pcieDevicePath : pcieDevicePaths)
41 {
42 std::string pciecDeviceName =
43 sdbusplus::message::object_path(pcieDevicePath).filename();
44 if (pciecDeviceName.empty() || pciecDeviceName != pcieDeviceId)
45 {
46 continue;
47 }
48
49 dbus::utility::getDbusObject(
Konstantin Aladyshev3a58c5a2024-08-05 12:57:13 +030050 pcieDevicePath, pcieDeviceInterface,
Ed Tanousac106bf2023-06-07 09:24:59 -070051 [pcieDevicePath, asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060052 callback](const boost::system::error_code& ec,
53 const dbus::utility::MapperGetObject& object) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -040054 if (ec || object.empty())
55 {
56 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
57 messages::internalError(asyncResp->res);
58 return;
59 }
60 callback(pcieDevicePath, object.begin()->first);
61 });
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060062 return;
63 }
64
Ed Tanous62598e32023-07-17 17:06:25 -070065 BMCWEB_LOG_WARNING("PCIe Device not found");
Ed Tanousac106bf2023-06-07 09:24:59 -070066 messages::resourceNotFound(asyncResp->res, "PCIeDevice", pcieDeviceId);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060067}
68
Ed Tanous4ff0f1f2024-09-04 17:27:37 -070069inline void getValidPCIeDevicePath(
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060070 const std::string& pcieDeviceId,
Ed Tanousac106bf2023-06-07 09:24:59 -070071 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060072 const std::function<void(const std::string& pcieDevicePath,
73 const std::string& service)>& callback)
74{
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060075 dbus::utility::getSubTreePaths(
Lakshmi Yadlapati94c3a102023-04-05 18:11:22 -050076 inventoryPath, 0, pcieDeviceInterface,
Ed Tanousac106bf2023-06-07 09:24:59 -070077 [pcieDeviceId, asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060078 callback](const boost::system::error_code& ec,
79 const dbus::utility::MapperGetSubTreePathsResponse&
80 pcieDevicePaths) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -040081 if (ec)
82 {
83 BMCWEB_LOG_ERROR("D-Bus response error on GetSubTree {}", ec);
84 messages::internalError(asyncResp->res);
85 return;
86 }
87 handlePCIeDevicePath(pcieDeviceId, asyncResp, pcieDevicePaths,
88 callback);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060089 return;
Patrick Williamsbd79bce2024-08-16 15:22:20 -040090 });
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060091}
92
Ed Tanous4ff0f1f2024-09-04 17:27:37 -070093inline void handlePCIeDeviceCollectionGet(
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -060094 crow::App& app, const crow::Request& req,
Ed Tanousac106bf2023-06-07 09:24:59 -070095 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -060096 const std::string& systemName)
97{
Ed Tanousac106bf2023-06-07 09:24:59 -070098 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -060099 {
100 return;
101 }
Ed Tanous25b54db2024-04-17 15:40:31 -0700102 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800103 {
104 // Option currently returns no systems. TBD
105 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
106 systemName);
107 return;
108 }
Ed Tanous253f11b2024-05-16 09:38:31 -0700109 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600110 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700111 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
112 systemName);
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600113 return;
114 }
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600115
Ed Tanousac106bf2023-06-07 09:24:59 -0700116 asyncResp->res.addHeader(boost::beast::http::field::link,
117 "</redfish/v1/JsonSchemas/PCIeDeviceCollection/"
118 "PCIeDeviceCollection.json>; rel=describedby");
119 asyncResp->res.jsonValue["@odata.type"] =
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600120 "#PCIeDeviceCollection.PCIeDeviceCollection";
Ed Tanous253f11b2024-05-16 09:38:31 -0700121 asyncResp->res.jsonValue["@odata.id"] = std::format(
122 "/redfish/v1/Systems/{}/PCIeDevices", BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanousac106bf2023-06-07 09:24:59 -0700123 asyncResp->res.jsonValue["Name"] = "PCIe Device Collection";
124 asyncResp->res.jsonValue["Description"] = "Collection of PCIe Devices";
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600125
Lakshmi Yadlapati70c4d542023-06-08 04:37:18 -0500126 pcie_util::getPCIeDeviceList(asyncResp,
127 nlohmann::json::json_pointer("/Members"));
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600128}
129
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700130inline void requestRoutesSystemPCIeDeviceCollection(App& app)
Jason M. Billsadbe1922019-10-14 15:44:35 -0700131{
Jason M. Billsadbe1922019-10-14 15:44:35 -0700132 /**
133 * Functions triggers appropriate requests on DBus
134 */
Ed Tanous22d268c2022-05-19 09:39:07 -0700135 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/PCIeDevices/")
Ed Tanoused398212021-06-09 17:05:54 -0700136 .privileges(redfish::privileges::getPCIeDeviceCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700137 .methods(boost::beast::http::verb::get)(
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600138 std::bind_front(handlePCIeDeviceCollectionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700139}
140
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500141inline void addPCIeSlotProperties(
142 crow::Response& res, const boost::system::error_code& ec,
143 const dbus::utility::DBusPropertiesMap& pcieSlotProperties)
144{
145 if (ec)
146 {
Ed Tanous62598e32023-07-17 17:06:25 -0700147 BMCWEB_LOG_ERROR("DBUS response error for getAllProperties{}",
148 ec.value());
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500149 messages::internalError(res);
150 return;
151 }
152 std::string generation;
153 size_t lanes = 0;
154 std::string slotType;
155
156 bool success = sdbusplus::unpackPropertiesNoThrow(
157 dbus_utils::UnpackErrorPrinter(), pcieSlotProperties, "Generation",
158 generation, "Lanes", lanes, "SlotType", slotType);
159
160 if (!success)
161 {
162 messages::internalError(res);
163 return;
164 }
165
166 std::optional<pcie_device::PCIeTypes> pcieType =
167 pcie_util::redfishPcieGenerationFromDbus(generation);
168 if (!pcieType)
169 {
Ed Tanous62598e32023-07-17 17:06:25 -0700170 BMCWEB_LOG_WARNING("Unknown PCIeType: {}", generation);
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500171 }
172 else
173 {
174 if (*pcieType == pcie_device::PCIeTypes::Invalid)
175 {
Ed Tanous62598e32023-07-17 17:06:25 -0700176 BMCWEB_LOG_ERROR("Invalid PCIeType: {}", generation);
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500177 messages::internalError(res);
178 return;
179 }
180 res.jsonValue["Slot"]["PCIeType"] = *pcieType;
181 }
182
Konstantin Aladyshev82f80322023-07-10 15:00:38 +0300183 if (lanes != 0)
184 {
185 res.jsonValue["Slot"]["Lanes"] = lanes;
186 }
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500187
188 std::optional<pcie_slots::SlotTypes> redfishSlotType =
189 pcie_util::dbusSlotTypeToRf(slotType);
190 if (!redfishSlotType)
191 {
Ed Tanous62598e32023-07-17 17:06:25 -0700192 BMCWEB_LOG_WARNING("Unknown PCIeSlot Type: {}", slotType);
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500193 }
194 else
195 {
196 if (*redfishSlotType == pcie_slots::SlotTypes::Invalid)
197 {
Ed Tanous62598e32023-07-17 17:06:25 -0700198 BMCWEB_LOG_ERROR("Invalid PCIeSlot type: {}", slotType);
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500199 messages::internalError(res);
200 return;
201 }
202 res.jsonValue["Slot"]["SlotType"] = *redfishSlotType;
203 }
204}
205
206inline void getPCIeDeviceSlotPath(
207 const std::string& pcieDevicePath,
208 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
209 std::function<void(const std::string& pcieDeviceSlot)>&& callback)
210{
211 std::string associationPath = pcieDevicePath + "/contained_by";
212 dbus::utility::getAssociatedSubTreePaths(
213 associationPath, sdbusplus::message::object_path(inventoryPath), 0,
214 pcieSlotInterface,
Ed Tanous8cb2c022024-03-27 16:31:46 -0700215 [callback = std::move(callback), asyncResp, pcieDevicePath](
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500216 const boost::system::error_code& ec,
217 const dbus::utility::MapperGetSubTreePathsResponse& endpoints) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400218 if (ec)
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500219 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400220 if (ec.value() == EBADR)
221 {
222 // Missing association is not an error
223 return;
224 }
225 BMCWEB_LOG_ERROR(
226 "DBUS response error for getAssociatedSubTreePaths {}",
227 ec.value());
228 messages::internalError(asyncResp->res);
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500229 return;
230 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400231 if (endpoints.size() > 1)
232 {
233 BMCWEB_LOG_ERROR(
Gunnar Millsa6bd55b2025-01-13 11:24:00 -0600234 "PCIeDevice {} is associated with more than one PCIeSlot: {}",
235 pcieDevicePath, endpoints.size());
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400236 messages::internalError(asyncResp->res);
237 return;
238 }
239 if (endpoints.empty())
240 {
241 // If the device doesn't have an association, return without
242 // PCIe Slot properties
243 BMCWEB_LOG_DEBUG("PCIeDevice is not associated with PCIeSlot");
244 return;
245 }
246 callback(endpoints[0]);
247 });
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500248}
249
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400250inline void afterGetDbusObject(
251 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
252 const std::string& pcieDeviceSlot, const boost::system::error_code& ec,
253 const dbus::utility::MapperGetObject& object)
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500254{
255 if (ec || object.empty())
256 {
Ed Tanous62598e32023-07-17 17:06:25 -0700257 BMCWEB_LOG_ERROR("DBUS response error for getDbusObject {}",
258 ec.value());
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500259 messages::internalError(asyncResp->res);
260 return;
261 }
Ed Tanousdeae6a72024-11-11 21:58:57 -0800262 dbus::utility::getAllProperties(
263 object.begin()->first, pcieDeviceSlot,
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500264 "xyz.openbmc_project.Inventory.Item.PCIeSlot",
265 [asyncResp](
266 const boost::system::error_code& ec2,
267 const dbus::utility::DBusPropertiesMap& pcieSlotProperties) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400268 addPCIeSlotProperties(asyncResp->res, ec2, pcieSlotProperties);
269 });
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500270}
271
272inline void afterGetPCIeDeviceSlotPath(
273 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
274 const std::string& pcieDeviceSlot)
275{
276 dbus::utility::getDbusObject(
277 pcieDeviceSlot, pcieSlotInterface,
278 [asyncResp,
279 pcieDeviceSlot](const boost::system::error_code& ec,
280 const dbus::utility::MapperGetObject& object) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400281 afterGetDbusObject(asyncResp, pcieDeviceSlot, ec, object);
282 });
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500283}
284
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400285inline void getPCIeDeviceHealth(
286 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
287 const std::string& pcieDevicePath, const std::string& service)
Lakshmi Yadlapatie164f1b2023-04-12 17:01:34 -0500288{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800289 dbus::utility::getProperty<bool>(
290 service, pcieDevicePath,
Lakshmi Yadlapatie164f1b2023-04-12 17:01:34 -0500291 "xyz.openbmc_project.State.Decorator.OperationalStatus", "Functional",
292 [asyncResp](const boost::system::error_code& ec, const bool value) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400293 if (ec)
Lakshmi Yadlapatie164f1b2023-04-12 17:01:34 -0500294 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400295 if (ec.value() != EBADR)
296 {
297 BMCWEB_LOG_ERROR("DBUS response error for Health {}",
298 ec.value());
299 messages::internalError(asyncResp->res);
300 }
301 return;
Lakshmi Yadlapatie164f1b2023-04-12 17:01:34 -0500302 }
Lakshmi Yadlapatie164f1b2023-04-12 17:01:34 -0500303
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400304 if (!value)
305 {
306 asyncResp->res.jsonValue["Status"]["Health"] =
307 resource::Health::Critical;
308 }
309 });
Lakshmi Yadlapatie164f1b2023-04-12 17:01:34 -0500310}
311
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400312inline void getPCIeDeviceState(
313 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
314 const std::string& pcieDevicePath, const std::string& service)
Lakshmi Yadlapatic6bb3282023-04-12 16:56:49 -0500315{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800316 dbus::utility::getProperty<bool>(
317 service, pcieDevicePath, "xyz.openbmc_project.Inventory.Item",
318 "Present",
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500319 [asyncResp](const boost::system::error_code& ec, bool value) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400320 if (ec)
Lakshmi Yadlapatic6bb3282023-04-12 16:56:49 -0500321 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400322 if (ec.value() != EBADR)
323 {
324 BMCWEB_LOG_ERROR("DBUS response error for State");
325 messages::internalError(asyncResp->res);
326 }
327 return;
Lakshmi Yadlapatic6bb3282023-04-12 16:56:49 -0500328 }
Lakshmi Yadlapatic6bb3282023-04-12 16:56:49 -0500329
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400330 if (!value)
331 {
332 asyncResp->res.jsonValue["Status"]["State"] =
333 resource::State::Absent;
334 }
335 });
Lakshmi Yadlapatic6bb3282023-04-12 16:56:49 -0500336}
337
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400338inline void getPCIeDeviceAsset(
339 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
340 const std::string& pcieDevicePath, const std::string& service)
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600341{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800342 dbus::utility::getAllProperties(
343 service, pcieDevicePath,
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600344 "xyz.openbmc_project.Inventory.Decorator.Asset",
Ed Tanousac106bf2023-06-07 09:24:59 -0700345 [pcieDevicePath, asyncResp{asyncResp}](
346 const boost::system::error_code& ec,
347 const dbus::utility::DBusPropertiesMap& assetList) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400348 if (ec)
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600349 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400350 if (ec.value() != EBADR)
351 {
352 BMCWEB_LOG_ERROR("DBUS response error for Properties{}",
353 ec.value());
354 messages::internalError(asyncResp->res);
355 }
356 return;
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600357 }
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600358
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400359 const std::string* manufacturer = nullptr;
360 const std::string* model = nullptr;
361 const std::string* partNumber = nullptr;
362 const std::string* serialNumber = nullptr;
363 const std::string* sparePartNumber = nullptr;
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600364
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400365 const bool success = sdbusplus::unpackPropertiesNoThrow(
366 dbus_utils::UnpackErrorPrinter(), assetList, "Manufacturer",
367 manufacturer, "Model", model, "PartNumber", partNumber,
368 "SerialNumber", serialNumber, "SparePartNumber",
369 sparePartNumber);
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600370
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400371 if (!success)
372 {
373 messages::internalError(asyncResp->res);
374 return;
375 }
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600376
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400377 if (manufacturer != nullptr)
378 {
379 asyncResp->res.jsonValue["Manufacturer"] = *manufacturer;
380 }
381 if (model != nullptr)
382 {
383 asyncResp->res.jsonValue["Model"] = *model;
384 }
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600385
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400386 if (partNumber != nullptr)
387 {
388 asyncResp->res.jsonValue["PartNumber"] = *partNumber;
389 }
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600390
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400391 if (serialNumber != nullptr)
392 {
393 asyncResp->res.jsonValue["SerialNumber"] = *serialNumber;
394 }
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600395
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400396 if (sparePartNumber != nullptr && !sparePartNumber->empty())
397 {
398 asyncResp->res.jsonValue["SparePartNumber"] = *sparePartNumber;
399 }
400 });
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600401}
402
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600403inline void addPCIeDeviceProperties(
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500404 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
405 const std::string& pcieDeviceId,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600406 const dbus::utility::DBusPropertiesMap& pcieDevProperties)
407{
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600408 const std::string* generationInUse = nullptr;
Konstantin Aladyshev814bf202023-07-04 16:30:10 +0300409 const std::string* generationSupported = nullptr;
Konstantin Aladyshev9bb0a7f2023-07-04 12:59:34 +0300410 const size_t* lanesInUse = nullptr;
Konstantin Aladyshev814bf202023-07-04 16:30:10 +0300411 const size_t* maxLanes = nullptr;
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600412
413 const bool success = sdbusplus::unpackPropertiesNoThrow(
Ed Tanous609ba4c2023-07-11 09:14:24 -0700414 dbus_utils::UnpackErrorPrinter(), pcieDevProperties, "GenerationInUse",
415 generationInUse, "GenerationSupported", generationSupported,
416 "LanesInUse", lanesInUse, "MaxLanes", maxLanes);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600417
418 if (!success)
419 {
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500420 messages::internalError(asyncResp->res);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600421 return;
422 }
423
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600424 if (generationInUse != nullptr)
425 {
426 std::optional<pcie_device::PCIeTypes> redfishGenerationInUse =
Lakshmi Yadlapatic49c3292023-04-19 16:42:35 -0500427 pcie_util::redfishPcieGenerationFromDbus(*generationInUse);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600428
429 if (!redfishGenerationInUse)
430 {
Ed Tanous62598e32023-07-17 17:06:25 -0700431 BMCWEB_LOG_WARNING("Unknown PCIe Device Generation: {}",
432 *generationInUse);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600433 }
Lakshmi Yadlapaticf3b4842023-06-27 02:36:53 -0500434 else
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600435 {
Lakshmi Yadlapaticf3b4842023-06-27 02:36:53 -0500436 if (*redfishGenerationInUse == pcie_device::PCIeTypes::Invalid)
437 {
Ed Tanous62598e32023-07-17 17:06:25 -0700438 BMCWEB_LOG_ERROR("Invalid PCIe Device Generation: {}",
439 *generationInUse);
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500440 messages::internalError(asyncResp->res);
Lakshmi Yadlapaticf3b4842023-06-27 02:36:53 -0500441 return;
442 }
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500443 asyncResp->res.jsonValue["PCIeInterface"]["PCIeType"] =
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600444 *redfishGenerationInUse;
445 }
446 }
447
Konstantin Aladyshev814bf202023-07-04 16:30:10 +0300448 if (generationSupported != nullptr)
449 {
450 std::optional<pcie_device::PCIeTypes> redfishGenerationSupported =
451 pcie_util::redfishPcieGenerationFromDbus(*generationSupported);
452
453 if (!redfishGenerationSupported)
454 {
Ed Tanous62598e32023-07-17 17:06:25 -0700455 BMCWEB_LOG_WARNING("Unknown PCIe Device Generation: {}",
456 *generationSupported);
Konstantin Aladyshev814bf202023-07-04 16:30:10 +0300457 }
458 else
459 {
460 if (*redfishGenerationSupported == pcie_device::PCIeTypes::Invalid)
461 {
Ed Tanous62598e32023-07-17 17:06:25 -0700462 BMCWEB_LOG_ERROR("Invalid PCIe Device Generation: {}",
463 *generationSupported);
Konstantin Aladyshev814bf202023-07-04 16:30:10 +0300464 messages::internalError(asyncResp->res);
465 return;
466 }
467 asyncResp->res.jsonValue["PCIeInterface"]["MaxPCIeType"] =
468 *redfishGenerationSupported;
469 }
470 }
471
Myung Bae8c1d0542024-03-12 17:50:48 -0500472 if (lanesInUse != nullptr)
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600473 {
Myung Bae8c1d0542024-03-12 17:50:48 -0500474 if (*lanesInUse == std::numeric_limits<size_t>::max())
475 {
476 // The default value of LanesInUse is "maxint", and the field will
477 // be null if it is a default value.
478 asyncResp->res.jsonValue["PCIeInterface"]["LanesInUse"] = nullptr;
479 }
480 else
481 {
482 asyncResp->res.jsonValue["PCIeInterface"]["LanesInUse"] =
483 *lanesInUse;
484 }
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600485 }
Konstantin Aladyshev814bf202023-07-04 16:30:10 +0300486 // The default value of MaxLanes is 0, and the field will be
487 // left as off if it is a default value.
488 if (maxLanes != nullptr && *maxLanes != 0)
489 {
490 asyncResp->res.jsonValue["PCIeInterface"]["MaxLanes"] = *maxLanes;
491 }
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600492
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500493 asyncResp->res.jsonValue["PCIeFunctions"]["@odata.id"] =
494 boost::urls::format(
Ed Tanous253f11b2024-05-16 09:38:31 -0700495 "/redfish/v1/Systems/{}/PCIeDevices/{}/PCIeFunctions",
496 BMCWEB_REDFISH_SYSTEM_URI_NAME, pcieDeviceId);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600497}
498
499inline void getPCIeDeviceProperties(
Ed Tanousac106bf2023-06-07 09:24:59 -0700500 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600501 const std::string& pcieDevicePath, const std::string& service,
502 const std::function<void(
503 const dbus::utility::DBusPropertiesMap& pcieDevProperties)>&& callback)
504{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800505 dbus::utility::getAllProperties(
506 service, pcieDevicePath,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600507 "xyz.openbmc_project.Inventory.Item.PCIeDevice",
Ed Tanousac106bf2023-06-07 09:24:59 -0700508 [asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600509 callback](const boost::system::error_code& ec,
510 const dbus::utility::DBusPropertiesMap& pcieDevProperties) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400511 if (ec)
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600512 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400513 if (ec.value() != EBADR)
514 {
515 BMCWEB_LOG_ERROR("DBUS response error for Properties");
516 messages::internalError(asyncResp->res);
517 }
518 return;
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600519 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400520 callback(pcieDevProperties);
521 });
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600522}
523
524inline void addPCIeDeviceCommonProperties(
Ed Tanousac106bf2023-06-07 09:24:59 -0700525 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600526 const std::string& pcieDeviceId)
527{
Ed Tanousac106bf2023-06-07 09:24:59 -0700528 asyncResp->res.addHeader(
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600529 boost::beast::http::field::link,
530 "</redfish/v1/JsonSchemas/PCIeDevice/PCIeDevice.json>; rel=describedby");
Ed Tanousac106bf2023-06-07 09:24:59 -0700531 asyncResp->res.jsonValue["@odata.type"] = "#PCIeDevice.v1_9_0.PCIeDevice";
Ed Tanous253f11b2024-05-16 09:38:31 -0700532 asyncResp->res.jsonValue["@odata.id"] =
533 boost::urls::format("/redfish/v1/Systems/{}/PCIeDevices/{}",
534 BMCWEB_REDFISH_SYSTEM_URI_NAME, pcieDeviceId);
Ed Tanousac106bf2023-06-07 09:24:59 -0700535 asyncResp->res.jsonValue["Name"] = "PCIe Device";
536 asyncResp->res.jsonValue["Id"] = pcieDeviceId;
Ed Tanous539d8c62024-06-19 14:38:27 -0700537 asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled;
538 asyncResp->res.jsonValue["Status"]["Health"] = resource::Health::OK;
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600539}
540
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500541inline void afterGetValidPcieDevicePath(
542 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
543 const std::string& pcieDeviceId, const std::string& pcieDevicePath,
544 const std::string& service)
545{
546 addPCIeDeviceCommonProperties(asyncResp, pcieDeviceId);
547 getPCIeDeviceAsset(asyncResp, pcieDevicePath, service);
548 getPCIeDeviceState(asyncResp, pcieDevicePath, service);
549 getPCIeDeviceHealth(asyncResp, pcieDevicePath, service);
550 getPCIeDeviceProperties(
551 asyncResp, pcieDevicePath, service,
552 std::bind_front(addPCIeDeviceProperties, asyncResp, pcieDeviceId));
553 getPCIeDeviceSlotPath(
554 pcieDevicePath, asyncResp,
555 std::bind_front(afterGetPCIeDeviceSlotPath, asyncResp));
556}
557
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400558inline void handlePCIeDeviceGet(
559 App& app, const crow::Request& req,
560 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
561 const std::string& systemName, const std::string& pcieDeviceId)
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600562{
Ed Tanousac106bf2023-06-07 09:24:59 -0700563 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600564 {
565 return;
566 }
Ed Tanous25b54db2024-04-17 15:40:31 -0700567 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800568 {
569 // Option currently returns no systems. TBD
570 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
571 systemName);
572 return;
573 }
Ed Tanous253f11b2024-05-16 09:38:31 -0700574 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600575 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700576 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
577 systemName);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600578 return;
579 }
580
581 getValidPCIeDevicePath(
Ed Tanousac106bf2023-06-07 09:24:59 -0700582 pcieDeviceId, asyncResp,
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500583 std::bind_front(afterGetValidPcieDevicePath, asyncResp, pcieDeviceId));
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600584}
585
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700586inline void requestRoutesSystemPCIeDevice(App& app)
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -0800587{
Ed Tanous22d268c2022-05-19 09:39:07 -0700588 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/PCIeDevices/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700589 .privileges(redfish::privileges::getPCIeDevice)
Ed Tanous002d39b2022-05-31 08:59:27 -0700590 .methods(boost::beast::http::verb::get)(
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600591 std::bind_front(handlePCIeDeviceGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700592}
593
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600594inline void addPCIeFunctionList(
595 crow::Response& res, const std::string& pcieDeviceId,
596 const dbus::utility::DBusPropertiesMap& pcieDevProperties)
597{
598 nlohmann::json& pcieFunctionList = res.jsonValue["Members"];
599 pcieFunctionList = nlohmann::json::array();
600 static constexpr const int maxPciFunctionNum = 8;
601
602 for (int functionNum = 0; functionNum < maxPciFunctionNum; functionNum++)
603 {
604 // Check if this function exists by
605 // looking for a device ID
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400606 std::string devIDProperty =
607 "Function" + std::to_string(functionNum) + "DeviceId";
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600608 const std::string* property = nullptr;
609 for (const auto& propEntry : pcieDevProperties)
610 {
611 if (propEntry.first == devIDProperty)
612 {
613 property = std::get_if<std::string>(&propEntry.second);
614 break;
615 }
616 }
617 if (property == nullptr || property->empty())
618 {
619 continue;
620 }
621
622 nlohmann::json::object_t pcieFunction;
Ed Tanousef4c65b2023-04-24 15:28:50 -0700623 pcieFunction["@odata.id"] = boost::urls::format(
Ed Tanous253f11b2024-05-16 09:38:31 -0700624 "/redfish/v1/Systems/{}/PCIeDevices/{}/PCIeFunctions/{}",
625 BMCWEB_REDFISH_SYSTEM_URI_NAME, pcieDeviceId,
626 std::to_string(functionNum));
Patrick Williamsb2ba3072023-05-12 10:27:39 -0500627 pcieFunctionList.emplace_back(std::move(pcieFunction));
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600628 }
629 res.jsonValue["PCIeFunctions@odata.count"] = pcieFunctionList.size();
630}
631
632inline void handlePCIeFunctionCollectionGet(
633 App& app, const crow::Request& req,
Ed Tanousac106bf2023-06-07 09:24:59 -0700634 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800635 const std::string& systemName, const std::string& pcieDeviceId)
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600636{
Ed Tanousac106bf2023-06-07 09:24:59 -0700637 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600638 {
639 return;
640 }
Ed Tanous25b54db2024-04-17 15:40:31 -0700641 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800642 {
643 // Option currently returns no systems. TBD
644 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
645 systemName);
646 return;
647 }
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600648
649 getValidPCIeDevicePath(
Ed Tanousac106bf2023-06-07 09:24:59 -0700650 pcieDeviceId, asyncResp,
651 [asyncResp, pcieDeviceId](const std::string& pcieDevicePath,
652 const std::string& service) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400653 asyncResp->res.addHeader(
654 boost::beast::http::field::link,
655 "</redfish/v1/JsonSchemas/PCIeFunctionCollection/PCIeFunctionCollection.json>; rel=describedby");
656 asyncResp->res.jsonValue["@odata.type"] =
657 "#PCIeFunctionCollection.PCIeFunctionCollection";
658 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
659 "/redfish/v1/Systems/{}/PCIeDevices/{}/PCIeFunctions",
660 BMCWEB_REDFISH_SYSTEM_URI_NAME, pcieDeviceId);
661 asyncResp->res.jsonValue["Name"] = "PCIe Function Collection";
662 asyncResp->res.jsonValue["Description"] =
663 "Collection of PCIe Functions for PCIe Device " + pcieDeviceId;
664 getPCIeDeviceProperties(
665 asyncResp, pcieDevicePath, service,
666 [asyncResp, pcieDeviceId](
667 const dbus::utility::DBusPropertiesMap& pcieDevProperties) {
668 addPCIeFunctionList(asyncResp->res, pcieDeviceId,
669 pcieDevProperties);
670 });
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600671 });
672}
673
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700674inline void requestRoutesSystemPCIeFunctionCollection(App& app)
675{
676 /**
677 * Functions triggers appropriate requests on DBus
678 */
679 BMCWEB_ROUTE(app,
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800680 "/redfish/v1/Systems/<str>/PCIeDevices/<str>/PCIeFunctions/")
Ed Tanoused398212021-06-09 17:05:54 -0700681 .privileges(redfish::privileges::getPCIeFunctionCollection)
Ed Tanous002d39b2022-05-31 08:59:27 -0700682 .methods(boost::beast::http::verb::get)(
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600683 std::bind_front(handlePCIeFunctionCollectionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700684}
685
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600686inline bool validatePCIeFunctionId(
Myung Baed5e74b82023-05-31 11:28:02 -0500687 uint64_t pcieFunctionId,
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600688 const dbus::utility::DBusPropertiesMap& pcieDevProperties)
689{
Myung Baed5e74b82023-05-31 11:28:02 -0500690 std::string functionName = "Function" + std::to_string(pcieFunctionId);
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600691 std::string devIDProperty = functionName + "DeviceId";
692
693 const std::string* devIdProperty = nullptr;
694 for (const auto& property : pcieDevProperties)
695 {
696 if (property.first == devIDProperty)
697 {
698 devIdProperty = std::get_if<std::string>(&property.second);
699 break;
700 }
701 }
702 return (devIdProperty != nullptr && !devIdProperty->empty());
703}
704
705inline void addPCIeFunctionProperties(
Ed Tanouse14742c2023-05-31 10:27:49 -0700706 crow::Response& resp, uint64_t pcieFunctionId,
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600707 const dbus::utility::DBusPropertiesMap& pcieDevProperties)
708{
Ed Tanouse14742c2023-05-31 10:27:49 -0700709 std::string functionName = "Function" + std::to_string(pcieFunctionId);
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600710 for (const auto& property : pcieDevProperties)
711 {
712 const std::string* strProperty =
713 std::get_if<std::string>(&property.second);
Ed Tanousdc8cfa62024-04-07 13:37:25 -0700714 if (strProperty == nullptr)
715 {
Ed Tanousdc8cfa62024-04-07 13:37:25 -0700716 continue;
717 }
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600718 if (property.first == functionName + "DeviceId")
719 {
720 resp.jsonValue["DeviceId"] = *strProperty;
721 }
722 if (property.first == functionName + "VendorId")
723 {
724 resp.jsonValue["VendorId"] = *strProperty;
725 }
726 // TODO: FunctionType and DeviceClass are Redfish enums. The D-Bus
727 // property strings should be mapped correctly to ensure these
728 // strings are Redfish enum values. For now just check for empty.
729 if (property.first == functionName + "FunctionType")
730 {
731 if (!strProperty->empty())
732 {
733 resp.jsonValue["FunctionType"] = *strProperty;
734 }
735 }
736 if (property.first == functionName + "DeviceClass")
737 {
738 if (!strProperty->empty())
739 {
740 resp.jsonValue["DeviceClass"] = *strProperty;
741 }
742 }
743 if (property.first == functionName + "ClassCode")
744 {
745 resp.jsonValue["ClassCode"] = *strProperty;
746 }
747 if (property.first == functionName + "RevisionId")
748 {
749 resp.jsonValue["RevisionId"] = *strProperty;
750 }
751 if (property.first == functionName + "SubsystemId")
752 {
753 resp.jsonValue["SubsystemId"] = *strProperty;
754 }
755 if (property.first == functionName + "SubsystemVendorId")
756 {
757 resp.jsonValue["SubsystemVendorId"] = *strProperty;
758 }
759 }
760}
761
762inline void addPCIeFunctionCommonProperties(crow::Response& resp,
763 const std::string& pcieDeviceId,
Ed Tanouse14742c2023-05-31 10:27:49 -0700764 uint64_t pcieFunctionId)
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600765{
766 resp.addHeader(
767 boost::beast::http::field::link,
768 "</redfish/v1/JsonSchemas/PCIeFunction/PCIeFunction.json>; rel=describedby");
769 resp.jsonValue["@odata.type"] = "#PCIeFunction.v1_2_3.PCIeFunction";
Ed Tanousef4c65b2023-04-24 15:28:50 -0700770 resp.jsonValue["@odata.id"] = boost::urls::format(
Ed Tanous253f11b2024-05-16 09:38:31 -0700771 "/redfish/v1/Systems/{}/PCIeDevices/{}/PCIeFunctions/{}",
772 BMCWEB_REDFISH_SYSTEM_URI_NAME, pcieDeviceId,
773 std::to_string(pcieFunctionId));
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600774 resp.jsonValue["Name"] = "PCIe Function";
Ed Tanouse14742c2023-05-31 10:27:49 -0700775 resp.jsonValue["Id"] = std::to_string(pcieFunctionId);
776 resp.jsonValue["FunctionId"] = pcieFunctionId;
Ed Tanous253f11b2024-05-16 09:38:31 -0700777 resp.jsonValue["Links"]["PCIeDevice"]["@odata.id"] =
778 boost::urls::format("/redfish/v1/Systems/{}/PCIeDevices/{}",
779 BMCWEB_REDFISH_SYSTEM_URI_NAME, pcieDeviceId);
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600780}
781
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400782inline void handlePCIeFunctionGet(
783 App& app, const crow::Request& req,
784 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
785 const std::string& systemName, const std::string& pcieDeviceId,
786 const std::string& pcieFunctionIdStr)
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600787{
Ed Tanousac106bf2023-06-07 09:24:59 -0700788 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600789 {
790 return;
791 }
Ed Tanous25b54db2024-04-17 15:40:31 -0700792 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800793 {
794 // Option currently returns no systems. TBD
795 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
796 systemName);
797 return;
798 }
Ed Tanous253f11b2024-05-16 09:38:31 -0700799 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800800 {
801 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
802 systemName);
803 return;
804 }
Ed Tanousdc8cfa62024-04-07 13:37:25 -0700805 std::string_view pcieFunctionIdView = pcieFunctionIdStr;
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800806
Ed Tanouse14742c2023-05-31 10:27:49 -0700807 uint64_t pcieFunctionId = 0;
808 std::from_chars_result result = std::from_chars(
Ed Tanousdc8cfa62024-04-07 13:37:25 -0700809 pcieFunctionIdView.begin(), pcieFunctionIdView.end(), pcieFunctionId);
810 if (result.ec != std::errc{} || result.ptr != pcieFunctionIdView.end())
Ed Tanouse14742c2023-05-31 10:27:49 -0700811 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700812 messages::resourceNotFound(asyncResp->res, "PCIeFunction",
Ed Tanouse14742c2023-05-31 10:27:49 -0700813 pcieFunctionIdStr);
814 return;
815 }
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600816
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400817 getValidPCIeDevicePath(
818 pcieDeviceId, asyncResp,
819 [asyncResp, pcieDeviceId, pcieFunctionId](
820 const std::string& pcieDevicePath, const std::string& service) {
821 getPCIeDeviceProperties(
822 asyncResp, pcieDevicePath, service,
823 [asyncResp, pcieDeviceId, pcieFunctionId](
824 const dbus::utility::DBusPropertiesMap& pcieDevProperties) {
825 addPCIeFunctionCommonProperties(
826 asyncResp->res, pcieDeviceId, pcieFunctionId);
827 addPCIeFunctionProperties(asyncResp->res, pcieFunctionId,
828 pcieDevProperties);
829 });
Patrick Williams5a39f772023-10-20 11:20:21 -0500830 });
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600831}
832
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700833inline void requestRoutesSystemPCIeFunction(App& app)
834{
835 BMCWEB_ROUTE(
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800836 app, "/redfish/v1/Systems/<str>/PCIeDevices/<str>/PCIeFunctions/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700837 .privileges(redfish::privileges::getPCIeFunction)
Ed Tanous002d39b2022-05-31 08:59:27 -0700838 .methods(boost::beast::http::verb::get)(
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600839 std::bind_front(handlePCIeFunctionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700840}
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -0800841
842} // namespace redfish