blob: 3cfed3a3ca4491b01d78dd97de3d3f9d43de59fe [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
Myung Bae8c1d0542024-03-12 17:50:48 -050032#include <limits>
33
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -080034namespace redfish
35{
36
Patrick Williams89492a12023-05-10 07:51:34 -050037static constexpr const char* inventoryPath = "/xyz/openbmc_project/inventory";
Lakshmi Yadlapati94c3a102023-04-05 18:11:22 -050038static constexpr std::array<std::string_view, 1> pcieDeviceInterface = {
39 "xyz.openbmc_project.Inventory.Item.PCIeDevice"};
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -050040static constexpr std::array<std::string_view, 1> pcieSlotInterface = {
41 "xyz.openbmc_project.Inventory.Item.PCIeSlot"};
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -080042
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060043static inline void handlePCIeDevicePath(
44 const std::string& pcieDeviceId,
Ed Tanousac106bf2023-06-07 09:24:59 -070045 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060046 const dbus::utility::MapperGetSubTreePathsResponse& pcieDevicePaths,
47 const std::function<void(const std::string& pcieDevicePath,
48 const std::string& service)>& callback)
49
50{
51 for (const std::string& pcieDevicePath : pcieDevicePaths)
52 {
53 std::string pciecDeviceName =
54 sdbusplus::message::object_path(pcieDevicePath).filename();
55 if (pciecDeviceName.empty() || pciecDeviceName != pcieDeviceId)
56 {
57 continue;
58 }
59
60 dbus::utility::getDbusObject(
61 pcieDevicePath, {},
Ed Tanousac106bf2023-06-07 09:24:59 -070062 [pcieDevicePath, asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060063 callback](const boost::system::error_code& ec,
64 const dbus::utility::MapperGetObject& object) {
65 if (ec || object.empty())
66 {
Ed Tanous62598e32023-07-17 17:06:25 -070067 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
Ed Tanousac106bf2023-06-07 09:24:59 -070068 messages::internalError(asyncResp->res);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060069 return;
70 }
71 callback(pcieDevicePath, object.begin()->first);
Patrick Williams5a39f772023-10-20 11:20:21 -050072 });
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060073 return;
74 }
75
Ed Tanous62598e32023-07-17 17:06:25 -070076 BMCWEB_LOG_WARNING("PCIe Device not found");
Ed Tanousac106bf2023-06-07 09:24:59 -070077 messages::resourceNotFound(asyncResp->res, "PCIeDevice", pcieDeviceId);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060078}
79
80static inline void getValidPCIeDevicePath(
81 const std::string& pcieDeviceId,
Ed Tanousac106bf2023-06-07 09:24:59 -070082 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060083 const std::function<void(const std::string& pcieDevicePath,
84 const std::string& service)>& callback)
85{
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060086 dbus::utility::getSubTreePaths(
Lakshmi Yadlapati94c3a102023-04-05 18:11:22 -050087 inventoryPath, 0, pcieDeviceInterface,
Ed Tanousac106bf2023-06-07 09:24:59 -070088 [pcieDeviceId, asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060089 callback](const boost::system::error_code& ec,
90 const dbus::utility::MapperGetSubTreePathsResponse&
91 pcieDevicePaths) {
92 if (ec)
93 {
Ed Tanous62598e32023-07-17 17:06:25 -070094 BMCWEB_LOG_ERROR("D-Bus response error on GetSubTree {}", ec);
Ed Tanousac106bf2023-06-07 09:24:59 -070095 messages::internalError(asyncResp->res);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060096 return;
97 }
Ed Tanousac106bf2023-06-07 09:24:59 -070098 handlePCIeDevicePath(pcieDeviceId, asyncResp, pcieDevicePaths,
99 callback);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600100 return;
Patrick Williams5a39f772023-10-20 11:20:21 -0500101 });
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600102}
103
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600104static inline void handlePCIeDeviceCollectionGet(
105 crow::App& app, const crow::Request& req,
Ed Tanousac106bf2023-06-07 09:24:59 -0700106 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600107 const std::string& systemName)
108{
Ed Tanousac106bf2023-06-07 09:24:59 -0700109 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600110 {
111 return;
112 }
Ed Tanous25b54db2024-04-17 15:40:31 -0700113 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800114 {
115 // Option currently returns no systems. TBD
116 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
117 systemName);
118 return;
119 }
Ed Tanous253f11b2024-05-16 09:38:31 -0700120 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600121 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700122 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
123 systemName);
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600124 return;
125 }
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600126
Ed Tanousac106bf2023-06-07 09:24:59 -0700127 asyncResp->res.addHeader(boost::beast::http::field::link,
128 "</redfish/v1/JsonSchemas/PCIeDeviceCollection/"
129 "PCIeDeviceCollection.json>; rel=describedby");
130 asyncResp->res.jsonValue["@odata.type"] =
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600131 "#PCIeDeviceCollection.PCIeDeviceCollection";
Ed Tanous253f11b2024-05-16 09:38:31 -0700132 asyncResp->res.jsonValue["@odata.id"] = std::format(
133 "/redfish/v1/Systems/{}/PCIeDevices", BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanousac106bf2023-06-07 09:24:59 -0700134 asyncResp->res.jsonValue["Name"] = "PCIe Device Collection";
135 asyncResp->res.jsonValue["Description"] = "Collection of PCIe Devices";
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600136
Lakshmi Yadlapati70c4d542023-06-08 04:37:18 -0500137 pcie_util::getPCIeDeviceList(asyncResp,
138 nlohmann::json::json_pointer("/Members"));
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600139}
140
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700141inline void requestRoutesSystemPCIeDeviceCollection(App& app)
Jason M. Billsadbe1922019-10-14 15:44:35 -0700142{
Jason M. Billsadbe1922019-10-14 15:44:35 -0700143 /**
144 * Functions triggers appropriate requests on DBus
145 */
Ed Tanous22d268c2022-05-19 09:39:07 -0700146 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/PCIeDevices/")
Ed Tanoused398212021-06-09 17:05:54 -0700147 .privileges(redfish::privileges::getPCIeDeviceCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700148 .methods(boost::beast::http::verb::get)(
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600149 std::bind_front(handlePCIeDeviceCollectionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700150}
151
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500152inline void addPCIeSlotProperties(
153 crow::Response& res, const boost::system::error_code& ec,
154 const dbus::utility::DBusPropertiesMap& pcieSlotProperties)
155{
156 if (ec)
157 {
Ed Tanous62598e32023-07-17 17:06:25 -0700158 BMCWEB_LOG_ERROR("DBUS response error for getAllProperties{}",
159 ec.value());
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500160 messages::internalError(res);
161 return;
162 }
163 std::string generation;
164 size_t lanes = 0;
165 std::string slotType;
166
167 bool success = sdbusplus::unpackPropertiesNoThrow(
168 dbus_utils::UnpackErrorPrinter(), pcieSlotProperties, "Generation",
169 generation, "Lanes", lanes, "SlotType", slotType);
170
171 if (!success)
172 {
173 messages::internalError(res);
174 return;
175 }
176
177 std::optional<pcie_device::PCIeTypes> pcieType =
178 pcie_util::redfishPcieGenerationFromDbus(generation);
179 if (!pcieType)
180 {
Ed Tanous62598e32023-07-17 17:06:25 -0700181 BMCWEB_LOG_WARNING("Unknown PCIeType: {}", generation);
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500182 }
183 else
184 {
185 if (*pcieType == pcie_device::PCIeTypes::Invalid)
186 {
Ed Tanous62598e32023-07-17 17:06:25 -0700187 BMCWEB_LOG_ERROR("Invalid PCIeType: {}", generation);
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500188 messages::internalError(res);
189 return;
190 }
191 res.jsonValue["Slot"]["PCIeType"] = *pcieType;
192 }
193
Konstantin Aladyshev82f80322023-07-10 15:00:38 +0300194 if (lanes != 0)
195 {
196 res.jsonValue["Slot"]["Lanes"] = lanes;
197 }
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500198
199 std::optional<pcie_slots::SlotTypes> redfishSlotType =
200 pcie_util::dbusSlotTypeToRf(slotType);
201 if (!redfishSlotType)
202 {
Ed Tanous62598e32023-07-17 17:06:25 -0700203 BMCWEB_LOG_WARNING("Unknown PCIeSlot Type: {}", slotType);
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500204 }
205 else
206 {
207 if (*redfishSlotType == pcie_slots::SlotTypes::Invalid)
208 {
Ed Tanous62598e32023-07-17 17:06:25 -0700209 BMCWEB_LOG_ERROR("Invalid PCIeSlot type: {}", slotType);
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500210 messages::internalError(res);
211 return;
212 }
213 res.jsonValue["Slot"]["SlotType"] = *redfishSlotType;
214 }
215}
216
217inline void getPCIeDeviceSlotPath(
218 const std::string& pcieDevicePath,
219 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
220 std::function<void(const std::string& pcieDeviceSlot)>&& callback)
221{
222 std::string associationPath = pcieDevicePath + "/contained_by";
223 dbus::utility::getAssociatedSubTreePaths(
224 associationPath, sdbusplus::message::object_path(inventoryPath), 0,
225 pcieSlotInterface,
Ed Tanous8cb2c022024-03-27 16:31:46 -0700226 [callback = std::move(callback), asyncResp, pcieDevicePath](
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500227 const boost::system::error_code& ec,
228 const dbus::utility::MapperGetSubTreePathsResponse& endpoints) {
229 if (ec)
230 {
231 if (ec.value() == EBADR)
232 {
233 // Missing association is not an error
234 return;
235 }
Ed Tanous62598e32023-07-17 17:06:25 -0700236 BMCWEB_LOG_ERROR(
237 "DBUS response error for getAssociatedSubTreePaths {}",
238 ec.value());
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500239 messages::internalError(asyncResp->res);
240 return;
241 }
242 if (endpoints.size() > 1)
243 {
Ed Tanous62598e32023-07-17 17:06:25 -0700244 BMCWEB_LOG_ERROR(
245 "PCIeDevice is associated with more than one PCIeSlot: {}",
246 endpoints.size());
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500247 messages::internalError(asyncResp->res);
248 return;
249 }
250 if (endpoints.empty())
251 {
252 // If the device doesn't have an association, return without PCIe
253 // Slot properties
Ed Tanous62598e32023-07-17 17:06:25 -0700254 BMCWEB_LOG_DEBUG("PCIeDevice is not associated with PCIeSlot");
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500255 return;
256 }
257 callback(endpoints[0]);
Patrick Williams5a39f772023-10-20 11:20:21 -0500258 });
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500259}
260
261inline void
262 afterGetDbusObject(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
263 const std::string& pcieDeviceSlot,
264 const boost::system::error_code& ec,
265 const dbus::utility::MapperGetObject& object)
266{
267 if (ec || object.empty())
268 {
Ed Tanous62598e32023-07-17 17:06:25 -0700269 BMCWEB_LOG_ERROR("DBUS response error for getDbusObject {}",
270 ec.value());
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500271 messages::internalError(asyncResp->res);
272 return;
273 }
274 sdbusplus::asio::getAllProperties(
275 *crow::connections::systemBus, object.begin()->first, pcieDeviceSlot,
276 "xyz.openbmc_project.Inventory.Item.PCIeSlot",
277 [asyncResp](
278 const boost::system::error_code& ec2,
279 const dbus::utility::DBusPropertiesMap& pcieSlotProperties) {
280 addPCIeSlotProperties(asyncResp->res, ec2, pcieSlotProperties);
Patrick Williams5a39f772023-10-20 11:20:21 -0500281 });
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500282}
283
284inline void afterGetPCIeDeviceSlotPath(
285 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
286 const std::string& pcieDeviceSlot)
287{
288 dbus::utility::getDbusObject(
289 pcieDeviceSlot, pcieSlotInterface,
290 [asyncResp,
291 pcieDeviceSlot](const boost::system::error_code& ec,
292 const dbus::utility::MapperGetObject& object) {
293 afterGetDbusObject(asyncResp, pcieDeviceSlot, ec, object);
Patrick Williams5a39f772023-10-20 11:20:21 -0500294 });
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500295}
296
Ed Tanousac106bf2023-06-07 09:24:59 -0700297inline void
Lakshmi Yadlapatie164f1b2023-04-12 17:01:34 -0500298 getPCIeDeviceHealth(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
299 const std::string& pcieDevicePath,
300 const std::string& service)
301{
302 sdbusplus::asio::getProperty<bool>(
303 *crow::connections::systemBus, service, pcieDevicePath,
304 "xyz.openbmc_project.State.Decorator.OperationalStatus", "Functional",
305 [asyncResp](const boost::system::error_code& ec, const bool value) {
306 if (ec)
307 {
308 if (ec.value() != EBADR)
309 {
Ed Tanous62598e32023-07-17 17:06:25 -0700310 BMCWEB_LOG_ERROR("DBUS response error for Health {}",
311 ec.value());
Lakshmi Yadlapatie164f1b2023-04-12 17:01:34 -0500312 messages::internalError(asyncResp->res);
313 }
314 return;
315 }
316
317 if (!value)
318 {
319 asyncResp->res.jsonValue["Status"]["Health"] = "Critical";
320 }
Patrick Williams5a39f772023-10-20 11:20:21 -0500321 });
Lakshmi Yadlapatie164f1b2023-04-12 17:01:34 -0500322}
323
324inline void
Ed Tanousac106bf2023-06-07 09:24:59 -0700325 getPCIeDeviceState(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
326 const std::string& pcieDevicePath,
327 const std::string& service)
Lakshmi Yadlapatic6bb3282023-04-12 16:56:49 -0500328{
329 sdbusplus::asio::getProperty<bool>(
330 *crow::connections::systemBus, service, pcieDevicePath,
331 "xyz.openbmc_project.Inventory.Item", "Present",
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500332 [asyncResp](const boost::system::error_code& ec, bool value) {
Lakshmi Yadlapatic6bb3282023-04-12 16:56:49 -0500333 if (ec)
334 {
335 if (ec.value() != EBADR)
336 {
Ed Tanous62598e32023-07-17 17:06:25 -0700337 BMCWEB_LOG_ERROR("DBUS response error for State");
Ed Tanousac106bf2023-06-07 09:24:59 -0700338 messages::internalError(asyncResp->res);
Lakshmi Yadlapatic6bb3282023-04-12 16:56:49 -0500339 }
340 return;
341 }
342
343 if (!value)
344 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700345 asyncResp->res.jsonValue["Status"]["State"] = "Absent";
Lakshmi Yadlapatic6bb3282023-04-12 16:56:49 -0500346 }
Patrick Williams5a39f772023-10-20 11:20:21 -0500347 });
Lakshmi Yadlapatic6bb3282023-04-12 16:56:49 -0500348}
349
Ed Tanousac106bf2023-06-07 09:24:59 -0700350inline void
351 getPCIeDeviceAsset(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
352 const std::string& pcieDevicePath,
353 const std::string& service)
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600354{
355 sdbusplus::asio::getAllProperties(
356 *crow::connections::systemBus, service, pcieDevicePath,
357 "xyz.openbmc_project.Inventory.Decorator.Asset",
Ed Tanousac106bf2023-06-07 09:24:59 -0700358 [pcieDevicePath, asyncResp{asyncResp}](
359 const boost::system::error_code& ec,
360 const dbus::utility::DBusPropertiesMap& assetList) {
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600361 if (ec)
362 {
363 if (ec.value() != EBADR)
364 {
Ed Tanous62598e32023-07-17 17:06:25 -0700365 BMCWEB_LOG_ERROR("DBUS response error for Properties{}",
366 ec.value());
Ed Tanousac106bf2023-06-07 09:24:59 -0700367 messages::internalError(asyncResp->res);
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600368 }
369 return;
370 }
371
372 const std::string* manufacturer = nullptr;
373 const std::string* model = nullptr;
374 const std::string* partNumber = nullptr;
375 const std::string* serialNumber = nullptr;
376 const std::string* sparePartNumber = nullptr;
377
378 const bool success = sdbusplus::unpackPropertiesNoThrow(
379 dbus_utils::UnpackErrorPrinter(), assetList, "Manufacturer",
380 manufacturer, "Model", model, "PartNumber", partNumber,
381 "SerialNumber", serialNumber, "SparePartNumber", sparePartNumber);
382
383 if (!success)
384 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700385 messages::internalError(asyncResp->res);
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600386 return;
387 }
388
389 if (manufacturer != nullptr)
390 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700391 asyncResp->res.jsonValue["Manufacturer"] = *manufacturer;
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600392 }
393 if (model != nullptr)
394 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700395 asyncResp->res.jsonValue["Model"] = *model;
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600396 }
397
398 if (partNumber != nullptr)
399 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700400 asyncResp->res.jsonValue["PartNumber"] = *partNumber;
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600401 }
402
403 if (serialNumber != nullptr)
404 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700405 asyncResp->res.jsonValue["SerialNumber"] = *serialNumber;
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600406 }
407
408 if (sparePartNumber != nullptr && !sparePartNumber->empty())
409 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700410 asyncResp->res.jsonValue["SparePartNumber"] = *sparePartNumber;
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600411 }
Patrick Williams5a39f772023-10-20 11:20:21 -0500412 });
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600413}
414
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600415inline void addPCIeDeviceProperties(
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500416 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
417 const std::string& pcieDeviceId,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600418 const dbus::utility::DBusPropertiesMap& pcieDevProperties)
419{
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600420 const std::string* generationInUse = nullptr;
Konstantin Aladyshev814bf202023-07-04 16:30:10 +0300421 const std::string* generationSupported = nullptr;
Konstantin Aladyshev9bb0a7f2023-07-04 12:59:34 +0300422 const size_t* lanesInUse = nullptr;
Konstantin Aladyshev814bf202023-07-04 16:30:10 +0300423 const size_t* maxLanes = nullptr;
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600424
425 const bool success = sdbusplus::unpackPropertiesNoThrow(
Ed Tanous609ba4c2023-07-11 09:14:24 -0700426 dbus_utils::UnpackErrorPrinter(), pcieDevProperties, "GenerationInUse",
427 generationInUse, "GenerationSupported", generationSupported,
428 "LanesInUse", lanesInUse, "MaxLanes", maxLanes);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600429
430 if (!success)
431 {
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500432 messages::internalError(asyncResp->res);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600433 return;
434 }
435
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600436 if (generationInUse != nullptr)
437 {
438 std::optional<pcie_device::PCIeTypes> redfishGenerationInUse =
Lakshmi Yadlapatic49c3292023-04-19 16:42:35 -0500439 pcie_util::redfishPcieGenerationFromDbus(*generationInUse);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600440
441 if (!redfishGenerationInUse)
442 {
Ed Tanous62598e32023-07-17 17:06:25 -0700443 BMCWEB_LOG_WARNING("Unknown PCIe Device Generation: {}",
444 *generationInUse);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600445 }
Lakshmi Yadlapaticf3b4842023-06-27 02:36:53 -0500446 else
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600447 {
Lakshmi Yadlapaticf3b4842023-06-27 02:36:53 -0500448 if (*redfishGenerationInUse == pcie_device::PCIeTypes::Invalid)
449 {
Ed Tanous62598e32023-07-17 17:06:25 -0700450 BMCWEB_LOG_ERROR("Invalid PCIe Device Generation: {}",
451 *generationInUse);
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500452 messages::internalError(asyncResp->res);
Lakshmi Yadlapaticf3b4842023-06-27 02:36:53 -0500453 return;
454 }
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500455 asyncResp->res.jsonValue["PCIeInterface"]["PCIeType"] =
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600456 *redfishGenerationInUse;
457 }
458 }
459
Konstantin Aladyshev814bf202023-07-04 16:30:10 +0300460 if (generationSupported != nullptr)
461 {
462 std::optional<pcie_device::PCIeTypes> redfishGenerationSupported =
463 pcie_util::redfishPcieGenerationFromDbus(*generationSupported);
464
465 if (!redfishGenerationSupported)
466 {
Ed Tanous62598e32023-07-17 17:06:25 -0700467 BMCWEB_LOG_WARNING("Unknown PCIe Device Generation: {}",
468 *generationSupported);
Konstantin Aladyshev814bf202023-07-04 16:30:10 +0300469 }
470 else
471 {
472 if (*redfishGenerationSupported == pcie_device::PCIeTypes::Invalid)
473 {
Ed Tanous62598e32023-07-17 17:06:25 -0700474 BMCWEB_LOG_ERROR("Invalid PCIe Device Generation: {}",
475 *generationSupported);
Konstantin Aladyshev814bf202023-07-04 16:30:10 +0300476 messages::internalError(asyncResp->res);
477 return;
478 }
479 asyncResp->res.jsonValue["PCIeInterface"]["MaxPCIeType"] =
480 *redfishGenerationSupported;
481 }
482 }
483
Myung Bae8c1d0542024-03-12 17:50:48 -0500484 if (lanesInUse != nullptr)
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600485 {
Myung Bae8c1d0542024-03-12 17:50:48 -0500486 if (*lanesInUse == std::numeric_limits<size_t>::max())
487 {
488 // The default value of LanesInUse is "maxint", and the field will
489 // be null if it is a default value.
490 asyncResp->res.jsonValue["PCIeInterface"]["LanesInUse"] = nullptr;
491 }
492 else
493 {
494 asyncResp->res.jsonValue["PCIeInterface"]["LanesInUse"] =
495 *lanesInUse;
496 }
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600497 }
Konstantin Aladyshev814bf202023-07-04 16:30:10 +0300498 // The default value of MaxLanes is 0, and the field will be
499 // left as off if it is a default value.
500 if (maxLanes != nullptr && *maxLanes != 0)
501 {
502 asyncResp->res.jsonValue["PCIeInterface"]["MaxLanes"] = *maxLanes;
503 }
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600504
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500505 asyncResp->res.jsonValue["PCIeFunctions"]["@odata.id"] =
506 boost::urls::format(
Ed Tanous253f11b2024-05-16 09:38:31 -0700507 "/redfish/v1/Systems/{}/PCIeDevices/{}/PCIeFunctions",
508 BMCWEB_REDFISH_SYSTEM_URI_NAME, pcieDeviceId);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600509}
510
511inline void getPCIeDeviceProperties(
Ed Tanousac106bf2023-06-07 09:24:59 -0700512 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600513 const std::string& pcieDevicePath, const std::string& service,
514 const std::function<void(
515 const dbus::utility::DBusPropertiesMap& pcieDevProperties)>&& callback)
516{
517 sdbusplus::asio::getAllProperties(
518 *crow::connections::systemBus, service, pcieDevicePath,
519 "xyz.openbmc_project.Inventory.Item.PCIeDevice",
Ed Tanousac106bf2023-06-07 09:24:59 -0700520 [asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600521 callback](const boost::system::error_code& ec,
522 const dbus::utility::DBusPropertiesMap& pcieDevProperties) {
523 if (ec)
524 {
525 if (ec.value() != EBADR)
526 {
Ed Tanous62598e32023-07-17 17:06:25 -0700527 BMCWEB_LOG_ERROR("DBUS response error for Properties");
Ed Tanousac106bf2023-06-07 09:24:59 -0700528 messages::internalError(asyncResp->res);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600529 }
530 return;
531 }
532 callback(pcieDevProperties);
Patrick Williams5a39f772023-10-20 11:20:21 -0500533 });
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600534}
535
536inline void addPCIeDeviceCommonProperties(
Ed Tanousac106bf2023-06-07 09:24:59 -0700537 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600538 const std::string& pcieDeviceId)
539{
Ed Tanousac106bf2023-06-07 09:24:59 -0700540 asyncResp->res.addHeader(
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600541 boost::beast::http::field::link,
542 "</redfish/v1/JsonSchemas/PCIeDevice/PCIeDevice.json>; rel=describedby");
Ed Tanousac106bf2023-06-07 09:24:59 -0700543 asyncResp->res.jsonValue["@odata.type"] = "#PCIeDevice.v1_9_0.PCIeDevice";
Ed Tanous253f11b2024-05-16 09:38:31 -0700544 asyncResp->res.jsonValue["@odata.id"] =
545 boost::urls::format("/redfish/v1/Systems/{}/PCIeDevices/{}",
546 BMCWEB_REDFISH_SYSTEM_URI_NAME, pcieDeviceId);
Ed Tanousac106bf2023-06-07 09:24:59 -0700547 asyncResp->res.jsonValue["Name"] = "PCIe Device";
548 asyncResp->res.jsonValue["Id"] = pcieDeviceId;
549 asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
Lakshmi Yadlapatie164f1b2023-04-12 17:01:34 -0500550 asyncResp->res.jsonValue["Status"]["Health"] = "OK";
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600551}
552
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500553inline void afterGetValidPcieDevicePath(
554 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
555 const std::string& pcieDeviceId, const std::string& pcieDevicePath,
556 const std::string& service)
557{
558 addPCIeDeviceCommonProperties(asyncResp, pcieDeviceId);
559 getPCIeDeviceAsset(asyncResp, pcieDevicePath, service);
560 getPCIeDeviceState(asyncResp, pcieDevicePath, service);
561 getPCIeDeviceHealth(asyncResp, pcieDevicePath, service);
562 getPCIeDeviceProperties(
563 asyncResp, pcieDevicePath, service,
564 std::bind_front(addPCIeDeviceProperties, asyncResp, pcieDeviceId));
565 getPCIeDeviceSlotPath(
566 pcieDevicePath, asyncResp,
567 std::bind_front(afterGetPCIeDeviceSlotPath, asyncResp));
568}
569
Ed Tanousac106bf2023-06-07 09:24:59 -0700570inline void
571 handlePCIeDeviceGet(App& app, const crow::Request& req,
572 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
573 const std::string& systemName,
574 const std::string& pcieDeviceId)
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600575{
Ed Tanousac106bf2023-06-07 09:24:59 -0700576 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600577 {
578 return;
579 }
Ed Tanous25b54db2024-04-17 15:40:31 -0700580 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800581 {
582 // Option currently returns no systems. TBD
583 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
584 systemName);
585 return;
586 }
Ed Tanous253f11b2024-05-16 09:38:31 -0700587 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600588 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700589 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
590 systemName);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600591 return;
592 }
593
594 getValidPCIeDevicePath(
Ed Tanousac106bf2023-06-07 09:24:59 -0700595 pcieDeviceId, asyncResp,
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500596 std::bind_front(afterGetValidPcieDevicePath, asyncResp, pcieDeviceId));
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600597}
598
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700599inline void requestRoutesSystemPCIeDevice(App& app)
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -0800600{
Ed Tanous22d268c2022-05-19 09:39:07 -0700601 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/PCIeDevices/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700602 .privileges(redfish::privileges::getPCIeDevice)
Ed Tanous002d39b2022-05-31 08:59:27 -0700603 .methods(boost::beast::http::verb::get)(
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600604 std::bind_front(handlePCIeDeviceGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700605}
606
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600607inline void addPCIeFunctionList(
608 crow::Response& res, const std::string& pcieDeviceId,
609 const dbus::utility::DBusPropertiesMap& pcieDevProperties)
610{
611 nlohmann::json& pcieFunctionList = res.jsonValue["Members"];
612 pcieFunctionList = nlohmann::json::array();
613 static constexpr const int maxPciFunctionNum = 8;
614
615 for (int functionNum = 0; functionNum < maxPciFunctionNum; functionNum++)
616 {
617 // Check if this function exists by
618 // looking for a device ID
Patrick Williams89492a12023-05-10 07:51:34 -0500619 std::string devIDProperty = "Function" + std::to_string(functionNum) +
620 "DeviceId";
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600621 const std::string* property = nullptr;
622 for (const auto& propEntry : pcieDevProperties)
623 {
624 if (propEntry.first == devIDProperty)
625 {
626 property = std::get_if<std::string>(&propEntry.second);
627 break;
628 }
629 }
630 if (property == nullptr || property->empty())
631 {
632 continue;
633 }
634
635 nlohmann::json::object_t pcieFunction;
Ed Tanousef4c65b2023-04-24 15:28:50 -0700636 pcieFunction["@odata.id"] = boost::urls::format(
Ed Tanous253f11b2024-05-16 09:38:31 -0700637 "/redfish/v1/Systems/{}/PCIeDevices/{}/PCIeFunctions/{}",
638 BMCWEB_REDFISH_SYSTEM_URI_NAME, pcieDeviceId,
639 std::to_string(functionNum));
Patrick Williamsb2ba3072023-05-12 10:27:39 -0500640 pcieFunctionList.emplace_back(std::move(pcieFunction));
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600641 }
642 res.jsonValue["PCIeFunctions@odata.count"] = pcieFunctionList.size();
643}
644
645inline void handlePCIeFunctionCollectionGet(
646 App& app, const crow::Request& req,
Ed Tanousac106bf2023-06-07 09:24:59 -0700647 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800648 const std::string& systemName, const std::string& pcieDeviceId)
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600649{
Ed Tanousac106bf2023-06-07 09:24:59 -0700650 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600651 {
652 return;
653 }
Ed Tanous25b54db2024-04-17 15:40:31 -0700654 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800655 {
656 // Option currently returns no systems. TBD
657 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
658 systemName);
659 return;
660 }
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600661
662 getValidPCIeDevicePath(
Ed Tanousac106bf2023-06-07 09:24:59 -0700663 pcieDeviceId, asyncResp,
664 [asyncResp, pcieDeviceId](const std::string& pcieDevicePath,
665 const std::string& service) {
666 asyncResp->res.addHeader(
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600667 boost::beast::http::field::link,
668 "</redfish/v1/JsonSchemas/PCIeFunctionCollection/PCIeFunctionCollection.json>; rel=describedby");
Ed Tanousac106bf2023-06-07 09:24:59 -0700669 asyncResp->res.jsonValue["@odata.type"] =
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600670 "#PCIeFunctionCollection.PCIeFunctionCollection";
Ed Tanousac106bf2023-06-07 09:24:59 -0700671 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
Ed Tanous253f11b2024-05-16 09:38:31 -0700672 "/redfish/v1/Systems/{}/PCIeDevices/{}/PCIeFunctions",
673 BMCWEB_REDFISH_SYSTEM_URI_NAME, pcieDeviceId);
Ed Tanousac106bf2023-06-07 09:24:59 -0700674 asyncResp->res.jsonValue["Name"] = "PCIe Function Collection";
675 asyncResp->res.jsonValue["Description"] =
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600676 "Collection of PCIe Functions for PCIe Device " + pcieDeviceId;
677 getPCIeDeviceProperties(
Ed Tanousac106bf2023-06-07 09:24:59 -0700678 asyncResp, pcieDevicePath, service,
679 [asyncResp, pcieDeviceId](
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600680 const dbus::utility::DBusPropertiesMap& pcieDevProperties) {
Ed Tanousac106bf2023-06-07 09:24:59 -0700681 addPCIeFunctionList(asyncResp->res, pcieDeviceId,
682 pcieDevProperties);
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600683 });
Patrick Williams5a39f772023-10-20 11:20:21 -0500684 });
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600685}
686
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700687inline void requestRoutesSystemPCIeFunctionCollection(App& app)
688{
689 /**
690 * Functions triggers appropriate requests on DBus
691 */
692 BMCWEB_ROUTE(app,
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800693 "/redfish/v1/Systems/<str>/PCIeDevices/<str>/PCIeFunctions/")
Ed Tanoused398212021-06-09 17:05:54 -0700694 .privileges(redfish::privileges::getPCIeFunctionCollection)
Ed Tanous002d39b2022-05-31 08:59:27 -0700695 .methods(boost::beast::http::verb::get)(
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600696 std::bind_front(handlePCIeFunctionCollectionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700697}
698
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600699inline bool validatePCIeFunctionId(
Myung Baed5e74b82023-05-31 11:28:02 -0500700 uint64_t pcieFunctionId,
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600701 const dbus::utility::DBusPropertiesMap& pcieDevProperties)
702{
Myung Baed5e74b82023-05-31 11:28:02 -0500703 std::string functionName = "Function" + std::to_string(pcieFunctionId);
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600704 std::string devIDProperty = functionName + "DeviceId";
705
706 const std::string* devIdProperty = nullptr;
707 for (const auto& property : pcieDevProperties)
708 {
709 if (property.first == devIDProperty)
710 {
711 devIdProperty = std::get_if<std::string>(&property.second);
712 break;
713 }
714 }
715 return (devIdProperty != nullptr && !devIdProperty->empty());
716}
717
718inline void addPCIeFunctionProperties(
Ed Tanouse14742c2023-05-31 10:27:49 -0700719 crow::Response& resp, uint64_t pcieFunctionId,
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600720 const dbus::utility::DBusPropertiesMap& pcieDevProperties)
721{
Ed Tanouse14742c2023-05-31 10:27:49 -0700722 std::string functionName = "Function" + std::to_string(pcieFunctionId);
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600723 for (const auto& property : pcieDevProperties)
724 {
725 const std::string* strProperty =
726 std::get_if<std::string>(&property.second);
Ed Tanousdc8cfa62024-04-07 13:37:25 -0700727 if (strProperty == nullptr)
728 {
729 BMCWEB_LOG_ERROR("Function wasn't a string?");
730 continue;
731 }
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600732 if (property.first == functionName + "DeviceId")
733 {
734 resp.jsonValue["DeviceId"] = *strProperty;
735 }
736 if (property.first == functionName + "VendorId")
737 {
738 resp.jsonValue["VendorId"] = *strProperty;
739 }
740 // TODO: FunctionType and DeviceClass are Redfish enums. The D-Bus
741 // property strings should be mapped correctly to ensure these
742 // strings are Redfish enum values. For now just check for empty.
743 if (property.first == functionName + "FunctionType")
744 {
745 if (!strProperty->empty())
746 {
747 resp.jsonValue["FunctionType"] = *strProperty;
748 }
749 }
750 if (property.first == functionName + "DeviceClass")
751 {
752 if (!strProperty->empty())
753 {
754 resp.jsonValue["DeviceClass"] = *strProperty;
755 }
756 }
757 if (property.first == functionName + "ClassCode")
758 {
759 resp.jsonValue["ClassCode"] = *strProperty;
760 }
761 if (property.first == functionName + "RevisionId")
762 {
763 resp.jsonValue["RevisionId"] = *strProperty;
764 }
765 if (property.first == functionName + "SubsystemId")
766 {
767 resp.jsonValue["SubsystemId"] = *strProperty;
768 }
769 if (property.first == functionName + "SubsystemVendorId")
770 {
771 resp.jsonValue["SubsystemVendorId"] = *strProperty;
772 }
773 }
774}
775
776inline void addPCIeFunctionCommonProperties(crow::Response& resp,
777 const std::string& pcieDeviceId,
Ed Tanouse14742c2023-05-31 10:27:49 -0700778 uint64_t pcieFunctionId)
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600779{
780 resp.addHeader(
781 boost::beast::http::field::link,
782 "</redfish/v1/JsonSchemas/PCIeFunction/PCIeFunction.json>; rel=describedby");
783 resp.jsonValue["@odata.type"] = "#PCIeFunction.v1_2_3.PCIeFunction";
Ed Tanousef4c65b2023-04-24 15:28:50 -0700784 resp.jsonValue["@odata.id"] = boost::urls::format(
Ed Tanous253f11b2024-05-16 09:38:31 -0700785 "/redfish/v1/Systems/{}/PCIeDevices/{}/PCIeFunctions/{}",
786 BMCWEB_REDFISH_SYSTEM_URI_NAME, pcieDeviceId,
787 std::to_string(pcieFunctionId));
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600788 resp.jsonValue["Name"] = "PCIe Function";
Ed Tanouse14742c2023-05-31 10:27:49 -0700789 resp.jsonValue["Id"] = std::to_string(pcieFunctionId);
790 resp.jsonValue["FunctionId"] = pcieFunctionId;
Ed Tanous253f11b2024-05-16 09:38:31 -0700791 resp.jsonValue["Links"]["PCIeDevice"]["@odata.id"] =
792 boost::urls::format("/redfish/v1/Systems/{}/PCIeDevices/{}",
793 BMCWEB_REDFISH_SYSTEM_URI_NAME, pcieDeviceId);
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600794}
795
796inline void
797 handlePCIeFunctionGet(App& app, const crow::Request& req,
Ed Tanousac106bf2023-06-07 09:24:59 -0700798 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800799 const std::string& systemName,
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600800 const std::string& pcieDeviceId,
Ed Tanouse14742c2023-05-31 10:27:49 -0700801 const std::string& pcieFunctionIdStr)
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600802{
Ed Tanousac106bf2023-06-07 09:24:59 -0700803 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600804 {
805 return;
806 }
Ed Tanous25b54db2024-04-17 15:40:31 -0700807 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800808 {
809 // Option currently returns no systems. TBD
810 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
811 systemName);
812 return;
813 }
Ed Tanous253f11b2024-05-16 09:38:31 -0700814 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800815 {
816 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
817 systemName);
818 return;
819 }
Ed Tanousdc8cfa62024-04-07 13:37:25 -0700820 std::string_view pcieFunctionIdView = pcieFunctionIdStr;
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800821
Ed Tanouse14742c2023-05-31 10:27:49 -0700822 uint64_t pcieFunctionId = 0;
823 std::from_chars_result result = std::from_chars(
Ed Tanousdc8cfa62024-04-07 13:37:25 -0700824 pcieFunctionIdView.begin(), pcieFunctionIdView.end(), pcieFunctionId);
825 if (result.ec != std::errc{} || result.ptr != pcieFunctionIdView.end())
Ed Tanouse14742c2023-05-31 10:27:49 -0700826 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700827 messages::resourceNotFound(asyncResp->res, "PCIeFunction",
Ed Tanouse14742c2023-05-31 10:27:49 -0700828 pcieFunctionIdStr);
829 return;
830 }
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600831
Ed Tanousac106bf2023-06-07 09:24:59 -0700832 getValidPCIeDevicePath(pcieDeviceId, asyncResp,
833 [asyncResp, pcieDeviceId,
834 pcieFunctionId](const std::string& pcieDevicePath,
835 const std::string& service) {
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600836 getPCIeDeviceProperties(
Ed Tanousac106bf2023-06-07 09:24:59 -0700837 asyncResp, pcieDevicePath, service,
838 [asyncResp, pcieDeviceId, pcieFunctionId](
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600839 const dbus::utility::DBusPropertiesMap& pcieDevProperties) {
Ed Tanousac106bf2023-06-07 09:24:59 -0700840 addPCIeFunctionCommonProperties(asyncResp->res, pcieDeviceId,
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600841 pcieFunctionId);
Ed Tanousac106bf2023-06-07 09:24:59 -0700842 addPCIeFunctionProperties(asyncResp->res, pcieFunctionId,
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600843 pcieDevProperties);
Patrick Williams5a39f772023-10-20 11:20:21 -0500844 });
Ed Tanousac106bf2023-06-07 09:24:59 -0700845 });
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600846}
847
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700848inline void requestRoutesSystemPCIeFunction(App& app)
849{
850 BMCWEB_ROUTE(
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800851 app, "/redfish/v1/Systems/<str>/PCIeDevices/<str>/PCIeFunctions/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700852 .privileges(redfish::privileges::getPCIeFunction)
Ed Tanous002d39b2022-05-31 08:59:27 -0700853 .methods(boost::beast::http::verb::get)(
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600854 std::bind_front(handlePCIeFunctionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700855}
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -0800856
857} // namespace redfish