blob: db3b94587669e27c1a04c073c1875cfcbe1510dc [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());
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400258 messages::internalError(asyncResp->res);
259 return;
260 }
261 if (endpoints.empty())
262 {
263 // If the device doesn't have an association, return without
264 // PCIe Slot properties
265 BMCWEB_LOG_DEBUG("PCIeDevice is not associated with PCIeSlot");
266 return;
267 }
268 callback(endpoints[0]);
269 });
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500270}
271
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400272inline void afterGetDbusObject(
273 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
274 const std::string& pcieDeviceSlot, const boost::system::error_code& ec,
275 const dbus::utility::MapperGetObject& object)
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500276{
277 if (ec || object.empty())
278 {
Ed Tanous62598e32023-07-17 17:06:25 -0700279 BMCWEB_LOG_ERROR("DBUS response error for getDbusObject {}",
280 ec.value());
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500281 messages::internalError(asyncResp->res);
282 return;
283 }
Ed Tanousdeae6a72024-11-11 21:58:57 -0800284 dbus::utility::getAllProperties(
285 object.begin()->first, pcieDeviceSlot,
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500286 "xyz.openbmc_project.Inventory.Item.PCIeSlot",
287 [asyncResp](
288 const boost::system::error_code& ec2,
289 const dbus::utility::DBusPropertiesMap& pcieSlotProperties) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400290 addPCIeSlotProperties(asyncResp->res, ec2, pcieSlotProperties);
291 });
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500292}
293
294inline void afterGetPCIeDeviceSlotPath(
295 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
296 const std::string& pcieDeviceSlot)
297{
298 dbus::utility::getDbusObject(
299 pcieDeviceSlot, pcieSlotInterface,
300 [asyncResp,
301 pcieDeviceSlot](const boost::system::error_code& ec,
302 const dbus::utility::MapperGetObject& object) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400303 afterGetDbusObject(asyncResp, pcieDeviceSlot, ec, object);
304 });
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500305}
306
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400307inline void getPCIeDeviceHealth(
308 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
309 const std::string& pcieDevicePath, const std::string& service)
Lakshmi Yadlapatie164f1b2023-04-12 17:01:34 -0500310{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800311 dbus::utility::getProperty<bool>(
312 service, pcieDevicePath,
Lakshmi Yadlapatie164f1b2023-04-12 17:01:34 -0500313 "xyz.openbmc_project.State.Decorator.OperationalStatus", "Functional",
314 [asyncResp](const boost::system::error_code& ec, const bool value) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400315 if (ec)
Lakshmi Yadlapatie164f1b2023-04-12 17:01:34 -0500316 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400317 if (ec.value() != EBADR)
318 {
319 BMCWEB_LOG_ERROR("DBUS response error for Health {}",
320 ec.value());
321 messages::internalError(asyncResp->res);
322 }
323 return;
Lakshmi Yadlapatie164f1b2023-04-12 17:01:34 -0500324 }
Lakshmi Yadlapatie164f1b2023-04-12 17:01:34 -0500325
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400326 if (!value)
327 {
328 asyncResp->res.jsonValue["Status"]["Health"] =
329 resource::Health::Critical;
330 }
331 });
Lakshmi Yadlapatie164f1b2023-04-12 17:01:34 -0500332}
333
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400334inline void getPCIeDeviceState(
335 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
336 const std::string& pcieDevicePath, const std::string& service)
Lakshmi Yadlapatic6bb3282023-04-12 16:56:49 -0500337{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800338 dbus::utility::getProperty<bool>(
339 service, pcieDevicePath, "xyz.openbmc_project.Inventory.Item",
340 "Present",
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500341 [asyncResp](const boost::system::error_code& ec, bool value) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400342 if (ec)
Lakshmi Yadlapatic6bb3282023-04-12 16:56:49 -0500343 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400344 if (ec.value() != EBADR)
345 {
346 BMCWEB_LOG_ERROR("DBUS response error for State");
347 messages::internalError(asyncResp->res);
348 }
349 return;
Lakshmi Yadlapatic6bb3282023-04-12 16:56:49 -0500350 }
Lakshmi Yadlapatic6bb3282023-04-12 16:56:49 -0500351
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400352 if (!value)
353 {
354 asyncResp->res.jsonValue["Status"]["State"] =
355 resource::State::Absent;
356 }
357 });
Lakshmi Yadlapatic6bb3282023-04-12 16:56:49 -0500358}
359
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400360inline void getPCIeDeviceAsset(
361 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
362 const std::string& pcieDevicePath, const std::string& service)
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600363{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800364 dbus::utility::getAllProperties(
365 service, pcieDevicePath,
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600366 "xyz.openbmc_project.Inventory.Decorator.Asset",
Ed Tanousac106bf2023-06-07 09:24:59 -0700367 [pcieDevicePath, asyncResp{asyncResp}](
368 const boost::system::error_code& ec,
369 const dbus::utility::DBusPropertiesMap& assetList) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400370 if (ec)
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600371 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400372 if (ec.value() != EBADR)
373 {
374 BMCWEB_LOG_ERROR("DBUS response error for Properties{}",
375 ec.value());
376 messages::internalError(asyncResp->res);
377 }
378 return;
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600379 }
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600380
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400381 const std::string* manufacturer = nullptr;
382 const std::string* model = nullptr;
383 const std::string* partNumber = nullptr;
384 const std::string* serialNumber = nullptr;
385 const std::string* sparePartNumber = nullptr;
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600386
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400387 const bool success = sdbusplus::unpackPropertiesNoThrow(
388 dbus_utils::UnpackErrorPrinter(), assetList, "Manufacturer",
389 manufacturer, "Model", model, "PartNumber", partNumber,
390 "SerialNumber", serialNumber, "SparePartNumber",
391 sparePartNumber);
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600392
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400393 if (!success)
394 {
395 messages::internalError(asyncResp->res);
396 return;
397 }
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600398
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400399 if (manufacturer != nullptr)
400 {
401 asyncResp->res.jsonValue["Manufacturer"] = *manufacturer;
402 }
403 if (model != nullptr)
404 {
405 asyncResp->res.jsonValue["Model"] = *model;
406 }
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600407
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400408 if (partNumber != nullptr)
409 {
410 asyncResp->res.jsonValue["PartNumber"] = *partNumber;
411 }
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600412
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400413 if (serialNumber != nullptr)
414 {
415 asyncResp->res.jsonValue["SerialNumber"] = *serialNumber;
416 }
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600417
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400418 if (sparePartNumber != nullptr && !sparePartNumber->empty())
419 {
420 asyncResp->res.jsonValue["SparePartNumber"] = *sparePartNumber;
421 }
422 });
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600423}
424
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600425inline void addPCIeDeviceProperties(
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500426 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
427 const std::string& pcieDeviceId,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600428 const dbus::utility::DBusPropertiesMap& pcieDevProperties)
429{
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600430 const std::string* generationInUse = nullptr;
Konstantin Aladyshev814bf202023-07-04 16:30:10 +0300431 const std::string* generationSupported = nullptr;
Konstantin Aladyshev9bb0a7f2023-07-04 12:59:34 +0300432 const size_t* lanesInUse = nullptr;
Konstantin Aladyshev814bf202023-07-04 16:30:10 +0300433 const size_t* maxLanes = nullptr;
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600434
435 const bool success = sdbusplus::unpackPropertiesNoThrow(
Ed Tanous609ba4c2023-07-11 09:14:24 -0700436 dbus_utils::UnpackErrorPrinter(), pcieDevProperties, "GenerationInUse",
437 generationInUse, "GenerationSupported", generationSupported,
438 "LanesInUse", lanesInUse, "MaxLanes", maxLanes);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600439
440 if (!success)
441 {
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500442 messages::internalError(asyncResp->res);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600443 return;
444 }
445
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600446 if (generationInUse != nullptr)
447 {
448 std::optional<pcie_device::PCIeTypes> redfishGenerationInUse =
Lakshmi Yadlapatic49c3292023-04-19 16:42:35 -0500449 pcie_util::redfishPcieGenerationFromDbus(*generationInUse);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600450
451 if (!redfishGenerationInUse)
452 {
Ed Tanous62598e32023-07-17 17:06:25 -0700453 BMCWEB_LOG_WARNING("Unknown PCIe Device Generation: {}",
454 *generationInUse);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600455 }
Lakshmi Yadlapaticf3b4842023-06-27 02:36:53 -0500456 else
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600457 {
Lakshmi Yadlapaticf3b4842023-06-27 02:36:53 -0500458 if (*redfishGenerationInUse == pcie_device::PCIeTypes::Invalid)
459 {
Ed Tanous62598e32023-07-17 17:06:25 -0700460 BMCWEB_LOG_ERROR("Invalid PCIe Device Generation: {}",
461 *generationInUse);
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500462 messages::internalError(asyncResp->res);
Lakshmi Yadlapaticf3b4842023-06-27 02:36:53 -0500463 return;
464 }
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500465 asyncResp->res.jsonValue["PCIeInterface"]["PCIeType"] =
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600466 *redfishGenerationInUse;
467 }
468 }
469
Konstantin Aladyshev814bf202023-07-04 16:30:10 +0300470 if (generationSupported != nullptr)
471 {
472 std::optional<pcie_device::PCIeTypes> redfishGenerationSupported =
473 pcie_util::redfishPcieGenerationFromDbus(*generationSupported);
474
475 if (!redfishGenerationSupported)
476 {
Ed Tanous62598e32023-07-17 17:06:25 -0700477 BMCWEB_LOG_WARNING("Unknown PCIe Device Generation: {}",
478 *generationSupported);
Konstantin Aladyshev814bf202023-07-04 16:30:10 +0300479 }
480 else
481 {
482 if (*redfishGenerationSupported == pcie_device::PCIeTypes::Invalid)
483 {
Ed Tanous62598e32023-07-17 17:06:25 -0700484 BMCWEB_LOG_ERROR("Invalid PCIe Device Generation: {}",
485 *generationSupported);
Konstantin Aladyshev814bf202023-07-04 16:30:10 +0300486 messages::internalError(asyncResp->res);
487 return;
488 }
489 asyncResp->res.jsonValue["PCIeInterface"]["MaxPCIeType"] =
490 *redfishGenerationSupported;
491 }
492 }
493
Myung Bae8c1d0542024-03-12 17:50:48 -0500494 if (lanesInUse != nullptr)
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600495 {
Myung Bae8c1d0542024-03-12 17:50:48 -0500496 if (*lanesInUse == std::numeric_limits<size_t>::max())
497 {
498 // The default value of LanesInUse is "maxint", and the field will
499 // be null if it is a default value.
500 asyncResp->res.jsonValue["PCIeInterface"]["LanesInUse"] = nullptr;
501 }
502 else
503 {
504 asyncResp->res.jsonValue["PCIeInterface"]["LanesInUse"] =
505 *lanesInUse;
506 }
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600507 }
Konstantin Aladyshev814bf202023-07-04 16:30:10 +0300508 // The default value of MaxLanes is 0, and the field will be
509 // left as off if it is a default value.
510 if (maxLanes != nullptr && *maxLanes != 0)
511 {
512 asyncResp->res.jsonValue["PCIeInterface"]["MaxLanes"] = *maxLanes;
513 }
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600514
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500515 asyncResp->res.jsonValue["PCIeFunctions"]["@odata.id"] =
516 boost::urls::format(
Ed Tanous253f11b2024-05-16 09:38:31 -0700517 "/redfish/v1/Systems/{}/PCIeDevices/{}/PCIeFunctions",
518 BMCWEB_REDFISH_SYSTEM_URI_NAME, pcieDeviceId);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600519}
520
521inline void getPCIeDeviceProperties(
Ed Tanousac106bf2023-06-07 09:24:59 -0700522 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600523 const std::string& pcieDevicePath, const std::string& service,
524 const std::function<void(
525 const dbus::utility::DBusPropertiesMap& pcieDevProperties)>&& callback)
526{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800527 dbus::utility::getAllProperties(
528 service, pcieDevicePath,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600529 "xyz.openbmc_project.Inventory.Item.PCIeDevice",
Ed Tanousac106bf2023-06-07 09:24:59 -0700530 [asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600531 callback](const boost::system::error_code& ec,
532 const dbus::utility::DBusPropertiesMap& pcieDevProperties) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400533 if (ec)
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600534 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400535 if (ec.value() != EBADR)
536 {
537 BMCWEB_LOG_ERROR("DBUS response error for Properties");
538 messages::internalError(asyncResp->res);
539 }
540 return;
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600541 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400542 callback(pcieDevProperties);
543 });
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600544}
545
546inline void addPCIeDeviceCommonProperties(
Ed Tanousac106bf2023-06-07 09:24:59 -0700547 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600548 const std::string& pcieDeviceId)
549{
Ed Tanousac106bf2023-06-07 09:24:59 -0700550 asyncResp->res.addHeader(
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600551 boost::beast::http::field::link,
552 "</redfish/v1/JsonSchemas/PCIeDevice/PCIeDevice.json>; rel=describedby");
Ed Tanousac106bf2023-06-07 09:24:59 -0700553 asyncResp->res.jsonValue["@odata.type"] = "#PCIeDevice.v1_9_0.PCIeDevice";
Ed Tanous253f11b2024-05-16 09:38:31 -0700554 asyncResp->res.jsonValue["@odata.id"] =
555 boost::urls::format("/redfish/v1/Systems/{}/PCIeDevices/{}",
556 BMCWEB_REDFISH_SYSTEM_URI_NAME, pcieDeviceId);
Ed Tanousac106bf2023-06-07 09:24:59 -0700557 asyncResp->res.jsonValue["Name"] = "PCIe Device";
558 asyncResp->res.jsonValue["Id"] = pcieDeviceId;
Ed Tanous539d8c62024-06-19 14:38:27 -0700559 asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled;
560 asyncResp->res.jsonValue["Status"]["Health"] = resource::Health::OK;
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600561}
562
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500563inline void afterGetValidPcieDevicePath(
564 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
565 const std::string& pcieDeviceId, const std::string& pcieDevicePath,
566 const std::string& service)
567{
568 addPCIeDeviceCommonProperties(asyncResp, pcieDeviceId);
569 getPCIeDeviceAsset(asyncResp, pcieDevicePath, service);
570 getPCIeDeviceState(asyncResp, pcieDevicePath, service);
571 getPCIeDeviceHealth(asyncResp, pcieDevicePath, service);
572 getPCIeDeviceProperties(
573 asyncResp, pcieDevicePath, service,
574 std::bind_front(addPCIeDeviceProperties, asyncResp, pcieDeviceId));
575 getPCIeDeviceSlotPath(
576 pcieDevicePath, asyncResp,
577 std::bind_front(afterGetPCIeDeviceSlotPath, asyncResp));
578}
579
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400580inline void handlePCIeDeviceGet(
581 App& app, const crow::Request& req,
582 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
583 const std::string& systemName, const std::string& pcieDeviceId)
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600584{
Ed Tanousac106bf2023-06-07 09:24:59 -0700585 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600586 {
587 return;
588 }
Ed Tanous25b54db2024-04-17 15:40:31 -0700589 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800590 {
591 // Option currently returns no systems. TBD
592 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
593 systemName);
594 return;
595 }
Ed Tanous253f11b2024-05-16 09:38:31 -0700596 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600597 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700598 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
599 systemName);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600600 return;
601 }
602
603 getValidPCIeDevicePath(
Ed Tanousac106bf2023-06-07 09:24:59 -0700604 pcieDeviceId, asyncResp,
Lakshmi Yadlapatia5409992023-04-20 16:53:59 -0500605 std::bind_front(afterGetValidPcieDevicePath, asyncResp, pcieDeviceId));
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600606}
607
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700608inline void requestRoutesSystemPCIeDevice(App& app)
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -0800609{
Ed Tanous22d268c2022-05-19 09:39:07 -0700610 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/PCIeDevices/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700611 .privileges(redfish::privileges::getPCIeDevice)
Ed Tanous002d39b2022-05-31 08:59:27 -0700612 .methods(boost::beast::http::verb::get)(
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600613 std::bind_front(handlePCIeDeviceGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700614}
615
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600616inline void addPCIeFunctionList(
617 crow::Response& res, const std::string& pcieDeviceId,
618 const dbus::utility::DBusPropertiesMap& pcieDevProperties)
619{
620 nlohmann::json& pcieFunctionList = res.jsonValue["Members"];
621 pcieFunctionList = nlohmann::json::array();
622 static constexpr const int maxPciFunctionNum = 8;
623
624 for (int functionNum = 0; functionNum < maxPciFunctionNum; functionNum++)
625 {
626 // Check if this function exists by
627 // looking for a device ID
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400628 std::string devIDProperty =
629 "Function" + std::to_string(functionNum) + "DeviceId";
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600630 const std::string* property = nullptr;
631 for (const auto& propEntry : pcieDevProperties)
632 {
633 if (propEntry.first == devIDProperty)
634 {
635 property = std::get_if<std::string>(&propEntry.second);
636 break;
637 }
638 }
639 if (property == nullptr || property->empty())
640 {
641 continue;
642 }
643
644 nlohmann::json::object_t pcieFunction;
Ed Tanousef4c65b2023-04-24 15:28:50 -0700645 pcieFunction["@odata.id"] = boost::urls::format(
Ed Tanous253f11b2024-05-16 09:38:31 -0700646 "/redfish/v1/Systems/{}/PCIeDevices/{}/PCIeFunctions/{}",
647 BMCWEB_REDFISH_SYSTEM_URI_NAME, pcieDeviceId,
648 std::to_string(functionNum));
Patrick Williamsb2ba3072023-05-12 10:27:39 -0500649 pcieFunctionList.emplace_back(std::move(pcieFunction));
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600650 }
651 res.jsonValue["PCIeFunctions@odata.count"] = pcieFunctionList.size();
652}
653
654inline void handlePCIeFunctionCollectionGet(
655 App& app, const crow::Request& req,
Ed Tanousac106bf2023-06-07 09:24:59 -0700656 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800657 const std::string& systemName, const std::string& pcieDeviceId)
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600658{
Ed Tanousac106bf2023-06-07 09:24:59 -0700659 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600660 {
661 return;
662 }
Ed Tanous25b54db2024-04-17 15:40:31 -0700663 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800664 {
665 // Option currently returns no systems. TBD
666 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
667 systemName);
668 return;
669 }
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600670
671 getValidPCIeDevicePath(
Ed Tanousac106bf2023-06-07 09:24:59 -0700672 pcieDeviceId, asyncResp,
673 [asyncResp, pcieDeviceId](const std::string& pcieDevicePath,
674 const std::string& service) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400675 asyncResp->res.addHeader(
676 boost::beast::http::field::link,
677 "</redfish/v1/JsonSchemas/PCIeFunctionCollection/PCIeFunctionCollection.json>; rel=describedby");
678 asyncResp->res.jsonValue["@odata.type"] =
679 "#PCIeFunctionCollection.PCIeFunctionCollection";
680 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
681 "/redfish/v1/Systems/{}/PCIeDevices/{}/PCIeFunctions",
682 BMCWEB_REDFISH_SYSTEM_URI_NAME, pcieDeviceId);
683 asyncResp->res.jsonValue["Name"] = "PCIe Function Collection";
684 asyncResp->res.jsonValue["Description"] =
685 "Collection of PCIe Functions for PCIe Device " + pcieDeviceId;
686 getPCIeDeviceProperties(
687 asyncResp, pcieDevicePath, service,
688 [asyncResp, pcieDeviceId](
689 const dbus::utility::DBusPropertiesMap& pcieDevProperties) {
690 addPCIeFunctionList(asyncResp->res, pcieDeviceId,
691 pcieDevProperties);
692 });
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600693 });
694}
695
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700696inline void requestRoutesSystemPCIeFunctionCollection(App& app)
697{
698 /**
699 * Functions triggers appropriate requests on DBus
700 */
701 BMCWEB_ROUTE(app,
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800702 "/redfish/v1/Systems/<str>/PCIeDevices/<str>/PCIeFunctions/")
Ed Tanoused398212021-06-09 17:05:54 -0700703 .privileges(redfish::privileges::getPCIeFunctionCollection)
Ed Tanous002d39b2022-05-31 08:59:27 -0700704 .methods(boost::beast::http::verb::get)(
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600705 std::bind_front(handlePCIeFunctionCollectionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700706}
707
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600708inline bool validatePCIeFunctionId(
Myung Baed5e74b82023-05-31 11:28:02 -0500709 uint64_t pcieFunctionId,
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600710 const dbus::utility::DBusPropertiesMap& pcieDevProperties)
711{
Myung Baed5e74b82023-05-31 11:28:02 -0500712 std::string functionName = "Function" + std::to_string(pcieFunctionId);
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600713 std::string devIDProperty = functionName + "DeviceId";
714
715 const std::string* devIdProperty = nullptr;
716 for (const auto& property : pcieDevProperties)
717 {
718 if (property.first == devIDProperty)
719 {
720 devIdProperty = std::get_if<std::string>(&property.second);
721 break;
722 }
723 }
724 return (devIdProperty != nullptr && !devIdProperty->empty());
725}
726
727inline void addPCIeFunctionProperties(
Ed Tanouse14742c2023-05-31 10:27:49 -0700728 crow::Response& resp, uint64_t pcieFunctionId,
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600729 const dbus::utility::DBusPropertiesMap& pcieDevProperties)
730{
Ed Tanouse14742c2023-05-31 10:27:49 -0700731 std::string functionName = "Function" + std::to_string(pcieFunctionId);
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600732 for (const auto& property : pcieDevProperties)
733 {
734 const std::string* strProperty =
735 std::get_if<std::string>(&property.second);
Ed Tanousdc8cfa62024-04-07 13:37:25 -0700736 if (strProperty == nullptr)
737 {
Ed Tanousdc8cfa62024-04-07 13:37:25 -0700738 continue;
739 }
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600740 if (property.first == functionName + "DeviceId")
741 {
742 resp.jsonValue["DeviceId"] = *strProperty;
743 }
744 if (property.first == functionName + "VendorId")
745 {
746 resp.jsonValue["VendorId"] = *strProperty;
747 }
748 // TODO: FunctionType and DeviceClass are Redfish enums. The D-Bus
749 // property strings should be mapped correctly to ensure these
750 // strings are Redfish enum values. For now just check for empty.
751 if (property.first == functionName + "FunctionType")
752 {
753 if (!strProperty->empty())
754 {
755 resp.jsonValue["FunctionType"] = *strProperty;
756 }
757 }
758 if (property.first == functionName + "DeviceClass")
759 {
760 if (!strProperty->empty())
761 {
762 resp.jsonValue["DeviceClass"] = *strProperty;
763 }
764 }
765 if (property.first == functionName + "ClassCode")
766 {
767 resp.jsonValue["ClassCode"] = *strProperty;
768 }
769 if (property.first == functionName + "RevisionId")
770 {
771 resp.jsonValue["RevisionId"] = *strProperty;
772 }
773 if (property.first == functionName + "SubsystemId")
774 {
775 resp.jsonValue["SubsystemId"] = *strProperty;
776 }
777 if (property.first == functionName + "SubsystemVendorId")
778 {
779 resp.jsonValue["SubsystemVendorId"] = *strProperty;
780 }
781 }
782}
783
784inline void addPCIeFunctionCommonProperties(crow::Response& resp,
785 const std::string& pcieDeviceId,
Ed Tanouse14742c2023-05-31 10:27:49 -0700786 uint64_t pcieFunctionId)
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600787{
788 resp.addHeader(
789 boost::beast::http::field::link,
790 "</redfish/v1/JsonSchemas/PCIeFunction/PCIeFunction.json>; rel=describedby");
791 resp.jsonValue["@odata.type"] = "#PCIeFunction.v1_2_3.PCIeFunction";
Ed Tanousef4c65b2023-04-24 15:28:50 -0700792 resp.jsonValue["@odata.id"] = boost::urls::format(
Ed Tanous253f11b2024-05-16 09:38:31 -0700793 "/redfish/v1/Systems/{}/PCIeDevices/{}/PCIeFunctions/{}",
794 BMCWEB_REDFISH_SYSTEM_URI_NAME, pcieDeviceId,
795 std::to_string(pcieFunctionId));
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600796 resp.jsonValue["Name"] = "PCIe Function";
Ed Tanouse14742c2023-05-31 10:27:49 -0700797 resp.jsonValue["Id"] = std::to_string(pcieFunctionId);
798 resp.jsonValue["FunctionId"] = pcieFunctionId;
Ed Tanous253f11b2024-05-16 09:38:31 -0700799 resp.jsonValue["Links"]["PCIeDevice"]["@odata.id"] =
800 boost::urls::format("/redfish/v1/Systems/{}/PCIeDevices/{}",
801 BMCWEB_REDFISH_SYSTEM_URI_NAME, pcieDeviceId);
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600802}
803
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400804inline void handlePCIeFunctionGet(
805 App& app, const crow::Request& req,
806 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
807 const std::string& systemName, const std::string& pcieDeviceId,
808 const std::string& pcieFunctionIdStr)
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600809{
Ed Tanousac106bf2023-06-07 09:24:59 -0700810 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600811 {
812 return;
813 }
Ed Tanous25b54db2024-04-17 15:40:31 -0700814 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800815 {
816 // Option currently returns no systems. TBD
817 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
818 systemName);
819 return;
820 }
Ed Tanous253f11b2024-05-16 09:38:31 -0700821 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800822 {
823 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
824 systemName);
825 return;
826 }
Ed Tanousdc8cfa62024-04-07 13:37:25 -0700827 std::string_view pcieFunctionIdView = pcieFunctionIdStr;
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800828
Ed Tanouse14742c2023-05-31 10:27:49 -0700829 uint64_t pcieFunctionId = 0;
830 std::from_chars_result result = std::from_chars(
Ed Tanousdc8cfa62024-04-07 13:37:25 -0700831 pcieFunctionIdView.begin(), pcieFunctionIdView.end(), pcieFunctionId);
832 if (result.ec != std::errc{} || result.ptr != pcieFunctionIdView.end())
Ed Tanouse14742c2023-05-31 10:27:49 -0700833 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700834 messages::resourceNotFound(asyncResp->res, "PCIeFunction",
Ed Tanouse14742c2023-05-31 10:27:49 -0700835 pcieFunctionIdStr);
836 return;
837 }
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600838
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400839 getValidPCIeDevicePath(
840 pcieDeviceId, asyncResp,
841 [asyncResp, pcieDeviceId, pcieFunctionId](
842 const std::string& pcieDevicePath, const std::string& service) {
843 getPCIeDeviceProperties(
844 asyncResp, pcieDevicePath, service,
845 [asyncResp, pcieDeviceId, pcieFunctionId](
846 const dbus::utility::DBusPropertiesMap& pcieDevProperties) {
847 addPCIeFunctionCommonProperties(
848 asyncResp->res, pcieDeviceId, pcieFunctionId);
849 addPCIeFunctionProperties(asyncResp->res, pcieFunctionId,
850 pcieDevProperties);
851 });
Patrick Williams5a39f772023-10-20 11:20:21 -0500852 });
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600853}
854
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700855inline void requestRoutesSystemPCIeFunction(App& app)
856{
857 BMCWEB_ROUTE(
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800858 app, "/redfish/v1/Systems/<str>/PCIeDevices/<str>/PCIeFunctions/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700859 .privileges(redfish::privileges::getPCIeFunction)
Ed Tanous002d39b2022-05-31 08:59:27 -0700860 .methods(boost::beast::http::verb::get)(
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600861 std::bind_front(handlePCIeFunctionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700862}
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -0800863
864} // namespace redfish