blob: 090fb952a4576ffc12a9414df0aa187939bd87f3 [file] [log] [blame]
Ed Tanous40e9b922024-09-10 13:50:16 -07001// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright OpenBMC Authors
3// SPDX-FileCopyrightText: Copyright 2018 Intel Corporation
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -08004
5#pragma once
6
Ed Tanousd7857202025-01-28 15:32:26 -08007#include "bmcweb_config.h"
8
Ed Tanous3ccb3ad2023-01-13 17:40:03 -08009#include "app.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -080010#include "async_resp.hpp"
George Liu7a1dbc42022-12-07 16:03:22 +080011#include "dbus_utility.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -080012#include "error_messages.hpp"
13#include "generated/enums/pcie_device.hpp"
14#include "generated/enums/pcie_slots.hpp"
Ed Tanous539d8c62024-06-19 14:38:27 -070015#include "generated/enums/resource.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -080016#include "http_request.hpp"
17#include "logging.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080018#include "query.hpp"
19#include "registries/privilege_registry.hpp"
20#include "utils/dbus_utils.hpp"
Lakshmi Yadlapatic49c3292023-04-19 16:42:35 -050021#include "utils/pcie_util.hpp"
Ed Tanous0ec8b832022-03-14 14:56:47 -070022
Ed Tanousd7857202025-01-28 15:32:26 -080023#include <asm-generic/errno.h>
24
25#include <boost/beast/http/field.hpp>
26#include <boost/beast/http/verb.hpp>
Ed Tanousef4c65b2023-04-24 15:28:50 -070027#include <boost/url/format.hpp>
Krzysztof Grobelnyd1bde9e2022-09-07 10:40:51 +020028#include <sdbusplus/unpack_properties.hpp>
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -080029
Ed Tanousd7857202025-01-28 15:32:26 -080030#include <array>
31#include <charconv>
32#include <cstddef>
33#include <cstdint>
34#include <format>
35#include <functional>
Myung Bae8c1d0542024-03-12 17:50:48 -050036#include <limits>
Ed Tanousd7857202025-01-28 15:32:26 -080037#include <memory>
38#include <optional>
39#include <string>
40#include <string_view>
41#include <system_error>
42#include <utility>
43#include <variant>
Myung Bae8c1d0542024-03-12 17:50:48 -050044
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -080045namespace redfish
46{
47
Patrick Williams89492a12023-05-10 07:51:34 -050048static constexpr const char* inventoryPath = "/xyz/openbmc_project/inventory";
Lakshmi Yadlapati94c3a102023-04-05 18:11:22 -050049static constexpr std::array<std::string_view, 1> pcieDeviceInterface = {
50 "xyz.openbmc_project.Inventory.Item.PCIeDevice"};
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -050051static constexpr std::array<std::string_view, 1> pcieSlotInterface = {
52 "xyz.openbmc_project.Inventory.Item.PCIeSlot"};
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -080053
Ed Tanous4ff0f1f2024-09-04 17:27:37 -070054inline void handlePCIeDevicePath(
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060055 const std::string& pcieDeviceId,
Ed Tanousac106bf2023-06-07 09:24:59 -070056 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060057 const dbus::utility::MapperGetSubTreePathsResponse& pcieDevicePaths,
58 const std::function<void(const std::string& pcieDevicePath,
59 const std::string& service)>& callback)
60
61{
62 for (const std::string& pcieDevicePath : pcieDevicePaths)
63 {
64 std::string pciecDeviceName =
65 sdbusplus::message::object_path(pcieDevicePath).filename();
66 if (pciecDeviceName.empty() || pciecDeviceName != pcieDeviceId)
67 {
68 continue;
69 }
70
71 dbus::utility::getDbusObject(
Konstantin Aladyshev3a58c5a2024-08-05 12:57:13 +030072 pcieDevicePath, pcieDeviceInterface,
Ed Tanousac106bf2023-06-07 09:24:59 -070073 [pcieDevicePath, asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060074 callback](const boost::system::error_code& ec,
75 const dbus::utility::MapperGetObject& object) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -040076 if (ec || object.empty())
77 {
78 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
79 messages::internalError(asyncResp->res);
80 return;
81 }
82 callback(pcieDevicePath, object.begin()->first);
83 });
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060084 return;
85 }
86
Ed Tanous62598e32023-07-17 17:06:25 -070087 BMCWEB_LOG_WARNING("PCIe Device not found");
Ed Tanousac106bf2023-06-07 09:24:59 -070088 messages::resourceNotFound(asyncResp->res, "PCIeDevice", pcieDeviceId);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060089}
90
Ed Tanous4ff0f1f2024-09-04 17:27:37 -070091inline void getValidPCIeDevicePath(
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060092 const std::string& pcieDeviceId,
Ed Tanousac106bf2023-06-07 09:24:59 -070093 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060094 const std::function<void(const std::string& pcieDevicePath,
95 const std::string& service)>& callback)
96{
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060097 dbus::utility::getSubTreePaths(
Lakshmi Yadlapati94c3a102023-04-05 18:11:22 -050098 inventoryPath, 0, pcieDeviceInterface,
Ed Tanousac106bf2023-06-07 09:24:59 -070099 [pcieDeviceId, asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600100 callback](const boost::system::error_code& ec,
101 const dbus::utility::MapperGetSubTreePathsResponse&
102 pcieDevicePaths) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400103 if (ec)
104 {
105 BMCWEB_LOG_ERROR("D-Bus response error on GetSubTree {}", ec);
106 messages::internalError(asyncResp->res);
107 return;
108 }
109 handlePCIeDevicePath(pcieDeviceId, asyncResp, pcieDevicePaths,
110 callback);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600111 return;
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400112 });
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600113}
114
Ed Tanous4ff0f1f2024-09-04 17:27:37 -0700115inline void handlePCIeDeviceCollectionGet(
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600116 crow::App& app, const crow::Request& req,
Ed Tanousac106bf2023-06-07 09:24:59 -0700117 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600118 const std::string& systemName)
119{
Ed Tanousac106bf2023-06-07 09:24:59 -0700120 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600121 {
122 return;
123 }
Ed Tanous25b54db2024-04-17 15:40:31 -0700124 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800125 {
126 // Option currently returns no systems. TBD
127 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
128 systemName);
129 return;
130 }
Ed Tanous253f11b2024-05-16 09:38:31 -0700131 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600132 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700133 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
134 systemName);
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600135 return;
136 }
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600137
Ed Tanousac106bf2023-06-07 09:24:59 -0700138 asyncResp->res.addHeader(boost::beast::http::field::link,
139 "</redfish/v1/JsonSchemas/PCIeDeviceCollection/"
140 "PCIeDeviceCollection.json>; rel=describedby");
141 asyncResp->res.jsonValue["@odata.type"] =
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600142 "#PCIeDeviceCollection.PCIeDeviceCollection";
Ed Tanous253f11b2024-05-16 09:38:31 -0700143 asyncResp->res.jsonValue["@odata.id"] = std::format(
144 "/redfish/v1/Systems/{}/PCIeDevices", BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanousac106bf2023-06-07 09:24:59 -0700145 asyncResp->res.jsonValue["Name"] = "PCIe Device Collection";
146 asyncResp->res.jsonValue["Description"] = "Collection of PCIe Devices";
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600147
Lakshmi Yadlapati70c4d542023-06-08 04:37:18 -0500148 pcie_util::getPCIeDeviceList(asyncResp,
149 nlohmann::json::json_pointer("/Members"));
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600150}
151
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700152inline void requestRoutesSystemPCIeDeviceCollection(App& app)
Jason M. Billsadbe1922019-10-14 15:44:35 -0700153{
Jason M. Billsadbe1922019-10-14 15:44:35 -0700154 /**
155 * Functions triggers appropriate requests on DBus
156 */
Ed Tanous22d268c2022-05-19 09:39:07 -0700157 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/PCIeDevices/")
Ed Tanoused398212021-06-09 17:05:54 -0700158 .privileges(redfish::privileges::getPCIeDeviceCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700159 .methods(boost::beast::http::verb::get)(
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600160 std::bind_front(handlePCIeDeviceCollectionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700161}
162
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500163inline void addPCIeSlotProperties(
164 crow::Response& res, const boost::system::error_code& ec,
165 const dbus::utility::DBusPropertiesMap& pcieSlotProperties)
166{
167 if (ec)
168 {
Ed Tanous62598e32023-07-17 17:06:25 -0700169 BMCWEB_LOG_ERROR("DBUS response error for getAllProperties{}",
170 ec.value());
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500171 messages::internalError(res);
172 return;
173 }
174 std::string generation;
175 size_t lanes = 0;
176 std::string slotType;
177
178 bool success = sdbusplus::unpackPropertiesNoThrow(
179 dbus_utils::UnpackErrorPrinter(), pcieSlotProperties, "Generation",
180 generation, "Lanes", lanes, "SlotType", slotType);
181
182 if (!success)
183 {
184 messages::internalError(res);
185 return;
186 }
187
188 std::optional<pcie_device::PCIeTypes> pcieType =
189 pcie_util::redfishPcieGenerationFromDbus(generation);
190 if (!pcieType)
191 {
Ed Tanous62598e32023-07-17 17:06:25 -0700192 BMCWEB_LOG_WARNING("Unknown PCIeType: {}", generation);
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500193 }
194 else
195 {
196 if (*pcieType == pcie_device::PCIeTypes::Invalid)
197 {
Ed Tanous62598e32023-07-17 17:06:25 -0700198 BMCWEB_LOG_ERROR("Invalid PCIeType: {}", generation);
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500199 messages::internalError(res);
200 return;
201 }
202 res.jsonValue["Slot"]["PCIeType"] = *pcieType;
203 }
204
Konstantin Aladyshev82f80322023-07-10 15:00:38 +0300205 if (lanes != 0)
206 {
207 res.jsonValue["Slot"]["Lanes"] = lanes;
208 }
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500209
210 std::optional<pcie_slots::SlotTypes> redfishSlotType =
211 pcie_util::dbusSlotTypeToRf(slotType);
212 if (!redfishSlotType)
213 {
Ed Tanous62598e32023-07-17 17:06:25 -0700214 BMCWEB_LOG_WARNING("Unknown PCIeSlot Type: {}", slotType);
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500215 }
216 else
217 {
218 if (*redfishSlotType == pcie_slots::SlotTypes::Invalid)
219 {
Ed Tanous62598e32023-07-17 17:06:25 -0700220 BMCWEB_LOG_ERROR("Invalid PCIeSlot type: {}", slotType);
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500221 messages::internalError(res);
222 return;
223 }
224 res.jsonValue["Slot"]["SlotType"] = *redfishSlotType;
225 }
226}
227
228inline void getPCIeDeviceSlotPath(
229 const std::string& pcieDevicePath,
230 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
231 std::function<void(const std::string& pcieDeviceSlot)>&& callback)
232{
233 std::string associationPath = pcieDevicePath + "/contained_by";
234 dbus::utility::getAssociatedSubTreePaths(
235 associationPath, sdbusplus::message::object_path(inventoryPath), 0,
236 pcieSlotInterface,
Ed Tanous8cb2c022024-03-27 16:31:46 -0700237 [callback = std::move(callback), asyncResp, pcieDevicePath](
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500238 const boost::system::error_code& ec,
239 const dbus::utility::MapperGetSubTreePathsResponse& endpoints) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400240 if (ec)
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500241 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400242 if (ec.value() == EBADR)
243 {
244 // Missing association is not an error
245 return;
246 }
247 BMCWEB_LOG_ERROR(
248 "DBUS response error for getAssociatedSubTreePaths {}",
249 ec.value());
250 messages::internalError(asyncResp->res);
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500251 return;
252 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400253 if (endpoints.size() > 1)
254 {
255 BMCWEB_LOG_ERROR(
Gunnar Millsa6bd55b2025-01-13 11:24:00 -0600256 "PCIeDevice {} is associated with more than one PCIeSlot: {}",
257 pcieDevicePath, endpoints.size());
Myung Bae67f0b9c2025-06-23 09:52:37 -0400258 for (const std::string& slotPath : endpoints)
259 {
260 BMCWEB_LOG_ERROR("Invalid PCIeSlotPath: {}", slotPath);
261 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400262 messages::internalError(asyncResp->res);
263 return;
264 }
265 if (endpoints.empty())
266 {
267 // If the device doesn't have an association, return without
268 // PCIe Slot properties
269 BMCWEB_LOG_DEBUG("PCIeDevice is not associated with PCIeSlot");
270 return;
271 }
272 callback(endpoints[0]);
273 });
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500274}
275
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400276inline void afterGetDbusObject(
277 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
278 const std::string& pcieDeviceSlot, const boost::system::error_code& ec,
279 const dbus::utility::MapperGetObject& object)
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500280{
281 if (ec || object.empty())
282 {
Ed Tanous62598e32023-07-17 17:06:25 -0700283 BMCWEB_LOG_ERROR("DBUS response error for getDbusObject {}",
284 ec.value());
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500285 messages::internalError(asyncResp->res);
286 return;
287 }
Ed Tanousdeae6a72024-11-11 21:58:57 -0800288 dbus::utility::getAllProperties(
289 object.begin()->first, pcieDeviceSlot,
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500290 "xyz.openbmc_project.Inventory.Item.PCIeSlot",
291 [asyncResp](
292 const boost::system::error_code& ec2,
293 const dbus::utility::DBusPropertiesMap& pcieSlotProperties) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400294 addPCIeSlotProperties(asyncResp->res, ec2, pcieSlotProperties);
295 });
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500296}
297
298inline void afterGetPCIeDeviceSlotPath(
299 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
300 const std::string& pcieDeviceSlot)
301{
302 dbus::utility::getDbusObject(
303 pcieDeviceSlot, pcieSlotInterface,
304 [asyncResp,
305 pcieDeviceSlot](const boost::system::error_code& ec,
306 const dbus::utility::MapperGetObject& object) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400307 afterGetDbusObject(asyncResp, pcieDeviceSlot, ec, object);
308 });
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500309}
310
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400311inline void getPCIeDeviceHealth(
312 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
313 const std::string& pcieDevicePath, const std::string& service)
Lakshmi Yadlapatie164f1b2023-04-12 17:01:34 -0500314{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800315 dbus::utility::getProperty<bool>(
316 service, pcieDevicePath,
Lakshmi Yadlapatie164f1b2023-04-12 17:01:34 -0500317 "xyz.openbmc_project.State.Decorator.OperationalStatus", "Functional",
318 [asyncResp](const boost::system::error_code& ec, const bool value) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400319 if (ec)
Lakshmi Yadlapatie164f1b2023-04-12 17:01:34 -0500320 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400321 if (ec.value() != EBADR)
322 {
323 BMCWEB_LOG_ERROR("DBUS response error for Health {}",
324 ec.value());
325 messages::internalError(asyncResp->res);
326 }
327 return;
Lakshmi Yadlapatie164f1b2023-04-12 17:01:34 -0500328 }
Lakshmi Yadlapatie164f1b2023-04-12 17:01:34 -0500329
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400330 if (!value)
331 {
332 asyncResp->res.jsonValue["Status"]["Health"] =
333 resource::Health::Critical;
334 }
335 });
Lakshmi Yadlapatie164f1b2023-04-12 17:01:34 -0500336}
337
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400338inline void getPCIeDeviceState(
339 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
340 const std::string& pcieDevicePath, const std::string& service)
Lakshmi Yadlapatic6bb3282023-04-12 16:56:49 -0500341{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800342 dbus::utility::getProperty<bool>(
343 service, pcieDevicePath, "xyz.openbmc_project.Inventory.Item",
344 "Present",
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500345 [asyncResp](const boost::system::error_code& ec, bool value) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400346 if (ec)
Lakshmi Yadlapatic6bb3282023-04-12 16:56:49 -0500347 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400348 if (ec.value() != EBADR)
349 {
350 BMCWEB_LOG_ERROR("DBUS response error for State");
351 messages::internalError(asyncResp->res);
352 }
353 return;
Lakshmi Yadlapatic6bb3282023-04-12 16:56:49 -0500354 }
Lakshmi Yadlapatic6bb3282023-04-12 16:56:49 -0500355
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400356 if (!value)
357 {
358 asyncResp->res.jsonValue["Status"]["State"] =
359 resource::State::Absent;
360 }
361 });
Lakshmi Yadlapatic6bb3282023-04-12 16:56:49 -0500362}
363
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400364inline void getPCIeDeviceAsset(
365 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
366 const std::string& pcieDevicePath, const std::string& service)
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600367{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800368 dbus::utility::getAllProperties(
369 service, pcieDevicePath,
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600370 "xyz.openbmc_project.Inventory.Decorator.Asset",
Ed Tanousac106bf2023-06-07 09:24:59 -0700371 [pcieDevicePath, asyncResp{asyncResp}](
372 const boost::system::error_code& ec,
373 const dbus::utility::DBusPropertiesMap& assetList) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400374 if (ec)
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600375 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400376 if (ec.value() != EBADR)
377 {
378 BMCWEB_LOG_ERROR("DBUS response error for Properties{}",
379 ec.value());
380 messages::internalError(asyncResp->res);
381 }
382 return;
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600383 }
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600384
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400385 const std::string* manufacturer = nullptr;
386 const std::string* model = nullptr;
387 const std::string* partNumber = nullptr;
388 const std::string* serialNumber = nullptr;
389 const std::string* sparePartNumber = nullptr;
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600390
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400391 const bool success = sdbusplus::unpackPropertiesNoThrow(
392 dbus_utils::UnpackErrorPrinter(), assetList, "Manufacturer",
393 manufacturer, "Model", model, "PartNumber", partNumber,
394 "SerialNumber", serialNumber, "SparePartNumber",
395 sparePartNumber);
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600396
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400397 if (!success)
398 {
399 messages::internalError(asyncResp->res);
400 return;
401 }
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600402
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400403 if (manufacturer != nullptr)
404 {
405 asyncResp->res.jsonValue["Manufacturer"] = *manufacturer;
406 }
407 if (model != nullptr)
408 {
409 asyncResp->res.jsonValue["Model"] = *model;
410 }
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600411
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400412 if (partNumber != nullptr)
413 {
414 asyncResp->res.jsonValue["PartNumber"] = *partNumber;
415 }
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600416
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400417 if (serialNumber != nullptr)
418 {
419 asyncResp->res.jsonValue["SerialNumber"] = *serialNumber;
420 }
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600421
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400422 if (sparePartNumber != nullptr && !sparePartNumber->empty())
423 {
424 asyncResp->res.jsonValue["SparePartNumber"] = *sparePartNumber;
425 }
426 });
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600427}
428
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600429inline void addPCIeDeviceProperties(
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500430 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
431 const std::string& pcieDeviceId,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600432 const dbus::utility::DBusPropertiesMap& pcieDevProperties)
433{
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600434 const std::string* generationInUse = nullptr;
Konstantin Aladyshev814bf202023-07-04 16:30:10 +0300435 const std::string* generationSupported = nullptr;
Konstantin Aladyshev9bb0a7f2023-07-04 12:59:34 +0300436 const size_t* lanesInUse = nullptr;
Konstantin Aladyshev814bf202023-07-04 16:30:10 +0300437 const size_t* maxLanes = nullptr;
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600438
439 const bool success = sdbusplus::unpackPropertiesNoThrow(
Ed Tanous609ba4c2023-07-11 09:14:24 -0700440 dbus_utils::UnpackErrorPrinter(), pcieDevProperties, "GenerationInUse",
441 generationInUse, "GenerationSupported", generationSupported,
442 "LanesInUse", lanesInUse, "MaxLanes", maxLanes);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600443
444 if (!success)
445 {
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500446 messages::internalError(asyncResp->res);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600447 return;
448 }
449
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600450 if (generationInUse != nullptr)
451 {
452 std::optional<pcie_device::PCIeTypes> redfishGenerationInUse =
Lakshmi Yadlapatic49c3292023-04-19 16:42:35 -0500453 pcie_util::redfishPcieGenerationFromDbus(*generationInUse);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600454
455 if (!redfishGenerationInUse)
456 {
Ed Tanous62598e32023-07-17 17:06:25 -0700457 BMCWEB_LOG_WARNING("Unknown PCIe Device Generation: {}",
458 *generationInUse);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600459 }
Lakshmi Yadlapaticf3b4842023-06-27 02:36:53 -0500460 else
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600461 {
Lakshmi Yadlapaticf3b4842023-06-27 02:36:53 -0500462 if (*redfishGenerationInUse == pcie_device::PCIeTypes::Invalid)
463 {
Ed Tanous62598e32023-07-17 17:06:25 -0700464 BMCWEB_LOG_ERROR("Invalid PCIe Device Generation: {}",
465 *generationInUse);
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500466 messages::internalError(asyncResp->res);
Lakshmi Yadlapaticf3b4842023-06-27 02:36:53 -0500467 return;
468 }
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500469 asyncResp->res.jsonValue["PCIeInterface"]["PCIeType"] =
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600470 *redfishGenerationInUse;
471 }
472 }
473
Konstantin Aladyshev814bf202023-07-04 16:30:10 +0300474 if (generationSupported != nullptr)
475 {
476 std::optional<pcie_device::PCIeTypes> redfishGenerationSupported =
477 pcie_util::redfishPcieGenerationFromDbus(*generationSupported);
478
479 if (!redfishGenerationSupported)
480 {
Ed Tanous62598e32023-07-17 17:06:25 -0700481 BMCWEB_LOG_WARNING("Unknown PCIe Device Generation: {}",
482 *generationSupported);
Konstantin Aladyshev814bf202023-07-04 16:30:10 +0300483 }
484 else
485 {
486 if (*redfishGenerationSupported == pcie_device::PCIeTypes::Invalid)
487 {
Ed Tanous62598e32023-07-17 17:06:25 -0700488 BMCWEB_LOG_ERROR("Invalid PCIe Device Generation: {}",
489 *generationSupported);
Konstantin Aladyshev814bf202023-07-04 16:30:10 +0300490 messages::internalError(asyncResp->res);
491 return;
492 }
493 asyncResp->res.jsonValue["PCIeInterface"]["MaxPCIeType"] =
494 *redfishGenerationSupported;
495 }
496 }
497
Myung Bae8c1d0542024-03-12 17:50:48 -0500498 if (lanesInUse != nullptr)
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600499 {
Myung Bae8c1d0542024-03-12 17:50:48 -0500500 if (*lanesInUse == std::numeric_limits<size_t>::max())
501 {
502 // The default value of LanesInUse is "maxint", and the field will
503 // be null if it is a default value.
504 asyncResp->res.jsonValue["PCIeInterface"]["LanesInUse"] = nullptr;
505 }
506 else
507 {
508 asyncResp->res.jsonValue["PCIeInterface"]["LanesInUse"] =
509 *lanesInUse;
510 }
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600511 }
Konstantin Aladyshev814bf202023-07-04 16:30:10 +0300512 // The default value of MaxLanes is 0, and the field will be
513 // left as off if it is a default value.
514 if (maxLanes != nullptr && *maxLanes != 0)
515 {
516 asyncResp->res.jsonValue["PCIeInterface"]["MaxLanes"] = *maxLanes;
517 }
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600518
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500519 asyncResp->res.jsonValue["PCIeFunctions"]["@odata.id"] =
520 boost::urls::format(
Ed Tanous253f11b2024-05-16 09:38:31 -0700521 "/redfish/v1/Systems/{}/PCIeDevices/{}/PCIeFunctions",
522 BMCWEB_REDFISH_SYSTEM_URI_NAME, pcieDeviceId);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600523}
524
525inline void getPCIeDeviceProperties(
Ed Tanousac106bf2023-06-07 09:24:59 -0700526 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600527 const std::string& pcieDevicePath, const std::string& service,
528 const std::function<void(
529 const dbus::utility::DBusPropertiesMap& pcieDevProperties)>&& callback)
530{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800531 dbus::utility::getAllProperties(
532 service, pcieDevicePath,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600533 "xyz.openbmc_project.Inventory.Item.PCIeDevice",
Ed Tanousac106bf2023-06-07 09:24:59 -0700534 [asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600535 callback](const boost::system::error_code& ec,
536 const dbus::utility::DBusPropertiesMap& pcieDevProperties) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400537 if (ec)
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600538 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400539 if (ec.value() != EBADR)
540 {
541 BMCWEB_LOG_ERROR("DBUS response error for Properties");
542 messages::internalError(asyncResp->res);
543 }
544 return;
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600545 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400546 callback(pcieDevProperties);
547 });
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600548}
549
550inline void addPCIeDeviceCommonProperties(
Ed Tanousac106bf2023-06-07 09:24:59 -0700551 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600552 const std::string& pcieDeviceId)
553{
Ed Tanousac106bf2023-06-07 09:24:59 -0700554 asyncResp->res.addHeader(
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600555 boost::beast::http::field::link,
556 "</redfish/v1/JsonSchemas/PCIeDevice/PCIeDevice.json>; rel=describedby");
Ed Tanousac106bf2023-06-07 09:24:59 -0700557 asyncResp->res.jsonValue["@odata.type"] = "#PCIeDevice.v1_9_0.PCIeDevice";
Ed Tanous253f11b2024-05-16 09:38:31 -0700558 asyncResp->res.jsonValue["@odata.id"] =
559 boost::urls::format("/redfish/v1/Systems/{}/PCIeDevices/{}",
560 BMCWEB_REDFISH_SYSTEM_URI_NAME, pcieDeviceId);
Ed Tanousac106bf2023-06-07 09:24:59 -0700561 asyncResp->res.jsonValue["Name"] = "PCIe Device";
562 asyncResp->res.jsonValue["Id"] = pcieDeviceId;
Ed Tanous539d8c62024-06-19 14:38:27 -0700563 asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled;
564 asyncResp->res.jsonValue["Status"]["Health"] = resource::Health::OK;
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600565}
566
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500567inline void afterGetValidPcieDevicePath(
568 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
569 const std::string& pcieDeviceId, const std::string& pcieDevicePath,
570 const std::string& service)
571{
572 addPCIeDeviceCommonProperties(asyncResp, pcieDeviceId);
573 getPCIeDeviceAsset(asyncResp, pcieDevicePath, service);
574 getPCIeDeviceState(asyncResp, pcieDevicePath, service);
575 getPCIeDeviceHealth(asyncResp, pcieDevicePath, service);
576 getPCIeDeviceProperties(
577 asyncResp, pcieDevicePath, service,
578 std::bind_front(addPCIeDeviceProperties, asyncResp, pcieDeviceId));
579 getPCIeDeviceSlotPath(
580 pcieDevicePath, asyncResp,
581 std::bind_front(afterGetPCIeDeviceSlotPath, asyncResp));
582}
583
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400584inline void handlePCIeDeviceGet(
585 App& app, const crow::Request& req,
586 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
587 const std::string& systemName, const std::string& pcieDeviceId)
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600588{
Ed Tanousac106bf2023-06-07 09:24:59 -0700589 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600590 {
591 return;
592 }
Ed Tanous25b54db2024-04-17 15:40:31 -0700593 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800594 {
595 // Option currently returns no systems. TBD
596 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
597 systemName);
598 return;
599 }
Ed Tanous253f11b2024-05-16 09:38:31 -0700600 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600601 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700602 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
603 systemName);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600604 return;
605 }
606
607 getValidPCIeDevicePath(
Ed Tanousac106bf2023-06-07 09:24:59 -0700608 pcieDeviceId, asyncResp,
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500609 std::bind_front(afterGetValidPcieDevicePath, asyncResp, pcieDeviceId));
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600610}
611
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700612inline void requestRoutesSystemPCIeDevice(App& app)
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -0800613{
Ed Tanous22d268c2022-05-19 09:39:07 -0700614 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/PCIeDevices/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700615 .privileges(redfish::privileges::getPCIeDevice)
Ed Tanous002d39b2022-05-31 08:59:27 -0700616 .methods(boost::beast::http::verb::get)(
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600617 std::bind_front(handlePCIeDeviceGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700618}
619
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600620inline void addPCIeFunctionList(
621 crow::Response& res, const std::string& pcieDeviceId,
622 const dbus::utility::DBusPropertiesMap& pcieDevProperties)
623{
624 nlohmann::json& pcieFunctionList = res.jsonValue["Members"];
625 pcieFunctionList = nlohmann::json::array();
626 static constexpr const int maxPciFunctionNum = 8;
627
628 for (int functionNum = 0; functionNum < maxPciFunctionNum; functionNum++)
629 {
630 // Check if this function exists by
631 // looking for a device ID
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400632 std::string devIDProperty =
633 "Function" + std::to_string(functionNum) + "DeviceId";
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600634 const std::string* property = nullptr;
635 for (const auto& propEntry : pcieDevProperties)
636 {
637 if (propEntry.first == devIDProperty)
638 {
639 property = std::get_if<std::string>(&propEntry.second);
640 break;
641 }
642 }
643 if (property == nullptr || property->empty())
644 {
645 continue;
646 }
647
648 nlohmann::json::object_t pcieFunction;
Ed Tanousef4c65b2023-04-24 15:28:50 -0700649 pcieFunction["@odata.id"] = boost::urls::format(
Ed Tanous253f11b2024-05-16 09:38:31 -0700650 "/redfish/v1/Systems/{}/PCIeDevices/{}/PCIeFunctions/{}",
651 BMCWEB_REDFISH_SYSTEM_URI_NAME, pcieDeviceId,
652 std::to_string(functionNum));
Patrick Williamsb2ba3072023-05-12 10:27:39 -0500653 pcieFunctionList.emplace_back(std::move(pcieFunction));
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600654 }
655 res.jsonValue["PCIeFunctions@odata.count"] = pcieFunctionList.size();
656}
657
658inline void handlePCIeFunctionCollectionGet(
659 App& app, const crow::Request& req,
Ed Tanousac106bf2023-06-07 09:24:59 -0700660 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800661 const std::string& systemName, const std::string& pcieDeviceId)
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600662{
Ed Tanousac106bf2023-06-07 09:24:59 -0700663 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600664 {
665 return;
666 }
Ed Tanous25b54db2024-04-17 15:40:31 -0700667 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800668 {
669 // Option currently returns no systems. TBD
670 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
671 systemName);
672 return;
673 }
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600674
675 getValidPCIeDevicePath(
Ed Tanousac106bf2023-06-07 09:24:59 -0700676 pcieDeviceId, asyncResp,
677 [asyncResp, pcieDeviceId](const std::string& pcieDevicePath,
678 const std::string& service) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400679 asyncResp->res.addHeader(
680 boost::beast::http::field::link,
681 "</redfish/v1/JsonSchemas/PCIeFunctionCollection/PCIeFunctionCollection.json>; rel=describedby");
682 asyncResp->res.jsonValue["@odata.type"] =
683 "#PCIeFunctionCollection.PCIeFunctionCollection";
684 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
685 "/redfish/v1/Systems/{}/PCIeDevices/{}/PCIeFunctions",
686 BMCWEB_REDFISH_SYSTEM_URI_NAME, pcieDeviceId);
687 asyncResp->res.jsonValue["Name"] = "PCIe Function Collection";
688 asyncResp->res.jsonValue["Description"] =
689 "Collection of PCIe Functions for PCIe Device " + pcieDeviceId;
690 getPCIeDeviceProperties(
691 asyncResp, pcieDevicePath, service,
692 [asyncResp, pcieDeviceId](
693 const dbus::utility::DBusPropertiesMap& pcieDevProperties) {
694 addPCIeFunctionList(asyncResp->res, pcieDeviceId,
695 pcieDevProperties);
696 });
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600697 });
698}
699
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700700inline void requestRoutesSystemPCIeFunctionCollection(App& app)
701{
702 /**
703 * Functions triggers appropriate requests on DBus
704 */
705 BMCWEB_ROUTE(app,
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800706 "/redfish/v1/Systems/<str>/PCIeDevices/<str>/PCIeFunctions/")
Ed Tanoused398212021-06-09 17:05:54 -0700707 .privileges(redfish::privileges::getPCIeFunctionCollection)
Ed Tanous002d39b2022-05-31 08:59:27 -0700708 .methods(boost::beast::http::verb::get)(
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600709 std::bind_front(handlePCIeFunctionCollectionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700710}
711
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600712inline bool validatePCIeFunctionId(
Myung Baed5e74b82023-05-31 11:28:02 -0500713 uint64_t pcieFunctionId,
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600714 const dbus::utility::DBusPropertiesMap& pcieDevProperties)
715{
Myung Baed5e74b82023-05-31 11:28:02 -0500716 std::string functionName = "Function" + std::to_string(pcieFunctionId);
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600717 std::string devIDProperty = functionName + "DeviceId";
718
719 const std::string* devIdProperty = nullptr;
720 for (const auto& property : pcieDevProperties)
721 {
722 if (property.first == devIDProperty)
723 {
724 devIdProperty = std::get_if<std::string>(&property.second);
725 break;
726 }
727 }
728 return (devIdProperty != nullptr && !devIdProperty->empty());
729}
730
731inline void addPCIeFunctionProperties(
Ed Tanouse14742c2023-05-31 10:27:49 -0700732 crow::Response& resp, uint64_t pcieFunctionId,
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600733 const dbus::utility::DBusPropertiesMap& pcieDevProperties)
734{
Ed Tanouse14742c2023-05-31 10:27:49 -0700735 std::string functionName = "Function" + std::to_string(pcieFunctionId);
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600736 for (const auto& property : pcieDevProperties)
737 {
738 const std::string* strProperty =
739 std::get_if<std::string>(&property.second);
Ed Tanousdc8cfa62024-04-07 13:37:25 -0700740 if (strProperty == nullptr)
741 {
Ed Tanousdc8cfa62024-04-07 13:37:25 -0700742 continue;
743 }
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600744 if (property.first == functionName + "DeviceId")
745 {
746 resp.jsonValue["DeviceId"] = *strProperty;
747 }
748 if (property.first == functionName + "VendorId")
749 {
750 resp.jsonValue["VendorId"] = *strProperty;
751 }
752 // TODO: FunctionType and DeviceClass are Redfish enums. The D-Bus
753 // property strings should be mapped correctly to ensure these
754 // strings are Redfish enum values. For now just check for empty.
755 if (property.first == functionName + "FunctionType")
756 {
757 if (!strProperty->empty())
758 {
759 resp.jsonValue["FunctionType"] = *strProperty;
760 }
761 }
762 if (property.first == functionName + "DeviceClass")
763 {
764 if (!strProperty->empty())
765 {
766 resp.jsonValue["DeviceClass"] = *strProperty;
767 }
768 }
769 if (property.first == functionName + "ClassCode")
770 {
771 resp.jsonValue["ClassCode"] = *strProperty;
772 }
773 if (property.first == functionName + "RevisionId")
774 {
775 resp.jsonValue["RevisionId"] = *strProperty;
776 }
777 if (property.first == functionName + "SubsystemId")
778 {
779 resp.jsonValue["SubsystemId"] = *strProperty;
780 }
781 if (property.first == functionName + "SubsystemVendorId")
782 {
783 resp.jsonValue["SubsystemVendorId"] = *strProperty;
784 }
785 }
786}
787
788inline void addPCIeFunctionCommonProperties(crow::Response& resp,
789 const std::string& pcieDeviceId,
Ed Tanouse14742c2023-05-31 10:27:49 -0700790 uint64_t pcieFunctionId)
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600791{
792 resp.addHeader(
793 boost::beast::http::field::link,
794 "</redfish/v1/JsonSchemas/PCIeFunction/PCIeFunction.json>; rel=describedby");
795 resp.jsonValue["@odata.type"] = "#PCIeFunction.v1_2_3.PCIeFunction";
Ed Tanousef4c65b2023-04-24 15:28:50 -0700796 resp.jsonValue["@odata.id"] = boost::urls::format(
Ed Tanous253f11b2024-05-16 09:38:31 -0700797 "/redfish/v1/Systems/{}/PCIeDevices/{}/PCIeFunctions/{}",
798 BMCWEB_REDFISH_SYSTEM_URI_NAME, pcieDeviceId,
799 std::to_string(pcieFunctionId));
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600800 resp.jsonValue["Name"] = "PCIe Function";
Ed Tanouse14742c2023-05-31 10:27:49 -0700801 resp.jsonValue["Id"] = std::to_string(pcieFunctionId);
802 resp.jsonValue["FunctionId"] = pcieFunctionId;
Ed Tanous253f11b2024-05-16 09:38:31 -0700803 resp.jsonValue["Links"]["PCIeDevice"]["@odata.id"] =
804 boost::urls::format("/redfish/v1/Systems/{}/PCIeDevices/{}",
805 BMCWEB_REDFISH_SYSTEM_URI_NAME, pcieDeviceId);
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600806}
807
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400808inline void handlePCIeFunctionGet(
809 App& app, const crow::Request& req,
810 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
811 const std::string& systemName, const std::string& pcieDeviceId,
812 const std::string& pcieFunctionIdStr)
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600813{
Ed Tanousac106bf2023-06-07 09:24:59 -0700814 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600815 {
816 return;
817 }
Ed Tanous25b54db2024-04-17 15:40:31 -0700818 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800819 {
820 // Option currently returns no systems. TBD
821 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
822 systemName);
823 return;
824 }
Ed Tanous253f11b2024-05-16 09:38:31 -0700825 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800826 {
827 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
828 systemName);
829 return;
830 }
Ed Tanousdc8cfa62024-04-07 13:37:25 -0700831 std::string_view pcieFunctionIdView = pcieFunctionIdStr;
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800832
Ed Tanouse14742c2023-05-31 10:27:49 -0700833 uint64_t pcieFunctionId = 0;
834 std::from_chars_result result = std::from_chars(
Ed Tanousdc8cfa62024-04-07 13:37:25 -0700835 pcieFunctionIdView.begin(), pcieFunctionIdView.end(), pcieFunctionId);
836 if (result.ec != std::errc{} || result.ptr != pcieFunctionIdView.end())
Ed Tanouse14742c2023-05-31 10:27:49 -0700837 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700838 messages::resourceNotFound(asyncResp->res, "PCIeFunction",
Ed Tanouse14742c2023-05-31 10:27:49 -0700839 pcieFunctionIdStr);
840 return;
841 }
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600842
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400843 getValidPCIeDevicePath(
844 pcieDeviceId, asyncResp,
845 [asyncResp, pcieDeviceId, pcieFunctionId](
846 const std::string& pcieDevicePath, const std::string& service) {
847 getPCIeDeviceProperties(
848 asyncResp, pcieDevicePath, service,
849 [asyncResp, pcieDeviceId, pcieFunctionId](
850 const dbus::utility::DBusPropertiesMap& pcieDevProperties) {
851 addPCIeFunctionCommonProperties(
852 asyncResp->res, pcieDeviceId, pcieFunctionId);
853 addPCIeFunctionProperties(asyncResp->res, pcieFunctionId,
854 pcieDevProperties);
855 });
Patrick Williams5a39f772023-10-20 11:20:21 -0500856 });
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600857}
858
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700859inline void requestRoutesSystemPCIeFunction(App& app)
860{
861 BMCWEB_ROUTE(
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800862 app, "/redfish/v1/Systems/<str>/PCIeDevices/<str>/PCIeFunctions/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700863 .privileges(redfish::privileges::getPCIeFunction)
Ed Tanous002d39b2022-05-31 08:59:27 -0700864 .methods(boost::beast::http::verb::get)(
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600865 std::bind_front(handlePCIeFunctionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700866}
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -0800867
868} // namespace redfish