blob: d623321c1a464b44c0973ebbed8734dae06dfb06 [file] [log] [blame]
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -08001/*
2// Copyright (c) 2018 Intel Corporation
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
16
17#pragma once
18
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080019#include "app.hpp"
George Liu7a1dbc42022-12-07 16:03:22 +080020#include "dbus_utility.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080021#include "query.hpp"
22#include "registries/privilege_registry.hpp"
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -060023#include "utils/collection.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080024#include "utils/dbus_utils.hpp"
Lakshmi Yadlapatic49c3292023-04-19 16:42:35 -050025#include "utils/pcie_util.hpp"
Ed Tanous0ec8b832022-03-14 14:56:47 -070026
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -080027#include <boost/system/linux_error.hpp>
Ed Tanousef4c65b2023-04-24 15:28:50 -070028#include <boost/url/format.hpp>
Krzysztof Grobelnyd1bde9e2022-09-07 10:40:51 +020029#include <sdbusplus/asio/property.hpp>
30#include <sdbusplus/unpack_properties.hpp>
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -080031
32namespace redfish
33{
34
Patrick Williams89492a12023-05-10 07:51:34 -050035static constexpr const char* inventoryPath = "/xyz/openbmc_project/inventory";
Lakshmi Yadlapati94c3a102023-04-05 18:11:22 -050036static constexpr std::array<std::string_view, 1> pcieDeviceInterface = {
37 "xyz.openbmc_project.Inventory.Item.PCIeDevice"};
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -080038
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060039static inline void handlePCIeDevicePath(
40 const std::string& pcieDeviceId,
Ed Tanousac106bf2023-06-07 09:24:59 -070041 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060042 const dbus::utility::MapperGetSubTreePathsResponse& pcieDevicePaths,
43 const std::function<void(const std::string& pcieDevicePath,
44 const std::string& service)>& callback)
45
46{
47 for (const std::string& pcieDevicePath : pcieDevicePaths)
48 {
49 std::string pciecDeviceName =
50 sdbusplus::message::object_path(pcieDevicePath).filename();
51 if (pciecDeviceName.empty() || pciecDeviceName != pcieDeviceId)
52 {
53 continue;
54 }
55
56 dbus::utility::getDbusObject(
57 pcieDevicePath, {},
Ed Tanousac106bf2023-06-07 09:24:59 -070058 [pcieDevicePath, asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060059 callback](const boost::system::error_code& ec,
60 const dbus::utility::MapperGetObject& object) {
61 if (ec || object.empty())
62 {
63 BMCWEB_LOG_ERROR << "DBUS response error " << ec;
Ed Tanousac106bf2023-06-07 09:24:59 -070064 messages::internalError(asyncResp->res);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060065 return;
66 }
67 callback(pcieDevicePath, object.begin()->first);
68 });
69 return;
70 }
71
72 BMCWEB_LOG_WARNING << "PCIe Device not found";
Ed Tanousac106bf2023-06-07 09:24:59 -070073 messages::resourceNotFound(asyncResp->res, "PCIeDevice", pcieDeviceId);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060074}
75
76static inline void getValidPCIeDevicePath(
77 const std::string& pcieDeviceId,
Ed Tanousac106bf2023-06-07 09:24:59 -070078 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060079 const std::function<void(const std::string& pcieDevicePath,
80 const std::string& service)>& callback)
81{
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060082 dbus::utility::getSubTreePaths(
Lakshmi Yadlapati94c3a102023-04-05 18:11:22 -050083 inventoryPath, 0, pcieDeviceInterface,
Ed Tanousac106bf2023-06-07 09:24:59 -070084 [pcieDeviceId, asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060085 callback](const boost::system::error_code& ec,
86 const dbus::utility::MapperGetSubTreePathsResponse&
87 pcieDevicePaths) {
88 if (ec)
89 {
90 BMCWEB_LOG_ERROR << "D-Bus response error on GetSubTree " << ec;
Ed Tanousac106bf2023-06-07 09:24:59 -070091 messages::internalError(asyncResp->res);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060092 return;
93 }
Ed Tanousac106bf2023-06-07 09:24:59 -070094 handlePCIeDevicePath(pcieDeviceId, asyncResp, pcieDevicePaths,
95 callback);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -060096 return;
97 });
98}
99
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600100static inline void handlePCIeDeviceCollectionGet(
101 crow::App& app, const crow::Request& req,
Ed Tanousac106bf2023-06-07 09:24:59 -0700102 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600103 const std::string& systemName)
104{
Ed Tanousac106bf2023-06-07 09:24:59 -0700105 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600106 {
107 return;
108 }
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800109 if constexpr (bmcwebEnableMultiHost)
110 {
111 // Option currently returns no systems. TBD
112 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
113 systemName);
114 return;
115 }
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600116 if (systemName != "system")
117 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700118 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
119 systemName);
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600120 return;
121 }
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600122
Ed Tanousac106bf2023-06-07 09:24:59 -0700123 asyncResp->res.addHeader(boost::beast::http::field::link,
124 "</redfish/v1/JsonSchemas/PCIeDeviceCollection/"
125 "PCIeDeviceCollection.json>; rel=describedby");
126 asyncResp->res.jsonValue["@odata.type"] =
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600127 "#PCIeDeviceCollection.PCIeDeviceCollection";
Ed Tanousac106bf2023-06-07 09:24:59 -0700128 asyncResp->res.jsonValue["@odata.id"] =
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600129 "/redfish/v1/Systems/system/PCIeDevices";
Ed Tanousac106bf2023-06-07 09:24:59 -0700130 asyncResp->res.jsonValue["Name"] = "PCIe Device Collection";
131 asyncResp->res.jsonValue["Description"] = "Collection of PCIe Devices";
132 asyncResp->res.jsonValue["Members"] = nlohmann::json::array();
133 asyncResp->res.jsonValue["Members@odata.count"] = 0;
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600134
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600135 collection_util::getCollectionMembers(
Ed Tanousac106bf2023-06-07 09:24:59 -0700136 asyncResp, boost::urls::url("/redfish/v1/Systems/system/PCIeDevices"),
Lakshmi Yadlapati94c3a102023-04-05 18:11:22 -0500137 pcieDeviceInterface);
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600138}
139
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700140inline void requestRoutesSystemPCIeDeviceCollection(App& app)
Jason M. Billsadbe1922019-10-14 15:44:35 -0700141{
Jason M. Billsadbe1922019-10-14 15:44:35 -0700142 /**
143 * Functions triggers appropriate requests on DBus
144 */
Ed Tanous22d268c2022-05-19 09:39:07 -0700145 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/PCIeDevices/")
Ed Tanoused398212021-06-09 17:05:54 -0700146 .privileges(redfish::privileges::getPCIeDeviceCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700147 .methods(boost::beast::http::verb::get)(
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600148 std::bind_front(handlePCIeDeviceCollectionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700149}
150
Ed Tanousac106bf2023-06-07 09:24:59 -0700151inline void
Lakshmi Yadlapatie164f1b2023-04-12 17:01:34 -0500152 getPCIeDeviceHealth(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
153 const std::string& pcieDevicePath,
154 const std::string& service)
155{
156 sdbusplus::asio::getProperty<bool>(
157 *crow::connections::systemBus, service, pcieDevicePath,
158 "xyz.openbmc_project.State.Decorator.OperationalStatus", "Functional",
159 [asyncResp](const boost::system::error_code& ec, const bool value) {
160 if (ec)
161 {
162 if (ec.value() != EBADR)
163 {
164 BMCWEB_LOG_ERROR << "DBUS response error for Health "
165 << ec.value();
166 messages::internalError(asyncResp->res);
167 }
168 return;
169 }
170
171 if (!value)
172 {
173 asyncResp->res.jsonValue["Status"]["Health"] = "Critical";
174 }
175 });
176}
177
178inline void
Ed Tanousac106bf2023-06-07 09:24:59 -0700179 getPCIeDeviceState(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
180 const std::string& pcieDevicePath,
181 const std::string& service)
Lakshmi Yadlapatic6bb3282023-04-12 16:56:49 -0500182{
183 sdbusplus::asio::getProperty<bool>(
184 *crow::connections::systemBus, service, pcieDevicePath,
185 "xyz.openbmc_project.Inventory.Item", "Present",
Ed Tanousac106bf2023-06-07 09:24:59 -0700186 [asyncResp](const boost::system::error_code& ec, const bool value) {
Lakshmi Yadlapatic6bb3282023-04-12 16:56:49 -0500187 if (ec)
188 {
189 if (ec.value() != EBADR)
190 {
191 BMCWEB_LOG_ERROR << "DBUS response error for State";
Ed Tanousac106bf2023-06-07 09:24:59 -0700192 messages::internalError(asyncResp->res);
Lakshmi Yadlapatic6bb3282023-04-12 16:56:49 -0500193 }
194 return;
195 }
196
197 if (!value)
198 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700199 asyncResp->res.jsonValue["Status"]["State"] = "Absent";
Lakshmi Yadlapatic6bb3282023-04-12 16:56:49 -0500200 }
201 });
202}
203
Ed Tanousac106bf2023-06-07 09:24:59 -0700204inline void
205 getPCIeDeviceAsset(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
206 const std::string& pcieDevicePath,
207 const std::string& service)
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600208{
209 sdbusplus::asio::getAllProperties(
210 *crow::connections::systemBus, service, pcieDevicePath,
211 "xyz.openbmc_project.Inventory.Decorator.Asset",
Ed Tanousac106bf2023-06-07 09:24:59 -0700212 [pcieDevicePath, asyncResp{asyncResp}](
213 const boost::system::error_code& ec,
214 const dbus::utility::DBusPropertiesMap& assetList) {
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600215 if (ec)
216 {
217 if (ec.value() != EBADR)
218 {
219 BMCWEB_LOG_ERROR << "DBUS response error for Properties"
220 << ec.value();
Ed Tanousac106bf2023-06-07 09:24:59 -0700221 messages::internalError(asyncResp->res);
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600222 }
223 return;
224 }
225
226 const std::string* manufacturer = nullptr;
227 const std::string* model = nullptr;
228 const std::string* partNumber = nullptr;
229 const std::string* serialNumber = nullptr;
230 const std::string* sparePartNumber = nullptr;
231
232 const bool success = sdbusplus::unpackPropertiesNoThrow(
233 dbus_utils::UnpackErrorPrinter(), assetList, "Manufacturer",
234 manufacturer, "Model", model, "PartNumber", partNumber,
235 "SerialNumber", serialNumber, "SparePartNumber", sparePartNumber);
236
237 if (!success)
238 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700239 messages::internalError(asyncResp->res);
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600240 return;
241 }
242
243 if (manufacturer != nullptr)
244 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700245 asyncResp->res.jsonValue["Manufacturer"] = *manufacturer;
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600246 }
247 if (model != nullptr)
248 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700249 asyncResp->res.jsonValue["Model"] = *model;
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600250 }
251
252 if (partNumber != nullptr)
253 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700254 asyncResp->res.jsonValue["PartNumber"] = *partNumber;
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600255 }
256
257 if (serialNumber != nullptr)
258 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700259 asyncResp->res.jsonValue["SerialNumber"] = *serialNumber;
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600260 }
261
262 if (sparePartNumber != nullptr && !sparePartNumber->empty())
263 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700264 asyncResp->res.jsonValue["SparePartNumber"] = *sparePartNumber;
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600265 }
266 });
267}
268
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600269inline void addPCIeDeviceProperties(
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600270 crow::Response& resp, const std::string& pcieDeviceId,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600271 const dbus::utility::DBusPropertiesMap& pcieDevProperties)
272{
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600273 const std::string* deviceType = nullptr;
274 const std::string* generationInUse = nullptr;
275 const int64_t* lanesInUse = nullptr;
276
277 const bool success = sdbusplus::unpackPropertiesNoThrow(
278 dbus_utils::UnpackErrorPrinter(), pcieDevProperties, "DeviceType",
279 deviceType, "GenerationInUse", generationInUse, "LanesInUse",
Lakshmi Yadlapatibad2c4a2023-04-07 09:14:37 -0500280 lanesInUse);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600281
282 if (!success)
283 {
284 messages::internalError(resp);
285 return;
286 }
287
288 if (deviceType != nullptr && !deviceType->empty())
289 {
290 resp.jsonValue["PCIeInterface"]["DeviceType"] = *deviceType;
291 }
292
293 if (generationInUse != nullptr)
294 {
295 std::optional<pcie_device::PCIeTypes> redfishGenerationInUse =
Lakshmi Yadlapatic49c3292023-04-19 16:42:35 -0500296 pcie_util::redfishPcieGenerationFromDbus(*generationInUse);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600297
298 if (!redfishGenerationInUse)
299 {
300 messages::internalError(resp);
301 return;
302 }
303 if (*redfishGenerationInUse != pcie_device::PCIeTypes::Invalid)
304 {
305 resp.jsonValue["PCIeInterface"]["PCIeType"] =
306 *redfishGenerationInUse;
307 }
308 }
309
310 // The default value of LanesInUse is 0, and the field will be
311 // left as off if it is a default value.
312 if (lanesInUse != nullptr && *lanesInUse != 0)
313 {
314 resp.jsonValue["PCIeInterface"]["LanesInUse"] = *lanesInUse;
315 }
316
Ed Tanousef4c65b2023-04-24 15:28:50 -0700317 resp.jsonValue["PCIeFunctions"]["@odata.id"] = boost::urls::format(
318 "/redfish/v1/Systems/system/PCIeDevices/{}/PCIeFunctions",
319 pcieDeviceId);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600320}
321
322inline void getPCIeDeviceProperties(
Ed Tanousac106bf2023-06-07 09:24:59 -0700323 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600324 const std::string& pcieDevicePath, const std::string& service,
325 const std::function<void(
326 const dbus::utility::DBusPropertiesMap& pcieDevProperties)>&& callback)
327{
328 sdbusplus::asio::getAllProperties(
329 *crow::connections::systemBus, service, pcieDevicePath,
330 "xyz.openbmc_project.Inventory.Item.PCIeDevice",
Ed Tanousac106bf2023-06-07 09:24:59 -0700331 [asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600332 callback](const boost::system::error_code& ec,
333 const dbus::utility::DBusPropertiesMap& pcieDevProperties) {
334 if (ec)
335 {
336 if (ec.value() != EBADR)
337 {
338 BMCWEB_LOG_ERROR << "DBUS response error for Properties";
Ed Tanousac106bf2023-06-07 09:24:59 -0700339 messages::internalError(asyncResp->res);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600340 }
341 return;
342 }
343 callback(pcieDevProperties);
344 });
345}
346
347inline void addPCIeDeviceCommonProperties(
Ed Tanousac106bf2023-06-07 09:24:59 -0700348 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600349 const std::string& pcieDeviceId)
350{
Ed Tanousac106bf2023-06-07 09:24:59 -0700351 asyncResp->res.addHeader(
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600352 boost::beast::http::field::link,
353 "</redfish/v1/JsonSchemas/PCIeDevice/PCIeDevice.json>; rel=describedby");
Ed Tanousac106bf2023-06-07 09:24:59 -0700354 asyncResp->res.jsonValue["@odata.type"] = "#PCIeDevice.v1_9_0.PCIeDevice";
355 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
Ed Tanousef4c65b2023-04-24 15:28:50 -0700356 "/redfish/v1/Systems/system/PCIeDevices/{}", pcieDeviceId);
Ed Tanousac106bf2023-06-07 09:24:59 -0700357 asyncResp->res.jsonValue["Name"] = "PCIe Device";
358 asyncResp->res.jsonValue["Id"] = pcieDeviceId;
359 asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
Lakshmi Yadlapatie164f1b2023-04-12 17:01:34 -0500360 asyncResp->res.jsonValue["Status"]["Health"] = "OK";
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600361}
362
Ed Tanousac106bf2023-06-07 09:24:59 -0700363inline void
364 handlePCIeDeviceGet(App& app, const crow::Request& req,
365 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
366 const std::string& systemName,
367 const std::string& pcieDeviceId)
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600368{
Ed Tanousac106bf2023-06-07 09:24:59 -0700369 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600370 {
371 return;
372 }
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800373 if constexpr (bmcwebEnableMultiHost)
374 {
375 // Option currently returns no systems. TBD
376 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
377 systemName);
378 return;
379 }
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600380 if (systemName != "system")
381 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700382 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
383 systemName);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600384 return;
385 }
386
387 getValidPCIeDevicePath(
Ed Tanousac106bf2023-06-07 09:24:59 -0700388 pcieDeviceId, asyncResp,
389 [asyncResp, pcieDeviceId](const std::string& pcieDevicePath,
390 const std::string& service) {
391 addPCIeDeviceCommonProperties(asyncResp, pcieDeviceId);
392 getPCIeDeviceAsset(asyncResp, pcieDevicePath, service);
393 getPCIeDeviceState(asyncResp, pcieDevicePath, service);
Lakshmi Yadlapatie164f1b2023-04-12 17:01:34 -0500394 getPCIeDeviceHealth(asyncResp, pcieDevicePath, service);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600395 getPCIeDeviceProperties(
Ed Tanousac106bf2023-06-07 09:24:59 -0700396 asyncResp, pcieDevicePath, service,
397 [asyncResp, pcieDeviceId](
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600398 const dbus::utility::DBusPropertiesMap& pcieDevProperties) {
Ed Tanousac106bf2023-06-07 09:24:59 -0700399 addPCIeDeviceProperties(asyncResp->res, pcieDeviceId,
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600400 pcieDevProperties);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600401 });
402 });
403}
404
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700405inline void requestRoutesSystemPCIeDevice(App& app)
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -0800406{
Ed Tanous22d268c2022-05-19 09:39:07 -0700407 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/PCIeDevices/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700408 .privileges(redfish::privileges::getPCIeDevice)
Ed Tanous002d39b2022-05-31 08:59:27 -0700409 .methods(boost::beast::http::verb::get)(
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600410 std::bind_front(handlePCIeDeviceGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700411}
412
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600413inline void addPCIeFunctionList(
414 crow::Response& res, const std::string& pcieDeviceId,
415 const dbus::utility::DBusPropertiesMap& pcieDevProperties)
416{
417 nlohmann::json& pcieFunctionList = res.jsonValue["Members"];
418 pcieFunctionList = nlohmann::json::array();
419 static constexpr const int maxPciFunctionNum = 8;
420
421 for (int functionNum = 0; functionNum < maxPciFunctionNum; functionNum++)
422 {
423 // Check if this function exists by
424 // looking for a device ID
Patrick Williams89492a12023-05-10 07:51:34 -0500425 std::string devIDProperty = "Function" + std::to_string(functionNum) +
426 "DeviceId";
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600427 const std::string* property = nullptr;
428 for (const auto& propEntry : pcieDevProperties)
429 {
430 if (propEntry.first == devIDProperty)
431 {
432 property = std::get_if<std::string>(&propEntry.second);
433 break;
434 }
435 }
436 if (property == nullptr || property->empty())
437 {
438 continue;
439 }
440
441 nlohmann::json::object_t pcieFunction;
Ed Tanousef4c65b2023-04-24 15:28:50 -0700442 pcieFunction["@odata.id"] = boost::urls::format(
443 "/redfish/v1/Systems/system/PCIeDevices/{}/PCIeFunctions/{}",
444 pcieDeviceId, std::to_string(functionNum));
Patrick Williamsb2ba3072023-05-12 10:27:39 -0500445 pcieFunctionList.emplace_back(std::move(pcieFunction));
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600446 }
447 res.jsonValue["PCIeFunctions@odata.count"] = pcieFunctionList.size();
448}
449
450inline void handlePCIeFunctionCollectionGet(
451 App& app, const crow::Request& req,
Ed Tanousac106bf2023-06-07 09:24:59 -0700452 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800453 const std::string& systemName, const std::string& pcieDeviceId)
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600454{
Ed Tanousac106bf2023-06-07 09:24:59 -0700455 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600456 {
457 return;
458 }
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800459 if constexpr (bmcwebEnableMultiHost)
460 {
461 // Option currently returns no systems. TBD
462 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
463 systemName);
464 return;
465 }
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600466
467 getValidPCIeDevicePath(
Ed Tanousac106bf2023-06-07 09:24:59 -0700468 pcieDeviceId, asyncResp,
469 [asyncResp, pcieDeviceId](const std::string& pcieDevicePath,
470 const std::string& service) {
471 asyncResp->res.addHeader(
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600472 boost::beast::http::field::link,
473 "</redfish/v1/JsonSchemas/PCIeFunctionCollection/PCIeFunctionCollection.json>; rel=describedby");
Ed Tanousac106bf2023-06-07 09:24:59 -0700474 asyncResp->res.jsonValue["@odata.type"] =
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600475 "#PCIeFunctionCollection.PCIeFunctionCollection";
Ed Tanousac106bf2023-06-07 09:24:59 -0700476 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
Ed Tanousef4c65b2023-04-24 15:28:50 -0700477 "/redfish/v1/Systems/system/PCIeDevices/{}/PCIeFunctions",
478 pcieDeviceId);
Ed Tanousac106bf2023-06-07 09:24:59 -0700479 asyncResp->res.jsonValue["Name"] = "PCIe Function Collection";
480 asyncResp->res.jsonValue["Description"] =
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600481 "Collection of PCIe Functions for PCIe Device " + pcieDeviceId;
482 getPCIeDeviceProperties(
Ed Tanousac106bf2023-06-07 09:24:59 -0700483 asyncResp, pcieDevicePath, service,
484 [asyncResp, pcieDeviceId](
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600485 const dbus::utility::DBusPropertiesMap& pcieDevProperties) {
Ed Tanousac106bf2023-06-07 09:24:59 -0700486 addPCIeFunctionList(asyncResp->res, pcieDeviceId,
487 pcieDevProperties);
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600488 });
489 });
490}
491
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700492inline void requestRoutesSystemPCIeFunctionCollection(App& app)
493{
494 /**
495 * Functions triggers appropriate requests on DBus
496 */
497 BMCWEB_ROUTE(app,
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800498 "/redfish/v1/Systems/<str>/PCIeDevices/<str>/PCIeFunctions/")
Ed Tanoused398212021-06-09 17:05:54 -0700499 .privileges(redfish::privileges::getPCIeFunctionCollection)
Ed Tanous002d39b2022-05-31 08:59:27 -0700500 .methods(boost::beast::http::verb::get)(
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600501 std::bind_front(handlePCIeFunctionCollectionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700502}
503
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600504inline bool validatePCIeFunctionId(
Myung Baed5e74b82023-05-31 11:28:02 -0500505 uint64_t pcieFunctionId,
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600506 const dbus::utility::DBusPropertiesMap& pcieDevProperties)
507{
Myung Baed5e74b82023-05-31 11:28:02 -0500508 std::string functionName = "Function" + std::to_string(pcieFunctionId);
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600509 std::string devIDProperty = functionName + "DeviceId";
510
511 const std::string* devIdProperty = nullptr;
512 for (const auto& property : pcieDevProperties)
513 {
514 if (property.first == devIDProperty)
515 {
516 devIdProperty = std::get_if<std::string>(&property.second);
517 break;
518 }
519 }
520 return (devIdProperty != nullptr && !devIdProperty->empty());
521}
522
523inline void addPCIeFunctionProperties(
Ed Tanouse14742c2023-05-31 10:27:49 -0700524 crow::Response& resp, uint64_t pcieFunctionId,
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600525 const dbus::utility::DBusPropertiesMap& pcieDevProperties)
526{
Ed Tanouse14742c2023-05-31 10:27:49 -0700527 std::string functionName = "Function" + std::to_string(pcieFunctionId);
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600528 for (const auto& property : pcieDevProperties)
529 {
530 const std::string* strProperty =
531 std::get_if<std::string>(&property.second);
532
533 if (property.first == functionName + "DeviceId")
534 {
535 resp.jsonValue["DeviceId"] = *strProperty;
536 }
537 if (property.first == functionName + "VendorId")
538 {
539 resp.jsonValue["VendorId"] = *strProperty;
540 }
541 // TODO: FunctionType and DeviceClass are Redfish enums. The D-Bus
542 // property strings should be mapped correctly to ensure these
543 // strings are Redfish enum values. For now just check for empty.
544 if (property.first == functionName + "FunctionType")
545 {
546 if (!strProperty->empty())
547 {
548 resp.jsonValue["FunctionType"] = *strProperty;
549 }
550 }
551 if (property.first == functionName + "DeviceClass")
552 {
553 if (!strProperty->empty())
554 {
555 resp.jsonValue["DeviceClass"] = *strProperty;
556 }
557 }
558 if (property.first == functionName + "ClassCode")
559 {
560 resp.jsonValue["ClassCode"] = *strProperty;
561 }
562 if (property.first == functionName + "RevisionId")
563 {
564 resp.jsonValue["RevisionId"] = *strProperty;
565 }
566 if (property.first == functionName + "SubsystemId")
567 {
568 resp.jsonValue["SubsystemId"] = *strProperty;
569 }
570 if (property.first == functionName + "SubsystemVendorId")
571 {
572 resp.jsonValue["SubsystemVendorId"] = *strProperty;
573 }
574 }
575}
576
577inline void addPCIeFunctionCommonProperties(crow::Response& resp,
578 const std::string& pcieDeviceId,
Ed Tanouse14742c2023-05-31 10:27:49 -0700579 uint64_t pcieFunctionId)
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600580{
581 resp.addHeader(
582 boost::beast::http::field::link,
583 "</redfish/v1/JsonSchemas/PCIeFunction/PCIeFunction.json>; rel=describedby");
584 resp.jsonValue["@odata.type"] = "#PCIeFunction.v1_2_3.PCIeFunction";
Ed Tanousef4c65b2023-04-24 15:28:50 -0700585 resp.jsonValue["@odata.id"] = boost::urls::format(
586 "/redfish/v1/Systems/system/PCIeDevices/{}/PCIeFunctions/{}",
Lakshmi Yadlapati768a1432023-06-14 12:45:54 -0500587 pcieDeviceId, std::to_string(pcieFunctionId));
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600588 resp.jsonValue["Name"] = "PCIe Function";
Ed Tanouse14742c2023-05-31 10:27:49 -0700589 resp.jsonValue["Id"] = std::to_string(pcieFunctionId);
590 resp.jsonValue["FunctionId"] = pcieFunctionId;
Ed Tanousef4c65b2023-04-24 15:28:50 -0700591 resp.jsonValue["Links"]["PCIeDevice"]["@odata.id"] = boost::urls::format(
592 "/redfish/v1/Systems/system/PCIeDevices/{}", pcieDeviceId);
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600593}
594
595inline void
596 handlePCIeFunctionGet(App& app, const crow::Request& req,
Ed Tanousac106bf2023-06-07 09:24:59 -0700597 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800598 const std::string& systemName,
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600599 const std::string& pcieDeviceId,
Ed Tanouse14742c2023-05-31 10:27:49 -0700600 const std::string& pcieFunctionIdStr)
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600601{
Ed Tanousac106bf2023-06-07 09:24:59 -0700602 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600603 {
604 return;
605 }
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800606 if constexpr (bmcwebEnableMultiHost)
607 {
608 // Option currently returns no systems. TBD
609 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
610 systemName);
611 return;
612 }
613 if (systemName != "system")
614 {
615 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
616 systemName);
617 return;
618 }
619
Ed Tanouse14742c2023-05-31 10:27:49 -0700620 uint64_t pcieFunctionId = 0;
621 std::from_chars_result result = std::from_chars(
622 &*pcieFunctionIdStr.begin(), &*pcieFunctionIdStr.end(), pcieFunctionId);
623 if (result.ec != std::errc{} || result.ptr != &*pcieFunctionIdStr.end())
624 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700625 messages::resourceNotFound(asyncResp->res, "PCIeFunction",
Ed Tanouse14742c2023-05-31 10:27:49 -0700626 pcieFunctionIdStr);
627 return;
628 }
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600629
Ed Tanousac106bf2023-06-07 09:24:59 -0700630 getValidPCIeDevicePath(pcieDeviceId, asyncResp,
631 [asyncResp, pcieDeviceId,
632 pcieFunctionId](const std::string& pcieDevicePath,
633 const std::string& service) {
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600634 getPCIeDeviceProperties(
Ed Tanousac106bf2023-06-07 09:24:59 -0700635 asyncResp, pcieDevicePath, service,
636 [asyncResp, pcieDeviceId, pcieFunctionId](
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600637 const dbus::utility::DBusPropertiesMap& pcieDevProperties) {
Ed Tanousac106bf2023-06-07 09:24:59 -0700638 addPCIeFunctionCommonProperties(asyncResp->res, pcieDeviceId,
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600639 pcieFunctionId);
Ed Tanousac106bf2023-06-07 09:24:59 -0700640 addPCIeFunctionProperties(asyncResp->res, pcieFunctionId,
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600641 pcieDevProperties);
642 });
Ed Tanousac106bf2023-06-07 09:24:59 -0700643 });
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600644}
645
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700646inline void requestRoutesSystemPCIeFunction(App& app)
647{
648 BMCWEB_ROUTE(
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800649 app, "/redfish/v1/Systems/<str>/PCIeDevices/<str>/PCIeFunctions/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700650 .privileges(redfish::privileges::getPCIeFunction)
Ed Tanous002d39b2022-05-31 08:59:27 -0700651 .methods(boost::beast::http::verb::get)(
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600652 std::bind_front(handlePCIeFunctionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700653}
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -0800654
655} // namespace redfish