blob: e62dc42ae8b1286401547491436f7a723841d6ad [file] [log] [blame]
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -08001/*
2// Copyright (c) 2018 Intel Corporation
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
16
17#pragma once
18
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080019#include "app.hpp"
George Liu7a1dbc42022-12-07 16:03:22 +080020#include "dbus_utility.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080021#include "query.hpp"
22#include "registries/privilege_registry.hpp"
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -060023#include "utils/collection.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080024#include "utils/dbus_utils.hpp"
Lakshmi Yadlapatic49c3292023-04-19 16:42:35 -050025#include "utils/pcie_util.hpp"
Ed Tanous0ec8b832022-03-14 14:56:47 -070026
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -080027#include <boost/system/linux_error.hpp>
Ed Tanousef4c65b2023-04-24 15:28:50 -070028#include <boost/url/format.hpp>
Krzysztof Grobelnyd1bde9e2022-09-07 10:40:51 +020029#include <sdbusplus/asio/property.hpp>
30#include <sdbusplus/unpack_properties.hpp>
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -080031
32namespace redfish
33{
34
Patrick Williams89492a12023-05-10 07:51:34 -050035static constexpr const char* inventoryPath = "/xyz/openbmc_project/inventory";
Lakshmi Yadlapati94c3a102023-04-05 18:11:22 -050036static constexpr std::array<std::string_view, 1> pcieDeviceInterface = {
37 "xyz.openbmc_project.Inventory.Item.PCIeDevice"};
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -050038static constexpr std::array<std::string_view, 1> pcieSlotInterface = {
39 "xyz.openbmc_project.Inventory.Item.PCIeSlot"};
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -080040
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060041static inline void handlePCIeDevicePath(
42 const std::string& pcieDeviceId,
Ed Tanousac106bf2023-06-07 09:24:59 -070043 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060044 const dbus::utility::MapperGetSubTreePathsResponse& pcieDevicePaths,
45 const std::function<void(const std::string& pcieDevicePath,
46 const std::string& service)>& callback)
47
48{
49 for (const std::string& pcieDevicePath : pcieDevicePaths)
50 {
51 std::string pciecDeviceName =
52 sdbusplus::message::object_path(pcieDevicePath).filename();
53 if (pciecDeviceName.empty() || pciecDeviceName != pcieDeviceId)
54 {
55 continue;
56 }
57
58 dbus::utility::getDbusObject(
59 pcieDevicePath, {},
Ed Tanousac106bf2023-06-07 09:24:59 -070060 [pcieDevicePath, asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060061 callback](const boost::system::error_code& ec,
62 const dbus::utility::MapperGetObject& object) {
63 if (ec || object.empty())
64 {
Ed Tanous62598e32023-07-17 17:06:25 -070065 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
Ed Tanousac106bf2023-06-07 09:24:59 -070066 messages::internalError(asyncResp->res);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060067 return;
68 }
69 callback(pcieDevicePath, object.begin()->first);
Patrick Williams5a39f772023-10-20 11:20:21 -050070 });
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060071 return;
72 }
73
Ed Tanous62598e32023-07-17 17:06:25 -070074 BMCWEB_LOG_WARNING("PCIe Device not found");
Ed Tanousac106bf2023-06-07 09:24:59 -070075 messages::resourceNotFound(asyncResp->res, "PCIeDevice", pcieDeviceId);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060076}
77
78static inline void getValidPCIeDevicePath(
79 const std::string& pcieDeviceId,
Ed Tanousac106bf2023-06-07 09:24:59 -070080 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060081 const std::function<void(const std::string& pcieDevicePath,
82 const std::string& service)>& callback)
83{
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060084 dbus::utility::getSubTreePaths(
Lakshmi Yadlapati94c3a102023-04-05 18:11:22 -050085 inventoryPath, 0, pcieDeviceInterface,
Ed Tanousac106bf2023-06-07 09:24:59 -070086 [pcieDeviceId, asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060087 callback](const boost::system::error_code& ec,
88 const dbus::utility::MapperGetSubTreePathsResponse&
89 pcieDevicePaths) {
90 if (ec)
91 {
Ed Tanous62598e32023-07-17 17:06:25 -070092 BMCWEB_LOG_ERROR("D-Bus response error on GetSubTree {}", ec);
Ed Tanousac106bf2023-06-07 09:24:59 -070093 messages::internalError(asyncResp->res);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060094 return;
95 }
Ed Tanousac106bf2023-06-07 09:24:59 -070096 handlePCIeDevicePath(pcieDeviceId, asyncResp, pcieDevicePaths,
97 callback);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060098 return;
Patrick Williams5a39f772023-10-20 11:20:21 -050099 });
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600100}
101
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600102static inline void handlePCIeDeviceCollectionGet(
103 crow::App& app, const crow::Request& req,
Ed Tanousac106bf2023-06-07 09:24:59 -0700104 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600105 const std::string& systemName)
106{
Ed Tanousac106bf2023-06-07 09:24:59 -0700107 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600108 {
109 return;
110 }
Ed Tanous25b54db2024-04-17 15:40:31 -0700111 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800112 {
113 // Option currently returns no systems. TBD
114 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
115 systemName);
116 return;
117 }
Ed Tanous253f11b2024-05-16 09:38:31 -0700118 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600119 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700120 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
121 systemName);
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600122 return;
123 }
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600124
Ed Tanousac106bf2023-06-07 09:24:59 -0700125 asyncResp->res.addHeader(boost::beast::http::field::link,
126 "</redfish/v1/JsonSchemas/PCIeDeviceCollection/"
127 "PCIeDeviceCollection.json>; rel=describedby");
128 asyncResp->res.jsonValue["@odata.type"] =
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600129 "#PCIeDeviceCollection.PCIeDeviceCollection";
Ed Tanous253f11b2024-05-16 09:38:31 -0700130 asyncResp->res.jsonValue["@odata.id"] = std::format(
131 "/redfish/v1/Systems/{}/PCIeDevices", BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanousac106bf2023-06-07 09:24:59 -0700132 asyncResp->res.jsonValue["Name"] = "PCIe Device Collection";
133 asyncResp->res.jsonValue["Description"] = "Collection of PCIe Devices";
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600134
Lakshmi Yadlapati70c4d542023-06-08 04:37:18 -0500135 pcie_util::getPCIeDeviceList(asyncResp,
136 nlohmann::json::json_pointer("/Members"));
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600137}
138
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700139inline void requestRoutesSystemPCIeDeviceCollection(App& app)
Jason M. Billsadbe1922019-10-14 15:44:35 -0700140{
Jason M. Billsadbe1922019-10-14 15:44:35 -0700141 /**
142 * Functions triggers appropriate requests on DBus
143 */
Ed Tanous22d268c2022-05-19 09:39:07 -0700144 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/PCIeDevices/")
Ed Tanoused398212021-06-09 17:05:54 -0700145 .privileges(redfish::privileges::getPCIeDeviceCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700146 .methods(boost::beast::http::verb::get)(
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600147 std::bind_front(handlePCIeDeviceCollectionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700148}
149
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500150inline void addPCIeSlotProperties(
151 crow::Response& res, const boost::system::error_code& ec,
152 const dbus::utility::DBusPropertiesMap& pcieSlotProperties)
153{
154 if (ec)
155 {
Ed Tanous62598e32023-07-17 17:06:25 -0700156 BMCWEB_LOG_ERROR("DBUS response error for getAllProperties{}",
157 ec.value());
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500158 messages::internalError(res);
159 return;
160 }
161 std::string generation;
162 size_t lanes = 0;
163 std::string slotType;
164
165 bool success = sdbusplus::unpackPropertiesNoThrow(
166 dbus_utils::UnpackErrorPrinter(), pcieSlotProperties, "Generation",
167 generation, "Lanes", lanes, "SlotType", slotType);
168
169 if (!success)
170 {
171 messages::internalError(res);
172 return;
173 }
174
175 std::optional<pcie_device::PCIeTypes> pcieType =
176 pcie_util::redfishPcieGenerationFromDbus(generation);
177 if (!pcieType)
178 {
Ed Tanous62598e32023-07-17 17:06:25 -0700179 BMCWEB_LOG_WARNING("Unknown PCIeType: {}", generation);
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500180 }
181 else
182 {
183 if (*pcieType == pcie_device::PCIeTypes::Invalid)
184 {
Ed Tanous62598e32023-07-17 17:06:25 -0700185 BMCWEB_LOG_ERROR("Invalid PCIeType: {}", generation);
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500186 messages::internalError(res);
187 return;
188 }
189 res.jsonValue["Slot"]["PCIeType"] = *pcieType;
190 }
191
Konstantin Aladyshev82f80322023-07-10 15:00:38 +0300192 if (lanes != 0)
193 {
194 res.jsonValue["Slot"]["Lanes"] = lanes;
195 }
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500196
197 std::optional<pcie_slots::SlotTypes> redfishSlotType =
198 pcie_util::dbusSlotTypeToRf(slotType);
199 if (!redfishSlotType)
200 {
Ed Tanous62598e32023-07-17 17:06:25 -0700201 BMCWEB_LOG_WARNING("Unknown PCIeSlot Type: {}", slotType);
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500202 }
203 else
204 {
205 if (*redfishSlotType == pcie_slots::SlotTypes::Invalid)
206 {
Ed Tanous62598e32023-07-17 17:06:25 -0700207 BMCWEB_LOG_ERROR("Invalid PCIeSlot type: {}", slotType);
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500208 messages::internalError(res);
209 return;
210 }
211 res.jsonValue["Slot"]["SlotType"] = *redfishSlotType;
212 }
213}
214
215inline void getPCIeDeviceSlotPath(
216 const std::string& pcieDevicePath,
217 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
218 std::function<void(const std::string& pcieDeviceSlot)>&& callback)
219{
220 std::string associationPath = pcieDevicePath + "/contained_by";
221 dbus::utility::getAssociatedSubTreePaths(
222 associationPath, sdbusplus::message::object_path(inventoryPath), 0,
223 pcieSlotInterface,
Ed Tanous8cb2c022024-03-27 16:31:46 -0700224 [callback = std::move(callback), asyncResp, pcieDevicePath](
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500225 const boost::system::error_code& ec,
226 const dbus::utility::MapperGetSubTreePathsResponse& endpoints) {
227 if (ec)
228 {
229 if (ec.value() == EBADR)
230 {
231 // Missing association is not an error
232 return;
233 }
Ed Tanous62598e32023-07-17 17:06:25 -0700234 BMCWEB_LOG_ERROR(
235 "DBUS response error for getAssociatedSubTreePaths {}",
236 ec.value());
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500237 messages::internalError(asyncResp->res);
238 return;
239 }
240 if (endpoints.size() > 1)
241 {
Ed Tanous62598e32023-07-17 17:06:25 -0700242 BMCWEB_LOG_ERROR(
243 "PCIeDevice is associated with more than one PCIeSlot: {}",
244 endpoints.size());
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500245 messages::internalError(asyncResp->res);
246 return;
247 }
248 if (endpoints.empty())
249 {
250 // If the device doesn't have an association, return without PCIe
251 // Slot properties
Ed Tanous62598e32023-07-17 17:06:25 -0700252 BMCWEB_LOG_DEBUG("PCIeDevice is not associated with PCIeSlot");
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500253 return;
254 }
255 callback(endpoints[0]);
Patrick Williams5a39f772023-10-20 11:20:21 -0500256 });
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500257}
258
259inline void
260 afterGetDbusObject(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
261 const std::string& pcieDeviceSlot,
262 const boost::system::error_code& ec,
263 const dbus::utility::MapperGetObject& object)
264{
265 if (ec || object.empty())
266 {
Ed Tanous62598e32023-07-17 17:06:25 -0700267 BMCWEB_LOG_ERROR("DBUS response error for getDbusObject {}",
268 ec.value());
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500269 messages::internalError(asyncResp->res);
270 return;
271 }
272 sdbusplus::asio::getAllProperties(
273 *crow::connections::systemBus, object.begin()->first, pcieDeviceSlot,
274 "xyz.openbmc_project.Inventory.Item.PCIeSlot",
275 [asyncResp](
276 const boost::system::error_code& ec2,
277 const dbus::utility::DBusPropertiesMap& pcieSlotProperties) {
278 addPCIeSlotProperties(asyncResp->res, ec2, pcieSlotProperties);
Patrick Williams5a39f772023-10-20 11:20:21 -0500279 });
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500280}
281
282inline void afterGetPCIeDeviceSlotPath(
283 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
284 const std::string& pcieDeviceSlot)
285{
286 dbus::utility::getDbusObject(
287 pcieDeviceSlot, pcieSlotInterface,
288 [asyncResp,
289 pcieDeviceSlot](const boost::system::error_code& ec,
290 const dbus::utility::MapperGetObject& object) {
291 afterGetDbusObject(asyncResp, pcieDeviceSlot, ec, object);
Patrick Williams5a39f772023-10-20 11:20:21 -0500292 });
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500293}
294
Ed Tanousac106bf2023-06-07 09:24:59 -0700295inline void
Lakshmi Yadlapatie164f1b2023-04-12 17:01:34 -0500296 getPCIeDeviceHealth(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
297 const std::string& pcieDevicePath,
298 const std::string& service)
299{
300 sdbusplus::asio::getProperty<bool>(
301 *crow::connections::systemBus, service, pcieDevicePath,
302 "xyz.openbmc_project.State.Decorator.OperationalStatus", "Functional",
303 [asyncResp](const boost::system::error_code& ec, const bool value) {
304 if (ec)
305 {
306 if (ec.value() != EBADR)
307 {
Ed Tanous62598e32023-07-17 17:06:25 -0700308 BMCWEB_LOG_ERROR("DBUS response error for Health {}",
309 ec.value());
Lakshmi Yadlapatie164f1b2023-04-12 17:01:34 -0500310 messages::internalError(asyncResp->res);
311 }
312 return;
313 }
314
315 if (!value)
316 {
317 asyncResp->res.jsonValue["Status"]["Health"] = "Critical";
318 }
Patrick Williams5a39f772023-10-20 11:20:21 -0500319 });
Lakshmi Yadlapatie164f1b2023-04-12 17:01:34 -0500320}
321
322inline void
Ed Tanousac106bf2023-06-07 09:24:59 -0700323 getPCIeDeviceState(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
324 const std::string& pcieDevicePath,
325 const std::string& service)
Lakshmi Yadlapatic6bb3282023-04-12 16:56:49 -0500326{
327 sdbusplus::asio::getProperty<bool>(
328 *crow::connections::systemBus, service, pcieDevicePath,
329 "xyz.openbmc_project.Inventory.Item", "Present",
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500330 [asyncResp](const boost::system::error_code& ec, bool value) {
Lakshmi Yadlapatic6bb3282023-04-12 16:56:49 -0500331 if (ec)
332 {
333 if (ec.value() != EBADR)
334 {
Ed Tanous62598e32023-07-17 17:06:25 -0700335 BMCWEB_LOG_ERROR("DBUS response error for State");
Ed Tanousac106bf2023-06-07 09:24:59 -0700336 messages::internalError(asyncResp->res);
Lakshmi Yadlapatic6bb3282023-04-12 16:56:49 -0500337 }
338 return;
339 }
340
341 if (!value)
342 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700343 asyncResp->res.jsonValue["Status"]["State"] = "Absent";
Lakshmi Yadlapatic6bb3282023-04-12 16:56:49 -0500344 }
Patrick Williams5a39f772023-10-20 11:20:21 -0500345 });
Lakshmi Yadlapatic6bb3282023-04-12 16:56:49 -0500346}
347
Ed Tanousac106bf2023-06-07 09:24:59 -0700348inline void
349 getPCIeDeviceAsset(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
350 const std::string& pcieDevicePath,
351 const std::string& service)
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600352{
353 sdbusplus::asio::getAllProperties(
354 *crow::connections::systemBus, service, pcieDevicePath,
355 "xyz.openbmc_project.Inventory.Decorator.Asset",
Ed Tanousac106bf2023-06-07 09:24:59 -0700356 [pcieDevicePath, asyncResp{asyncResp}](
357 const boost::system::error_code& ec,
358 const dbus::utility::DBusPropertiesMap& assetList) {
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600359 if (ec)
360 {
361 if (ec.value() != EBADR)
362 {
Ed Tanous62598e32023-07-17 17:06:25 -0700363 BMCWEB_LOG_ERROR("DBUS response error for Properties{}",
364 ec.value());
Ed Tanousac106bf2023-06-07 09:24:59 -0700365 messages::internalError(asyncResp->res);
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600366 }
367 return;
368 }
369
370 const std::string* manufacturer = nullptr;
371 const std::string* model = nullptr;
372 const std::string* partNumber = nullptr;
373 const std::string* serialNumber = nullptr;
374 const std::string* sparePartNumber = nullptr;
375
376 const bool success = sdbusplus::unpackPropertiesNoThrow(
377 dbus_utils::UnpackErrorPrinter(), assetList, "Manufacturer",
378 manufacturer, "Model", model, "PartNumber", partNumber,
379 "SerialNumber", serialNumber, "SparePartNumber", sparePartNumber);
380
381 if (!success)
382 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700383 messages::internalError(asyncResp->res);
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600384 return;
385 }
386
387 if (manufacturer != nullptr)
388 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700389 asyncResp->res.jsonValue["Manufacturer"] = *manufacturer;
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600390 }
391 if (model != nullptr)
392 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700393 asyncResp->res.jsonValue["Model"] = *model;
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600394 }
395
396 if (partNumber != nullptr)
397 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700398 asyncResp->res.jsonValue["PartNumber"] = *partNumber;
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600399 }
400
401 if (serialNumber != nullptr)
402 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700403 asyncResp->res.jsonValue["SerialNumber"] = *serialNumber;
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600404 }
405
406 if (sparePartNumber != nullptr && !sparePartNumber->empty())
407 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700408 asyncResp->res.jsonValue["SparePartNumber"] = *sparePartNumber;
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600409 }
Patrick Williams5a39f772023-10-20 11:20:21 -0500410 });
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600411}
412
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600413inline void addPCIeDeviceProperties(
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500414 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
415 const std::string& pcieDeviceId,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600416 const dbus::utility::DBusPropertiesMap& pcieDevProperties)
417{
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600418 const std::string* generationInUse = nullptr;
Konstantin Aladyshev814bf202023-07-04 16:30:10 +0300419 const std::string* generationSupported = nullptr;
Konstantin Aladyshev9bb0a7f2023-07-04 12:59:34 +0300420 const size_t* lanesInUse = nullptr;
Konstantin Aladyshev814bf202023-07-04 16:30:10 +0300421 const size_t* maxLanes = nullptr;
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600422
423 const bool success = sdbusplus::unpackPropertiesNoThrow(
Ed Tanous609ba4c2023-07-11 09:14:24 -0700424 dbus_utils::UnpackErrorPrinter(), pcieDevProperties, "GenerationInUse",
425 generationInUse, "GenerationSupported", generationSupported,
426 "LanesInUse", lanesInUse, "MaxLanes", maxLanes);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600427
428 if (!success)
429 {
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500430 messages::internalError(asyncResp->res);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600431 return;
432 }
433
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600434 if (generationInUse != nullptr)
435 {
436 std::optional<pcie_device::PCIeTypes> redfishGenerationInUse =
Lakshmi Yadlapatic49c3292023-04-19 16:42:35 -0500437 pcie_util::redfishPcieGenerationFromDbus(*generationInUse);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600438
439 if (!redfishGenerationInUse)
440 {
Ed Tanous62598e32023-07-17 17:06:25 -0700441 BMCWEB_LOG_WARNING("Unknown PCIe Device Generation: {}",
442 *generationInUse);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600443 }
Lakshmi Yadlapaticf3b4842023-06-27 02:36:53 -0500444 else
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600445 {
Lakshmi Yadlapaticf3b4842023-06-27 02:36:53 -0500446 if (*redfishGenerationInUse == pcie_device::PCIeTypes::Invalid)
447 {
Ed Tanous62598e32023-07-17 17:06:25 -0700448 BMCWEB_LOG_ERROR("Invalid PCIe Device Generation: {}",
449 *generationInUse);
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500450 messages::internalError(asyncResp->res);
Lakshmi Yadlapaticf3b4842023-06-27 02:36:53 -0500451 return;
452 }
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500453 asyncResp->res.jsonValue["PCIeInterface"]["PCIeType"] =
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600454 *redfishGenerationInUse;
455 }
456 }
457
Konstantin Aladyshev814bf202023-07-04 16:30:10 +0300458 if (generationSupported != nullptr)
459 {
460 std::optional<pcie_device::PCIeTypes> redfishGenerationSupported =
461 pcie_util::redfishPcieGenerationFromDbus(*generationSupported);
462
463 if (!redfishGenerationSupported)
464 {
Ed Tanous62598e32023-07-17 17:06:25 -0700465 BMCWEB_LOG_WARNING("Unknown PCIe Device Generation: {}",
466 *generationSupported);
Konstantin Aladyshev814bf202023-07-04 16:30:10 +0300467 }
468 else
469 {
470 if (*redfishGenerationSupported == pcie_device::PCIeTypes::Invalid)
471 {
Ed Tanous62598e32023-07-17 17:06:25 -0700472 BMCWEB_LOG_ERROR("Invalid PCIe Device Generation: {}",
473 *generationSupported);
Konstantin Aladyshev814bf202023-07-04 16:30:10 +0300474 messages::internalError(asyncResp->res);
475 return;
476 }
477 asyncResp->res.jsonValue["PCIeInterface"]["MaxPCIeType"] =
478 *redfishGenerationSupported;
479 }
480 }
481
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600482 // The default value of LanesInUse is 0, and the field will be
483 // left as off if it is a default value.
484 if (lanesInUse != nullptr && *lanesInUse != 0)
485 {
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500486 asyncResp->res.jsonValue["PCIeInterface"]["LanesInUse"] = *lanesInUse;
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600487 }
Konstantin Aladyshev814bf202023-07-04 16:30:10 +0300488 // The default value of MaxLanes is 0, and the field will be
489 // left as off if it is a default value.
490 if (maxLanes != nullptr && *maxLanes != 0)
491 {
492 asyncResp->res.jsonValue["PCIeInterface"]["MaxLanes"] = *maxLanes;
493 }
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600494
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500495 asyncResp->res.jsonValue["PCIeFunctions"]["@odata.id"] =
496 boost::urls::format(
Ed Tanous253f11b2024-05-16 09:38:31 -0700497 "/redfish/v1/Systems/{}/PCIeDevices/{}/PCIeFunctions",
498 BMCWEB_REDFISH_SYSTEM_URI_NAME, pcieDeviceId);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600499}
500
501inline void getPCIeDeviceProperties(
Ed Tanousac106bf2023-06-07 09:24:59 -0700502 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600503 const std::string& pcieDevicePath, const std::string& service,
504 const std::function<void(
505 const dbus::utility::DBusPropertiesMap& pcieDevProperties)>&& callback)
506{
507 sdbusplus::asio::getAllProperties(
508 *crow::connections::systemBus, service, pcieDevicePath,
509 "xyz.openbmc_project.Inventory.Item.PCIeDevice",
Ed Tanousac106bf2023-06-07 09:24:59 -0700510 [asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600511 callback](const boost::system::error_code& ec,
512 const dbus::utility::DBusPropertiesMap& pcieDevProperties) {
513 if (ec)
514 {
515 if (ec.value() != EBADR)
516 {
Ed Tanous62598e32023-07-17 17:06:25 -0700517 BMCWEB_LOG_ERROR("DBUS response error for Properties");
Ed Tanousac106bf2023-06-07 09:24:59 -0700518 messages::internalError(asyncResp->res);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600519 }
520 return;
521 }
522 callback(pcieDevProperties);
Patrick Williams5a39f772023-10-20 11:20:21 -0500523 });
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600524}
525
526inline void addPCIeDeviceCommonProperties(
Ed Tanousac106bf2023-06-07 09:24:59 -0700527 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600528 const std::string& pcieDeviceId)
529{
Ed Tanousac106bf2023-06-07 09:24:59 -0700530 asyncResp->res.addHeader(
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600531 boost::beast::http::field::link,
532 "</redfish/v1/JsonSchemas/PCIeDevice/PCIeDevice.json>; rel=describedby");
Ed Tanousac106bf2023-06-07 09:24:59 -0700533 asyncResp->res.jsonValue["@odata.type"] = "#PCIeDevice.v1_9_0.PCIeDevice";
Ed Tanous253f11b2024-05-16 09:38:31 -0700534 asyncResp->res.jsonValue["@odata.id"] =
535 boost::urls::format("/redfish/v1/Systems/{}/PCIeDevices/{}",
536 BMCWEB_REDFISH_SYSTEM_URI_NAME, pcieDeviceId);
Ed Tanousac106bf2023-06-07 09:24:59 -0700537 asyncResp->res.jsonValue["Name"] = "PCIe Device";
538 asyncResp->res.jsonValue["Id"] = pcieDeviceId;
539 asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
Lakshmi Yadlapatie164f1b2023-04-12 17:01:34 -0500540 asyncResp->res.jsonValue["Status"]["Health"] = "OK";
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600541}
542
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500543inline void afterGetValidPcieDevicePath(
544 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
545 const std::string& pcieDeviceId, const std::string& pcieDevicePath,
546 const std::string& service)
547{
548 addPCIeDeviceCommonProperties(asyncResp, pcieDeviceId);
549 getPCIeDeviceAsset(asyncResp, pcieDevicePath, service);
550 getPCIeDeviceState(asyncResp, pcieDevicePath, service);
551 getPCIeDeviceHealth(asyncResp, pcieDevicePath, service);
552 getPCIeDeviceProperties(
553 asyncResp, pcieDevicePath, service,
554 std::bind_front(addPCIeDeviceProperties, asyncResp, pcieDeviceId));
555 getPCIeDeviceSlotPath(
556 pcieDevicePath, asyncResp,
557 std::bind_front(afterGetPCIeDeviceSlotPath, asyncResp));
558}
559
Ed Tanousac106bf2023-06-07 09:24:59 -0700560inline void
561 handlePCIeDeviceGet(App& app, const crow::Request& req,
562 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
563 const std::string& systemName,
564 const std::string& pcieDeviceId)
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600565{
Ed Tanousac106bf2023-06-07 09:24:59 -0700566 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600567 {
568 return;
569 }
Ed Tanous25b54db2024-04-17 15:40:31 -0700570 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800571 {
572 // Option currently returns no systems. TBD
573 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
574 systemName);
575 return;
576 }
Ed Tanous253f11b2024-05-16 09:38:31 -0700577 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600578 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700579 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
580 systemName);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600581 return;
582 }
583
584 getValidPCIeDevicePath(
Ed Tanousac106bf2023-06-07 09:24:59 -0700585 pcieDeviceId, asyncResp,
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500586 std::bind_front(afterGetValidPcieDevicePath, asyncResp, pcieDeviceId));
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600587}
588
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700589inline void requestRoutesSystemPCIeDevice(App& app)
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -0800590{
Ed Tanous22d268c2022-05-19 09:39:07 -0700591 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/PCIeDevices/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700592 .privileges(redfish::privileges::getPCIeDevice)
Ed Tanous002d39b2022-05-31 08:59:27 -0700593 .methods(boost::beast::http::verb::get)(
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600594 std::bind_front(handlePCIeDeviceGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700595}
596
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600597inline void addPCIeFunctionList(
598 crow::Response& res, const std::string& pcieDeviceId,
599 const dbus::utility::DBusPropertiesMap& pcieDevProperties)
600{
601 nlohmann::json& pcieFunctionList = res.jsonValue["Members"];
602 pcieFunctionList = nlohmann::json::array();
603 static constexpr const int maxPciFunctionNum = 8;
604
605 for (int functionNum = 0; functionNum < maxPciFunctionNum; functionNum++)
606 {
607 // Check if this function exists by
608 // looking for a device ID
Patrick Williams89492a12023-05-10 07:51:34 -0500609 std::string devIDProperty = "Function" + std::to_string(functionNum) +
610 "DeviceId";
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600611 const std::string* property = nullptr;
612 for (const auto& propEntry : pcieDevProperties)
613 {
614 if (propEntry.first == devIDProperty)
615 {
616 property = std::get_if<std::string>(&propEntry.second);
617 break;
618 }
619 }
620 if (property == nullptr || property->empty())
621 {
622 continue;
623 }
624
625 nlohmann::json::object_t pcieFunction;
Ed Tanousef4c65b2023-04-24 15:28:50 -0700626 pcieFunction["@odata.id"] = boost::urls::format(
Ed Tanous253f11b2024-05-16 09:38:31 -0700627 "/redfish/v1/Systems/{}/PCIeDevices/{}/PCIeFunctions/{}",
628 BMCWEB_REDFISH_SYSTEM_URI_NAME, pcieDeviceId,
629 std::to_string(functionNum));
Patrick Williamsb2ba3072023-05-12 10:27:39 -0500630 pcieFunctionList.emplace_back(std::move(pcieFunction));
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600631 }
632 res.jsonValue["PCIeFunctions@odata.count"] = pcieFunctionList.size();
633}
634
635inline void handlePCIeFunctionCollectionGet(
636 App& app, const crow::Request& req,
Ed Tanousac106bf2023-06-07 09:24:59 -0700637 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800638 const std::string& systemName, const std::string& pcieDeviceId)
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600639{
Ed Tanousac106bf2023-06-07 09:24:59 -0700640 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600641 {
642 return;
643 }
Ed Tanous25b54db2024-04-17 15:40:31 -0700644 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800645 {
646 // Option currently returns no systems. TBD
647 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
648 systemName);
649 return;
650 }
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600651
652 getValidPCIeDevicePath(
Ed Tanousac106bf2023-06-07 09:24:59 -0700653 pcieDeviceId, asyncResp,
654 [asyncResp, pcieDeviceId](const std::string& pcieDevicePath,
655 const std::string& service) {
656 asyncResp->res.addHeader(
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600657 boost::beast::http::field::link,
658 "</redfish/v1/JsonSchemas/PCIeFunctionCollection/PCIeFunctionCollection.json>; rel=describedby");
Ed Tanousac106bf2023-06-07 09:24:59 -0700659 asyncResp->res.jsonValue["@odata.type"] =
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600660 "#PCIeFunctionCollection.PCIeFunctionCollection";
Ed Tanousac106bf2023-06-07 09:24:59 -0700661 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
Ed Tanous253f11b2024-05-16 09:38:31 -0700662 "/redfish/v1/Systems/{}/PCIeDevices/{}/PCIeFunctions",
663 BMCWEB_REDFISH_SYSTEM_URI_NAME, pcieDeviceId);
Ed Tanousac106bf2023-06-07 09:24:59 -0700664 asyncResp->res.jsonValue["Name"] = "PCIe Function Collection";
665 asyncResp->res.jsonValue["Description"] =
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600666 "Collection of PCIe Functions for PCIe Device " + pcieDeviceId;
667 getPCIeDeviceProperties(
Ed Tanousac106bf2023-06-07 09:24:59 -0700668 asyncResp, pcieDevicePath, service,
669 [asyncResp, pcieDeviceId](
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600670 const dbus::utility::DBusPropertiesMap& pcieDevProperties) {
Ed Tanousac106bf2023-06-07 09:24:59 -0700671 addPCIeFunctionList(asyncResp->res, pcieDeviceId,
672 pcieDevProperties);
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600673 });
Patrick Williams5a39f772023-10-20 11:20:21 -0500674 });
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600675}
676
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700677inline void requestRoutesSystemPCIeFunctionCollection(App& app)
678{
679 /**
680 * Functions triggers appropriate requests on DBus
681 */
682 BMCWEB_ROUTE(app,
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800683 "/redfish/v1/Systems/<str>/PCIeDevices/<str>/PCIeFunctions/")
Ed Tanoused398212021-06-09 17:05:54 -0700684 .privileges(redfish::privileges::getPCIeFunctionCollection)
Ed Tanous002d39b2022-05-31 08:59:27 -0700685 .methods(boost::beast::http::verb::get)(
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600686 std::bind_front(handlePCIeFunctionCollectionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700687}
688
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600689inline bool validatePCIeFunctionId(
Myung Baed5e74b82023-05-31 11:28:02 -0500690 uint64_t pcieFunctionId,
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600691 const dbus::utility::DBusPropertiesMap& pcieDevProperties)
692{
Myung Baed5e74b82023-05-31 11:28:02 -0500693 std::string functionName = "Function" + std::to_string(pcieFunctionId);
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600694 std::string devIDProperty = functionName + "DeviceId";
695
696 const std::string* devIdProperty = nullptr;
697 for (const auto& property : pcieDevProperties)
698 {
699 if (property.first == devIDProperty)
700 {
701 devIdProperty = std::get_if<std::string>(&property.second);
702 break;
703 }
704 }
705 return (devIdProperty != nullptr && !devIdProperty->empty());
706}
707
708inline void addPCIeFunctionProperties(
Ed Tanouse14742c2023-05-31 10:27:49 -0700709 crow::Response& resp, uint64_t pcieFunctionId,
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600710 const dbus::utility::DBusPropertiesMap& pcieDevProperties)
711{
Ed Tanouse14742c2023-05-31 10:27:49 -0700712 std::string functionName = "Function" + std::to_string(pcieFunctionId);
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600713 for (const auto& property : pcieDevProperties)
714 {
715 const std::string* strProperty =
716 std::get_if<std::string>(&property.second);
Ed Tanousdc8cfa62024-04-07 13:37:25 -0700717 if (strProperty == nullptr)
718 {
719 BMCWEB_LOG_ERROR("Function wasn't a string?");
720 continue;
721 }
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600722 if (property.first == functionName + "DeviceId")
723 {
724 resp.jsonValue["DeviceId"] = *strProperty;
725 }
726 if (property.first == functionName + "VendorId")
727 {
728 resp.jsonValue["VendorId"] = *strProperty;
729 }
730 // TODO: FunctionType and DeviceClass are Redfish enums. The D-Bus
731 // property strings should be mapped correctly to ensure these
732 // strings are Redfish enum values. For now just check for empty.
733 if (property.first == functionName + "FunctionType")
734 {
735 if (!strProperty->empty())
736 {
737 resp.jsonValue["FunctionType"] = *strProperty;
738 }
739 }
740 if (property.first == functionName + "DeviceClass")
741 {
742 if (!strProperty->empty())
743 {
744 resp.jsonValue["DeviceClass"] = *strProperty;
745 }
746 }
747 if (property.first == functionName + "ClassCode")
748 {
749 resp.jsonValue["ClassCode"] = *strProperty;
750 }
751 if (property.first == functionName + "RevisionId")
752 {
753 resp.jsonValue["RevisionId"] = *strProperty;
754 }
755 if (property.first == functionName + "SubsystemId")
756 {
757 resp.jsonValue["SubsystemId"] = *strProperty;
758 }
759 if (property.first == functionName + "SubsystemVendorId")
760 {
761 resp.jsonValue["SubsystemVendorId"] = *strProperty;
762 }
763 }
764}
765
766inline void addPCIeFunctionCommonProperties(crow::Response& resp,
767 const std::string& pcieDeviceId,
Ed Tanouse14742c2023-05-31 10:27:49 -0700768 uint64_t pcieFunctionId)
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600769{
770 resp.addHeader(
771 boost::beast::http::field::link,
772 "</redfish/v1/JsonSchemas/PCIeFunction/PCIeFunction.json>; rel=describedby");
773 resp.jsonValue["@odata.type"] = "#PCIeFunction.v1_2_3.PCIeFunction";
Ed Tanousef4c65b2023-04-24 15:28:50 -0700774 resp.jsonValue["@odata.id"] = boost::urls::format(
Ed Tanous253f11b2024-05-16 09:38:31 -0700775 "/redfish/v1/Systems/{}/PCIeDevices/{}/PCIeFunctions/{}",
776 BMCWEB_REDFISH_SYSTEM_URI_NAME, pcieDeviceId,
777 std::to_string(pcieFunctionId));
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600778 resp.jsonValue["Name"] = "PCIe Function";
Ed Tanouse14742c2023-05-31 10:27:49 -0700779 resp.jsonValue["Id"] = std::to_string(pcieFunctionId);
780 resp.jsonValue["FunctionId"] = pcieFunctionId;
Ed Tanous253f11b2024-05-16 09:38:31 -0700781 resp.jsonValue["Links"]["PCIeDevice"]["@odata.id"] =
782 boost::urls::format("/redfish/v1/Systems/{}/PCIeDevices/{}",
783 BMCWEB_REDFISH_SYSTEM_URI_NAME, pcieDeviceId);
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600784}
785
786inline void
787 handlePCIeFunctionGet(App& app, const crow::Request& req,
Ed Tanousac106bf2023-06-07 09:24:59 -0700788 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800789 const std::string& systemName,
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600790 const std::string& pcieDeviceId,
Ed Tanouse14742c2023-05-31 10:27:49 -0700791 const std::string& pcieFunctionIdStr)
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600792{
Ed Tanousac106bf2023-06-07 09:24:59 -0700793 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600794 {
795 return;
796 }
Ed Tanous25b54db2024-04-17 15:40:31 -0700797 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800798 {
799 // Option currently returns no systems. TBD
800 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
801 systemName);
802 return;
803 }
Ed Tanous253f11b2024-05-16 09:38:31 -0700804 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800805 {
806 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
807 systemName);
808 return;
809 }
Ed Tanousdc8cfa62024-04-07 13:37:25 -0700810 std::string_view pcieFunctionIdView = pcieFunctionIdStr;
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800811
Ed Tanouse14742c2023-05-31 10:27:49 -0700812 uint64_t pcieFunctionId = 0;
813 std::from_chars_result result = std::from_chars(
Ed Tanousdc8cfa62024-04-07 13:37:25 -0700814 pcieFunctionIdView.begin(), pcieFunctionIdView.end(), pcieFunctionId);
815 if (result.ec != std::errc{} || result.ptr != pcieFunctionIdView.end())
Ed Tanouse14742c2023-05-31 10:27:49 -0700816 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700817 messages::resourceNotFound(asyncResp->res, "PCIeFunction",
Ed Tanouse14742c2023-05-31 10:27:49 -0700818 pcieFunctionIdStr);
819 return;
820 }
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600821
Ed Tanousac106bf2023-06-07 09:24:59 -0700822 getValidPCIeDevicePath(pcieDeviceId, asyncResp,
823 [asyncResp, pcieDeviceId,
824 pcieFunctionId](const std::string& pcieDevicePath,
825 const std::string& service) {
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600826 getPCIeDeviceProperties(
Ed Tanousac106bf2023-06-07 09:24:59 -0700827 asyncResp, pcieDevicePath, service,
828 [asyncResp, pcieDeviceId, pcieFunctionId](
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600829 const dbus::utility::DBusPropertiesMap& pcieDevProperties) {
Ed Tanousac106bf2023-06-07 09:24:59 -0700830 addPCIeFunctionCommonProperties(asyncResp->res, pcieDeviceId,
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600831 pcieFunctionId);
Ed Tanousac106bf2023-06-07 09:24:59 -0700832 addPCIeFunctionProperties(asyncResp->res, pcieFunctionId,
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600833 pcieDevProperties);
Patrick Williams5a39f772023-10-20 11:20:21 -0500834 });
Ed Tanousac106bf2023-06-07 09:24:59 -0700835 });
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600836}
837
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700838inline void requestRoutesSystemPCIeFunction(App& app)
839{
840 BMCWEB_ROUTE(
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800841 app, "/redfish/v1/Systems/<str>/PCIeDevices/<str>/PCIeFunctions/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700842 .privileges(redfish::privileges::getPCIeFunction)
Ed Tanous002d39b2022-05-31 08:59:27 -0700843 .methods(boost::beast::http::verb::get)(
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600844 std::bind_front(handlePCIeFunctionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700845}
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -0800846
847} // namespace redfish