blob: 4ab2fd82bbee0453f322fd0a079258c8563eab76 [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 Tanous539d8c62024-06-19 14:38:27 -070021#include "generated/enums/resource.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080022#include "query.hpp"
23#include "registries/privilege_registry.hpp"
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -060024#include "utils/collection.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080025#include "utils/dbus_utils.hpp"
Lakshmi Yadlapatic49c3292023-04-19 16:42:35 -050026#include "utils/pcie_util.hpp"
Ed Tanous0ec8b832022-03-14 14:56:47 -070027
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -080028#include <boost/system/linux_error.hpp>
Ed Tanousef4c65b2023-04-24 15:28:50 -070029#include <boost/url/format.hpp>
Krzysztof Grobelnyd1bde9e2022-09-07 10:40:51 +020030#include <sdbusplus/asio/property.hpp>
31#include <sdbusplus/unpack_properties.hpp>
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -080032
Myung Bae8c1d0542024-03-12 17:50:48 -050033#include <limits>
34
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -080035namespace redfish
36{
37
Patrick Williams89492a12023-05-10 07:51:34 -050038static constexpr const char* inventoryPath = "/xyz/openbmc_project/inventory";
Lakshmi Yadlapati94c3a102023-04-05 18:11:22 -050039static constexpr std::array<std::string_view, 1> pcieDeviceInterface = {
40 "xyz.openbmc_project.Inventory.Item.PCIeDevice"};
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -050041static constexpr std::array<std::string_view, 1> pcieSlotInterface = {
42 "xyz.openbmc_project.Inventory.Item.PCIeSlot"};
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -080043
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060044static inline void handlePCIeDevicePath(
45 const std::string& pcieDeviceId,
Ed Tanousac106bf2023-06-07 09:24:59 -070046 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060047 const dbus::utility::MapperGetSubTreePathsResponse& pcieDevicePaths,
48 const std::function<void(const std::string& pcieDevicePath,
49 const std::string& service)>& callback)
50
51{
52 for (const std::string& pcieDevicePath : pcieDevicePaths)
53 {
54 std::string pciecDeviceName =
55 sdbusplus::message::object_path(pcieDevicePath).filename();
56 if (pciecDeviceName.empty() || pciecDeviceName != pcieDeviceId)
57 {
58 continue;
59 }
60
61 dbus::utility::getDbusObject(
62 pcieDevicePath, {},
Ed Tanousac106bf2023-06-07 09:24:59 -070063 [pcieDevicePath, asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060064 callback](const boost::system::error_code& ec,
65 const dbus::utility::MapperGetObject& object) {
66 if (ec || object.empty())
67 {
Ed Tanous62598e32023-07-17 17:06:25 -070068 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
Ed Tanousac106bf2023-06-07 09:24:59 -070069 messages::internalError(asyncResp->res);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060070 return;
71 }
72 callback(pcieDevicePath, object.begin()->first);
Patrick Williams5a39f772023-10-20 11:20:21 -050073 });
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060074 return;
75 }
76
Ed Tanous62598e32023-07-17 17:06:25 -070077 BMCWEB_LOG_WARNING("PCIe Device not found");
Ed Tanousac106bf2023-06-07 09:24:59 -070078 messages::resourceNotFound(asyncResp->res, "PCIeDevice", pcieDeviceId);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060079}
80
81static inline void getValidPCIeDevicePath(
82 const std::string& pcieDeviceId,
Ed Tanousac106bf2023-06-07 09:24:59 -070083 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060084 const std::function<void(const std::string& pcieDevicePath,
85 const std::string& service)>& callback)
86{
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060087 dbus::utility::getSubTreePaths(
Lakshmi Yadlapati94c3a102023-04-05 18:11:22 -050088 inventoryPath, 0, pcieDeviceInterface,
Ed Tanousac106bf2023-06-07 09:24:59 -070089 [pcieDeviceId, asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060090 callback](const boost::system::error_code& ec,
91 const dbus::utility::MapperGetSubTreePathsResponse&
92 pcieDevicePaths) {
93 if (ec)
94 {
Ed Tanous62598e32023-07-17 17:06:25 -070095 BMCWEB_LOG_ERROR("D-Bus response error on GetSubTree {}", ec);
Ed Tanousac106bf2023-06-07 09:24:59 -070096 messages::internalError(asyncResp->res);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060097 return;
98 }
Ed Tanousac106bf2023-06-07 09:24:59 -070099 handlePCIeDevicePath(pcieDeviceId, asyncResp, pcieDevicePaths,
100 callback);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600101 return;
Patrick Williams5a39f772023-10-20 11:20:21 -0500102 });
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600103}
104
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600105static inline void handlePCIeDeviceCollectionGet(
106 crow::App& app, const crow::Request& req,
Ed Tanousac106bf2023-06-07 09:24:59 -0700107 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600108 const std::string& systemName)
109{
Ed Tanousac106bf2023-06-07 09:24:59 -0700110 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600111 {
112 return;
113 }
Ed Tanous25b54db2024-04-17 15:40:31 -0700114 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800115 {
116 // Option currently returns no systems. TBD
117 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
118 systemName);
119 return;
120 }
Ed Tanous253f11b2024-05-16 09:38:31 -0700121 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600122 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700123 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
124 systemName);
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600125 return;
126 }
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600127
Ed Tanousac106bf2023-06-07 09:24:59 -0700128 asyncResp->res.addHeader(boost::beast::http::field::link,
129 "</redfish/v1/JsonSchemas/PCIeDeviceCollection/"
130 "PCIeDeviceCollection.json>; rel=describedby");
131 asyncResp->res.jsonValue["@odata.type"] =
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600132 "#PCIeDeviceCollection.PCIeDeviceCollection";
Ed Tanous253f11b2024-05-16 09:38:31 -0700133 asyncResp->res.jsonValue["@odata.id"] = std::format(
134 "/redfish/v1/Systems/{}/PCIeDevices", BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanousac106bf2023-06-07 09:24:59 -0700135 asyncResp->res.jsonValue["Name"] = "PCIe Device Collection";
136 asyncResp->res.jsonValue["Description"] = "Collection of PCIe Devices";
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600137
Lakshmi Yadlapati70c4d542023-06-08 04:37:18 -0500138 pcie_util::getPCIeDeviceList(asyncResp,
139 nlohmann::json::json_pointer("/Members"));
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600140}
141
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700142inline void requestRoutesSystemPCIeDeviceCollection(App& app)
Jason M. Billsadbe1922019-10-14 15:44:35 -0700143{
Jason M. Billsadbe1922019-10-14 15:44:35 -0700144 /**
145 * Functions triggers appropriate requests on DBus
146 */
Ed Tanous22d268c2022-05-19 09:39:07 -0700147 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/PCIeDevices/")
Ed Tanoused398212021-06-09 17:05:54 -0700148 .privileges(redfish::privileges::getPCIeDeviceCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700149 .methods(boost::beast::http::verb::get)(
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600150 std::bind_front(handlePCIeDeviceCollectionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700151}
152
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500153inline void addPCIeSlotProperties(
154 crow::Response& res, const boost::system::error_code& ec,
155 const dbus::utility::DBusPropertiesMap& pcieSlotProperties)
156{
157 if (ec)
158 {
Ed Tanous62598e32023-07-17 17:06:25 -0700159 BMCWEB_LOG_ERROR("DBUS response error for getAllProperties{}",
160 ec.value());
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500161 messages::internalError(res);
162 return;
163 }
164 std::string generation;
165 size_t lanes = 0;
166 std::string slotType;
167
168 bool success = sdbusplus::unpackPropertiesNoThrow(
169 dbus_utils::UnpackErrorPrinter(), pcieSlotProperties, "Generation",
170 generation, "Lanes", lanes, "SlotType", slotType);
171
172 if (!success)
173 {
174 messages::internalError(res);
175 return;
176 }
177
178 std::optional<pcie_device::PCIeTypes> pcieType =
179 pcie_util::redfishPcieGenerationFromDbus(generation);
180 if (!pcieType)
181 {
Ed Tanous62598e32023-07-17 17:06:25 -0700182 BMCWEB_LOG_WARNING("Unknown PCIeType: {}", generation);
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500183 }
184 else
185 {
186 if (*pcieType == pcie_device::PCIeTypes::Invalid)
187 {
Ed Tanous62598e32023-07-17 17:06:25 -0700188 BMCWEB_LOG_ERROR("Invalid PCIeType: {}", generation);
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500189 messages::internalError(res);
190 return;
191 }
192 res.jsonValue["Slot"]["PCIeType"] = *pcieType;
193 }
194
Konstantin Aladyshev82f80322023-07-10 15:00:38 +0300195 if (lanes != 0)
196 {
197 res.jsonValue["Slot"]["Lanes"] = lanes;
198 }
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500199
200 std::optional<pcie_slots::SlotTypes> redfishSlotType =
201 pcie_util::dbusSlotTypeToRf(slotType);
202 if (!redfishSlotType)
203 {
Ed Tanous62598e32023-07-17 17:06:25 -0700204 BMCWEB_LOG_WARNING("Unknown PCIeSlot Type: {}", slotType);
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500205 }
206 else
207 {
208 if (*redfishSlotType == pcie_slots::SlotTypes::Invalid)
209 {
Ed Tanous62598e32023-07-17 17:06:25 -0700210 BMCWEB_LOG_ERROR("Invalid PCIeSlot type: {}", slotType);
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500211 messages::internalError(res);
212 return;
213 }
214 res.jsonValue["Slot"]["SlotType"] = *redfishSlotType;
215 }
216}
217
218inline void getPCIeDeviceSlotPath(
219 const std::string& pcieDevicePath,
220 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
221 std::function<void(const std::string& pcieDeviceSlot)>&& callback)
222{
223 std::string associationPath = pcieDevicePath + "/contained_by";
224 dbus::utility::getAssociatedSubTreePaths(
225 associationPath, sdbusplus::message::object_path(inventoryPath), 0,
226 pcieSlotInterface,
Ed Tanous8cb2c022024-03-27 16:31:46 -0700227 [callback = std::move(callback), asyncResp, pcieDevicePath](
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500228 const boost::system::error_code& ec,
229 const dbus::utility::MapperGetSubTreePathsResponse& endpoints) {
230 if (ec)
231 {
232 if (ec.value() == EBADR)
233 {
234 // Missing association is not an error
235 return;
236 }
Ed Tanous62598e32023-07-17 17:06:25 -0700237 BMCWEB_LOG_ERROR(
238 "DBUS response error for getAssociatedSubTreePaths {}",
239 ec.value());
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500240 messages::internalError(asyncResp->res);
241 return;
242 }
243 if (endpoints.size() > 1)
244 {
Ed Tanous62598e32023-07-17 17:06:25 -0700245 BMCWEB_LOG_ERROR(
246 "PCIeDevice is associated with more than one PCIeSlot: {}",
247 endpoints.size());
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500248 messages::internalError(asyncResp->res);
249 return;
250 }
251 if (endpoints.empty())
252 {
253 // If the device doesn't have an association, return without PCIe
254 // Slot properties
Ed Tanous62598e32023-07-17 17:06:25 -0700255 BMCWEB_LOG_DEBUG("PCIeDevice is not associated with PCIeSlot");
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500256 return;
257 }
258 callback(endpoints[0]);
Patrick Williams5a39f772023-10-20 11:20:21 -0500259 });
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500260}
261
262inline void
263 afterGetDbusObject(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
264 const std::string& pcieDeviceSlot,
265 const boost::system::error_code& ec,
266 const dbus::utility::MapperGetObject& object)
267{
268 if (ec || object.empty())
269 {
Ed Tanous62598e32023-07-17 17:06:25 -0700270 BMCWEB_LOG_ERROR("DBUS response error for getDbusObject {}",
271 ec.value());
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500272 messages::internalError(asyncResp->res);
273 return;
274 }
275 sdbusplus::asio::getAllProperties(
276 *crow::connections::systemBus, object.begin()->first, pcieDeviceSlot,
277 "xyz.openbmc_project.Inventory.Item.PCIeSlot",
278 [asyncResp](
279 const boost::system::error_code& ec2,
280 const dbus::utility::DBusPropertiesMap& pcieSlotProperties) {
281 addPCIeSlotProperties(asyncResp->res, ec2, pcieSlotProperties);
Patrick Williams5a39f772023-10-20 11:20:21 -0500282 });
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500283}
284
285inline void afterGetPCIeDeviceSlotPath(
286 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
287 const std::string& pcieDeviceSlot)
288{
289 dbus::utility::getDbusObject(
290 pcieDeviceSlot, pcieSlotInterface,
291 [asyncResp,
292 pcieDeviceSlot](const boost::system::error_code& ec,
293 const dbus::utility::MapperGetObject& object) {
294 afterGetDbusObject(asyncResp, pcieDeviceSlot, ec, object);
Patrick Williams5a39f772023-10-20 11:20:21 -0500295 });
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500296}
297
Ed Tanousac106bf2023-06-07 09:24:59 -0700298inline void
Lakshmi Yadlapatie164f1b2023-04-12 17:01:34 -0500299 getPCIeDeviceHealth(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
300 const std::string& pcieDevicePath,
301 const std::string& service)
302{
303 sdbusplus::asio::getProperty<bool>(
304 *crow::connections::systemBus, service, pcieDevicePath,
305 "xyz.openbmc_project.State.Decorator.OperationalStatus", "Functional",
306 [asyncResp](const boost::system::error_code& ec, const bool value) {
307 if (ec)
308 {
309 if (ec.value() != EBADR)
310 {
Ed Tanous62598e32023-07-17 17:06:25 -0700311 BMCWEB_LOG_ERROR("DBUS response error for Health {}",
312 ec.value());
Lakshmi Yadlapatie164f1b2023-04-12 17:01:34 -0500313 messages::internalError(asyncResp->res);
314 }
315 return;
316 }
317
318 if (!value)
319 {
Ed Tanous539d8c62024-06-19 14:38:27 -0700320 asyncResp->res.jsonValue["Status"]["Health"] =
321 resource::Health::Critical;
Lakshmi Yadlapatie164f1b2023-04-12 17:01:34 -0500322 }
Patrick Williams5a39f772023-10-20 11:20:21 -0500323 });
Lakshmi Yadlapatie164f1b2023-04-12 17:01:34 -0500324}
325
326inline void
Ed Tanousac106bf2023-06-07 09:24:59 -0700327 getPCIeDeviceState(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
328 const std::string& pcieDevicePath,
329 const std::string& service)
Lakshmi Yadlapatic6bb3282023-04-12 16:56:49 -0500330{
331 sdbusplus::asio::getProperty<bool>(
332 *crow::connections::systemBus, service, pcieDevicePath,
333 "xyz.openbmc_project.Inventory.Item", "Present",
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500334 [asyncResp](const boost::system::error_code& ec, bool value) {
Lakshmi Yadlapatic6bb3282023-04-12 16:56:49 -0500335 if (ec)
336 {
337 if (ec.value() != EBADR)
338 {
Ed Tanous62598e32023-07-17 17:06:25 -0700339 BMCWEB_LOG_ERROR("DBUS response error for State");
Ed Tanousac106bf2023-06-07 09:24:59 -0700340 messages::internalError(asyncResp->res);
Lakshmi Yadlapatic6bb3282023-04-12 16:56:49 -0500341 }
342 return;
343 }
344
345 if (!value)
346 {
Ed Tanous539d8c62024-06-19 14:38:27 -0700347 asyncResp->res.jsonValue["Status"]["State"] =
348 resource::State::Absent;
Lakshmi Yadlapatic6bb3282023-04-12 16:56:49 -0500349 }
Patrick Williams5a39f772023-10-20 11:20:21 -0500350 });
Lakshmi Yadlapatic6bb3282023-04-12 16:56:49 -0500351}
352
Ed Tanousac106bf2023-06-07 09:24:59 -0700353inline void
354 getPCIeDeviceAsset(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
355 const std::string& pcieDevicePath,
356 const std::string& service)
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600357{
358 sdbusplus::asio::getAllProperties(
359 *crow::connections::systemBus, service, pcieDevicePath,
360 "xyz.openbmc_project.Inventory.Decorator.Asset",
Ed Tanousac106bf2023-06-07 09:24:59 -0700361 [pcieDevicePath, asyncResp{asyncResp}](
362 const boost::system::error_code& ec,
363 const dbus::utility::DBusPropertiesMap& assetList) {
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600364 if (ec)
365 {
366 if (ec.value() != EBADR)
367 {
Ed Tanous62598e32023-07-17 17:06:25 -0700368 BMCWEB_LOG_ERROR("DBUS response error for Properties{}",
369 ec.value());
Ed Tanousac106bf2023-06-07 09:24:59 -0700370 messages::internalError(asyncResp->res);
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600371 }
372 return;
373 }
374
375 const std::string* manufacturer = nullptr;
376 const std::string* model = nullptr;
377 const std::string* partNumber = nullptr;
378 const std::string* serialNumber = nullptr;
379 const std::string* sparePartNumber = nullptr;
380
381 const bool success = sdbusplus::unpackPropertiesNoThrow(
382 dbus_utils::UnpackErrorPrinter(), assetList, "Manufacturer",
383 manufacturer, "Model", model, "PartNumber", partNumber,
384 "SerialNumber", serialNumber, "SparePartNumber", sparePartNumber);
385
386 if (!success)
387 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700388 messages::internalError(asyncResp->res);
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600389 return;
390 }
391
392 if (manufacturer != nullptr)
393 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700394 asyncResp->res.jsonValue["Manufacturer"] = *manufacturer;
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600395 }
396 if (model != nullptr)
397 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700398 asyncResp->res.jsonValue["Model"] = *model;
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600399 }
400
401 if (partNumber != nullptr)
402 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700403 asyncResp->res.jsonValue["PartNumber"] = *partNumber;
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600404 }
405
406 if (serialNumber != nullptr)
407 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700408 asyncResp->res.jsonValue["SerialNumber"] = *serialNumber;
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600409 }
410
411 if (sparePartNumber != nullptr && !sparePartNumber->empty())
412 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700413 asyncResp->res.jsonValue["SparePartNumber"] = *sparePartNumber;
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600414 }
Patrick Williams5a39f772023-10-20 11:20:21 -0500415 });
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600416}
417
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600418inline void addPCIeDeviceProperties(
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500419 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
420 const std::string& pcieDeviceId,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600421 const dbus::utility::DBusPropertiesMap& pcieDevProperties)
422{
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600423 const std::string* generationInUse = nullptr;
Konstantin Aladyshev814bf202023-07-04 16:30:10 +0300424 const std::string* generationSupported = nullptr;
Konstantin Aladyshev9bb0a7f2023-07-04 12:59:34 +0300425 const size_t* lanesInUse = nullptr;
Konstantin Aladyshev814bf202023-07-04 16:30:10 +0300426 const size_t* maxLanes = nullptr;
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600427
428 const bool success = sdbusplus::unpackPropertiesNoThrow(
Ed Tanous609ba4c2023-07-11 09:14:24 -0700429 dbus_utils::UnpackErrorPrinter(), pcieDevProperties, "GenerationInUse",
430 generationInUse, "GenerationSupported", generationSupported,
431 "LanesInUse", lanesInUse, "MaxLanes", maxLanes);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600432
433 if (!success)
434 {
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500435 messages::internalError(asyncResp->res);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600436 return;
437 }
438
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600439 if (generationInUse != nullptr)
440 {
441 std::optional<pcie_device::PCIeTypes> redfishGenerationInUse =
Lakshmi Yadlapatic49c3292023-04-19 16:42:35 -0500442 pcie_util::redfishPcieGenerationFromDbus(*generationInUse);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600443
444 if (!redfishGenerationInUse)
445 {
Ed Tanous62598e32023-07-17 17:06:25 -0700446 BMCWEB_LOG_WARNING("Unknown PCIe Device Generation: {}",
447 *generationInUse);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600448 }
Lakshmi Yadlapaticf3b4842023-06-27 02:36:53 -0500449 else
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600450 {
Lakshmi Yadlapaticf3b4842023-06-27 02:36:53 -0500451 if (*redfishGenerationInUse == pcie_device::PCIeTypes::Invalid)
452 {
Ed Tanous62598e32023-07-17 17:06:25 -0700453 BMCWEB_LOG_ERROR("Invalid PCIe Device Generation: {}",
454 *generationInUse);
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500455 messages::internalError(asyncResp->res);
Lakshmi Yadlapaticf3b4842023-06-27 02:36:53 -0500456 return;
457 }
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500458 asyncResp->res.jsonValue["PCIeInterface"]["PCIeType"] =
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600459 *redfishGenerationInUse;
460 }
461 }
462
Konstantin Aladyshev814bf202023-07-04 16:30:10 +0300463 if (generationSupported != nullptr)
464 {
465 std::optional<pcie_device::PCIeTypes> redfishGenerationSupported =
466 pcie_util::redfishPcieGenerationFromDbus(*generationSupported);
467
468 if (!redfishGenerationSupported)
469 {
Ed Tanous62598e32023-07-17 17:06:25 -0700470 BMCWEB_LOG_WARNING("Unknown PCIe Device Generation: {}",
471 *generationSupported);
Konstantin Aladyshev814bf202023-07-04 16:30:10 +0300472 }
473 else
474 {
475 if (*redfishGenerationSupported == pcie_device::PCIeTypes::Invalid)
476 {
Ed Tanous62598e32023-07-17 17:06:25 -0700477 BMCWEB_LOG_ERROR("Invalid PCIe Device Generation: {}",
478 *generationSupported);
Konstantin Aladyshev814bf202023-07-04 16:30:10 +0300479 messages::internalError(asyncResp->res);
480 return;
481 }
482 asyncResp->res.jsonValue["PCIeInterface"]["MaxPCIeType"] =
483 *redfishGenerationSupported;
484 }
485 }
486
Myung Bae8c1d0542024-03-12 17:50:48 -0500487 if (lanesInUse != nullptr)
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600488 {
Myung Bae8c1d0542024-03-12 17:50:48 -0500489 if (*lanesInUse == std::numeric_limits<size_t>::max())
490 {
491 // The default value of LanesInUse is "maxint", and the field will
492 // be null if it is a default value.
493 asyncResp->res.jsonValue["PCIeInterface"]["LanesInUse"] = nullptr;
494 }
495 else
496 {
497 asyncResp->res.jsonValue["PCIeInterface"]["LanesInUse"] =
498 *lanesInUse;
499 }
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600500 }
Konstantin Aladyshev814bf202023-07-04 16:30:10 +0300501 // The default value of MaxLanes is 0, and the field will be
502 // left as off if it is a default value.
503 if (maxLanes != nullptr && *maxLanes != 0)
504 {
505 asyncResp->res.jsonValue["PCIeInterface"]["MaxLanes"] = *maxLanes;
506 }
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600507
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500508 asyncResp->res.jsonValue["PCIeFunctions"]["@odata.id"] =
509 boost::urls::format(
Ed Tanous253f11b2024-05-16 09:38:31 -0700510 "/redfish/v1/Systems/{}/PCIeDevices/{}/PCIeFunctions",
511 BMCWEB_REDFISH_SYSTEM_URI_NAME, pcieDeviceId);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600512}
513
514inline void getPCIeDeviceProperties(
Ed Tanousac106bf2023-06-07 09:24:59 -0700515 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600516 const std::string& pcieDevicePath, const std::string& service,
517 const std::function<void(
518 const dbus::utility::DBusPropertiesMap& pcieDevProperties)>&& callback)
519{
520 sdbusplus::asio::getAllProperties(
521 *crow::connections::systemBus, service, pcieDevicePath,
522 "xyz.openbmc_project.Inventory.Item.PCIeDevice",
Ed Tanousac106bf2023-06-07 09:24:59 -0700523 [asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600524 callback](const boost::system::error_code& ec,
525 const dbus::utility::DBusPropertiesMap& pcieDevProperties) {
526 if (ec)
527 {
528 if (ec.value() != EBADR)
529 {
Ed Tanous62598e32023-07-17 17:06:25 -0700530 BMCWEB_LOG_ERROR("DBUS response error for Properties");
Ed Tanousac106bf2023-06-07 09:24:59 -0700531 messages::internalError(asyncResp->res);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600532 }
533 return;
534 }
535 callback(pcieDevProperties);
Patrick Williams5a39f772023-10-20 11:20:21 -0500536 });
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600537}
538
539inline void addPCIeDeviceCommonProperties(
Ed Tanousac106bf2023-06-07 09:24:59 -0700540 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600541 const std::string& pcieDeviceId)
542{
Ed Tanousac106bf2023-06-07 09:24:59 -0700543 asyncResp->res.addHeader(
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600544 boost::beast::http::field::link,
545 "</redfish/v1/JsonSchemas/PCIeDevice/PCIeDevice.json>; rel=describedby");
Ed Tanousac106bf2023-06-07 09:24:59 -0700546 asyncResp->res.jsonValue["@odata.type"] = "#PCIeDevice.v1_9_0.PCIeDevice";
Ed Tanous253f11b2024-05-16 09:38:31 -0700547 asyncResp->res.jsonValue["@odata.id"] =
548 boost::urls::format("/redfish/v1/Systems/{}/PCIeDevices/{}",
549 BMCWEB_REDFISH_SYSTEM_URI_NAME, pcieDeviceId);
Ed Tanousac106bf2023-06-07 09:24:59 -0700550 asyncResp->res.jsonValue["Name"] = "PCIe Device";
551 asyncResp->res.jsonValue["Id"] = pcieDeviceId;
Ed Tanous539d8c62024-06-19 14:38:27 -0700552 asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled;
553 asyncResp->res.jsonValue["Status"]["Health"] = resource::Health::OK;
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600554}
555
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500556inline void afterGetValidPcieDevicePath(
557 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
558 const std::string& pcieDeviceId, const std::string& pcieDevicePath,
559 const std::string& service)
560{
561 addPCIeDeviceCommonProperties(asyncResp, pcieDeviceId);
562 getPCIeDeviceAsset(asyncResp, pcieDevicePath, service);
563 getPCIeDeviceState(asyncResp, pcieDevicePath, service);
564 getPCIeDeviceHealth(asyncResp, pcieDevicePath, service);
565 getPCIeDeviceProperties(
566 asyncResp, pcieDevicePath, service,
567 std::bind_front(addPCIeDeviceProperties, asyncResp, pcieDeviceId));
568 getPCIeDeviceSlotPath(
569 pcieDevicePath, asyncResp,
570 std::bind_front(afterGetPCIeDeviceSlotPath, asyncResp));
571}
572
Ed Tanousac106bf2023-06-07 09:24:59 -0700573inline void
574 handlePCIeDeviceGet(App& app, const crow::Request& req,
575 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
576 const std::string& systemName,
577 const std::string& pcieDeviceId)
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600578{
Ed Tanousac106bf2023-06-07 09:24:59 -0700579 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600580 {
581 return;
582 }
Ed Tanous25b54db2024-04-17 15:40:31 -0700583 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800584 {
585 // Option currently returns no systems. TBD
586 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
587 systemName);
588 return;
589 }
Ed Tanous253f11b2024-05-16 09:38:31 -0700590 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600591 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700592 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
593 systemName);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600594 return;
595 }
596
597 getValidPCIeDevicePath(
Ed Tanousac106bf2023-06-07 09:24:59 -0700598 pcieDeviceId, asyncResp,
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500599 std::bind_front(afterGetValidPcieDevicePath, asyncResp, pcieDeviceId));
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600600}
601
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700602inline void requestRoutesSystemPCIeDevice(App& app)
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -0800603{
Ed Tanous22d268c2022-05-19 09:39:07 -0700604 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/PCIeDevices/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700605 .privileges(redfish::privileges::getPCIeDevice)
Ed Tanous002d39b2022-05-31 08:59:27 -0700606 .methods(boost::beast::http::verb::get)(
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600607 std::bind_front(handlePCIeDeviceGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700608}
609
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600610inline void addPCIeFunctionList(
611 crow::Response& res, const std::string& pcieDeviceId,
612 const dbus::utility::DBusPropertiesMap& pcieDevProperties)
613{
614 nlohmann::json& pcieFunctionList = res.jsonValue["Members"];
615 pcieFunctionList = nlohmann::json::array();
616 static constexpr const int maxPciFunctionNum = 8;
617
618 for (int functionNum = 0; functionNum < maxPciFunctionNum; functionNum++)
619 {
620 // Check if this function exists by
621 // looking for a device ID
Patrick Williams89492a12023-05-10 07:51:34 -0500622 std::string devIDProperty = "Function" + std::to_string(functionNum) +
623 "DeviceId";
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600624 const std::string* property = nullptr;
625 for (const auto& propEntry : pcieDevProperties)
626 {
627 if (propEntry.first == devIDProperty)
628 {
629 property = std::get_if<std::string>(&propEntry.second);
630 break;
631 }
632 }
633 if (property == nullptr || property->empty())
634 {
635 continue;
636 }
637
638 nlohmann::json::object_t pcieFunction;
Ed Tanousef4c65b2023-04-24 15:28:50 -0700639 pcieFunction["@odata.id"] = boost::urls::format(
Ed Tanous253f11b2024-05-16 09:38:31 -0700640 "/redfish/v1/Systems/{}/PCIeDevices/{}/PCIeFunctions/{}",
641 BMCWEB_REDFISH_SYSTEM_URI_NAME, pcieDeviceId,
642 std::to_string(functionNum));
Patrick Williamsb2ba3072023-05-12 10:27:39 -0500643 pcieFunctionList.emplace_back(std::move(pcieFunction));
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600644 }
645 res.jsonValue["PCIeFunctions@odata.count"] = pcieFunctionList.size();
646}
647
648inline void handlePCIeFunctionCollectionGet(
649 App& app, const crow::Request& req,
Ed Tanousac106bf2023-06-07 09:24:59 -0700650 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800651 const std::string& systemName, const std::string& pcieDeviceId)
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600652{
Ed Tanousac106bf2023-06-07 09:24:59 -0700653 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600654 {
655 return;
656 }
Ed Tanous25b54db2024-04-17 15:40:31 -0700657 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800658 {
659 // Option currently returns no systems. TBD
660 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
661 systemName);
662 return;
663 }
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600664
665 getValidPCIeDevicePath(
Ed Tanousac106bf2023-06-07 09:24:59 -0700666 pcieDeviceId, asyncResp,
667 [asyncResp, pcieDeviceId](const std::string& pcieDevicePath,
668 const std::string& service) {
669 asyncResp->res.addHeader(
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600670 boost::beast::http::field::link,
671 "</redfish/v1/JsonSchemas/PCIeFunctionCollection/PCIeFunctionCollection.json>; rel=describedby");
Ed Tanousac106bf2023-06-07 09:24:59 -0700672 asyncResp->res.jsonValue["@odata.type"] =
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600673 "#PCIeFunctionCollection.PCIeFunctionCollection";
Ed Tanousac106bf2023-06-07 09:24:59 -0700674 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
Ed Tanous253f11b2024-05-16 09:38:31 -0700675 "/redfish/v1/Systems/{}/PCIeDevices/{}/PCIeFunctions",
676 BMCWEB_REDFISH_SYSTEM_URI_NAME, pcieDeviceId);
Ed Tanousac106bf2023-06-07 09:24:59 -0700677 asyncResp->res.jsonValue["Name"] = "PCIe Function Collection";
678 asyncResp->res.jsonValue["Description"] =
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600679 "Collection of PCIe Functions for PCIe Device " + pcieDeviceId;
680 getPCIeDeviceProperties(
Ed Tanousac106bf2023-06-07 09:24:59 -0700681 asyncResp, pcieDevicePath, service,
682 [asyncResp, pcieDeviceId](
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600683 const dbus::utility::DBusPropertiesMap& pcieDevProperties) {
Ed Tanousac106bf2023-06-07 09:24:59 -0700684 addPCIeFunctionList(asyncResp->res, pcieDeviceId,
685 pcieDevProperties);
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600686 });
Patrick Williams5a39f772023-10-20 11:20:21 -0500687 });
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600688}
689
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700690inline void requestRoutesSystemPCIeFunctionCollection(App& app)
691{
692 /**
693 * Functions triggers appropriate requests on DBus
694 */
695 BMCWEB_ROUTE(app,
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800696 "/redfish/v1/Systems/<str>/PCIeDevices/<str>/PCIeFunctions/")
Ed Tanoused398212021-06-09 17:05:54 -0700697 .privileges(redfish::privileges::getPCIeFunctionCollection)
Ed Tanous002d39b2022-05-31 08:59:27 -0700698 .methods(boost::beast::http::verb::get)(
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600699 std::bind_front(handlePCIeFunctionCollectionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700700}
701
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600702inline bool validatePCIeFunctionId(
Myung Baed5e74b82023-05-31 11:28:02 -0500703 uint64_t pcieFunctionId,
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600704 const dbus::utility::DBusPropertiesMap& pcieDevProperties)
705{
Myung Baed5e74b82023-05-31 11:28:02 -0500706 std::string functionName = "Function" + std::to_string(pcieFunctionId);
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600707 std::string devIDProperty = functionName + "DeviceId";
708
709 const std::string* devIdProperty = nullptr;
710 for (const auto& property : pcieDevProperties)
711 {
712 if (property.first == devIDProperty)
713 {
714 devIdProperty = std::get_if<std::string>(&property.second);
715 break;
716 }
717 }
718 return (devIdProperty != nullptr && !devIdProperty->empty());
719}
720
721inline void addPCIeFunctionProperties(
Ed Tanouse14742c2023-05-31 10:27:49 -0700722 crow::Response& resp, uint64_t pcieFunctionId,
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600723 const dbus::utility::DBusPropertiesMap& pcieDevProperties)
724{
Ed Tanouse14742c2023-05-31 10:27:49 -0700725 std::string functionName = "Function" + std::to_string(pcieFunctionId);
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600726 for (const auto& property : pcieDevProperties)
727 {
728 const std::string* strProperty =
729 std::get_if<std::string>(&property.second);
Ed Tanousdc8cfa62024-04-07 13:37:25 -0700730 if (strProperty == nullptr)
731 {
732 BMCWEB_LOG_ERROR("Function wasn't a string?");
733 continue;
734 }
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600735 if (property.first == functionName + "DeviceId")
736 {
737 resp.jsonValue["DeviceId"] = *strProperty;
738 }
739 if (property.first == functionName + "VendorId")
740 {
741 resp.jsonValue["VendorId"] = *strProperty;
742 }
743 // TODO: FunctionType and DeviceClass are Redfish enums. The D-Bus
744 // property strings should be mapped correctly to ensure these
745 // strings are Redfish enum values. For now just check for empty.
746 if (property.first == functionName + "FunctionType")
747 {
748 if (!strProperty->empty())
749 {
750 resp.jsonValue["FunctionType"] = *strProperty;
751 }
752 }
753 if (property.first == functionName + "DeviceClass")
754 {
755 if (!strProperty->empty())
756 {
757 resp.jsonValue["DeviceClass"] = *strProperty;
758 }
759 }
760 if (property.first == functionName + "ClassCode")
761 {
762 resp.jsonValue["ClassCode"] = *strProperty;
763 }
764 if (property.first == functionName + "RevisionId")
765 {
766 resp.jsonValue["RevisionId"] = *strProperty;
767 }
768 if (property.first == functionName + "SubsystemId")
769 {
770 resp.jsonValue["SubsystemId"] = *strProperty;
771 }
772 if (property.first == functionName + "SubsystemVendorId")
773 {
774 resp.jsonValue["SubsystemVendorId"] = *strProperty;
775 }
776 }
777}
778
779inline void addPCIeFunctionCommonProperties(crow::Response& resp,
780 const std::string& pcieDeviceId,
Ed Tanouse14742c2023-05-31 10:27:49 -0700781 uint64_t pcieFunctionId)
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600782{
783 resp.addHeader(
784 boost::beast::http::field::link,
785 "</redfish/v1/JsonSchemas/PCIeFunction/PCIeFunction.json>; rel=describedby");
786 resp.jsonValue["@odata.type"] = "#PCIeFunction.v1_2_3.PCIeFunction";
Ed Tanousef4c65b2023-04-24 15:28:50 -0700787 resp.jsonValue["@odata.id"] = boost::urls::format(
Ed Tanous253f11b2024-05-16 09:38:31 -0700788 "/redfish/v1/Systems/{}/PCIeDevices/{}/PCIeFunctions/{}",
789 BMCWEB_REDFISH_SYSTEM_URI_NAME, pcieDeviceId,
790 std::to_string(pcieFunctionId));
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600791 resp.jsonValue["Name"] = "PCIe Function";
Ed Tanouse14742c2023-05-31 10:27:49 -0700792 resp.jsonValue["Id"] = std::to_string(pcieFunctionId);
793 resp.jsonValue["FunctionId"] = pcieFunctionId;
Ed Tanous253f11b2024-05-16 09:38:31 -0700794 resp.jsonValue["Links"]["PCIeDevice"]["@odata.id"] =
795 boost::urls::format("/redfish/v1/Systems/{}/PCIeDevices/{}",
796 BMCWEB_REDFISH_SYSTEM_URI_NAME, pcieDeviceId);
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600797}
798
799inline void
800 handlePCIeFunctionGet(App& app, const crow::Request& req,
Ed Tanousac106bf2023-06-07 09:24:59 -0700801 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800802 const std::string& systemName,
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600803 const std::string& pcieDeviceId,
Ed Tanouse14742c2023-05-31 10:27:49 -0700804 const std::string& pcieFunctionIdStr)
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600805{
Ed Tanousac106bf2023-06-07 09:24:59 -0700806 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600807 {
808 return;
809 }
Ed Tanous25b54db2024-04-17 15:40:31 -0700810 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800811 {
812 // Option currently returns no systems. TBD
813 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
814 systemName);
815 return;
816 }
Ed Tanous253f11b2024-05-16 09:38:31 -0700817 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800818 {
819 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
820 systemName);
821 return;
822 }
Ed Tanousdc8cfa62024-04-07 13:37:25 -0700823 std::string_view pcieFunctionIdView = pcieFunctionIdStr;
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800824
Ed Tanouse14742c2023-05-31 10:27:49 -0700825 uint64_t pcieFunctionId = 0;
826 std::from_chars_result result = std::from_chars(
Ed Tanousdc8cfa62024-04-07 13:37:25 -0700827 pcieFunctionIdView.begin(), pcieFunctionIdView.end(), pcieFunctionId);
828 if (result.ec != std::errc{} || result.ptr != pcieFunctionIdView.end())
Ed Tanouse14742c2023-05-31 10:27:49 -0700829 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700830 messages::resourceNotFound(asyncResp->res, "PCIeFunction",
Ed Tanouse14742c2023-05-31 10:27:49 -0700831 pcieFunctionIdStr);
832 return;
833 }
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600834
Ed Tanousac106bf2023-06-07 09:24:59 -0700835 getValidPCIeDevicePath(pcieDeviceId, asyncResp,
836 [asyncResp, pcieDeviceId,
837 pcieFunctionId](const std::string& pcieDevicePath,
838 const std::string& service) {
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600839 getPCIeDeviceProperties(
Ed Tanousac106bf2023-06-07 09:24:59 -0700840 asyncResp, pcieDevicePath, service,
841 [asyncResp, pcieDeviceId, pcieFunctionId](
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600842 const dbus::utility::DBusPropertiesMap& pcieDevProperties) {
Ed Tanousac106bf2023-06-07 09:24:59 -0700843 addPCIeFunctionCommonProperties(asyncResp->res, pcieDeviceId,
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600844 pcieFunctionId);
Ed Tanousac106bf2023-06-07 09:24:59 -0700845 addPCIeFunctionProperties(asyncResp->res, pcieFunctionId,
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600846 pcieDevProperties);
Patrick Williams5a39f772023-10-20 11:20:21 -0500847 });
Ed Tanousac106bf2023-06-07 09:24:59 -0700848 });
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600849}
850
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700851inline void requestRoutesSystemPCIeFunction(App& app)
852{
853 BMCWEB_ROUTE(
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800854 app, "/redfish/v1/Systems/<str>/PCIeDevices/<str>/PCIeFunctions/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700855 .privileges(redfish::privileges::getPCIeFunction)
Ed Tanous002d39b2022-05-31 08:59:27 -0700856 .methods(boost::beast::http::verb::get)(
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600857 std::bind_front(handlePCIeFunctionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700858}
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -0800859
860} // namespace redfish