blob: 82e1a5f1a6756fac97b05915f09dfb0e255d84de [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 Yadlapati9e9325e2023-05-02 10:30:44 -0500135 pcie_util::getPCIeDeviceList(asyncResp, "Members");
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600136}
137
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700138inline void requestRoutesSystemPCIeDeviceCollection(App& app)
Jason M. Billsadbe1922019-10-14 15:44:35 -0700139{
Jason M. Billsadbe1922019-10-14 15:44:35 -0700140 /**
141 * Functions triggers appropriate requests on DBus
142 */
Ed Tanous22d268c2022-05-19 09:39:07 -0700143 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/PCIeDevices/")
Ed Tanoused398212021-06-09 17:05:54 -0700144 .privileges(redfish::privileges::getPCIeDeviceCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700145 .methods(boost::beast::http::verb::get)(
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600146 std::bind_front(handlePCIeDeviceCollectionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700147}
148
Ed Tanousac106bf2023-06-07 09:24:59 -0700149inline void
Lakshmi Yadlapatie164f1b2023-04-12 17:01:34 -0500150 getPCIeDeviceHealth(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
151 const std::string& pcieDevicePath,
152 const std::string& service)
153{
154 sdbusplus::asio::getProperty<bool>(
155 *crow::connections::systemBus, service, pcieDevicePath,
156 "xyz.openbmc_project.State.Decorator.OperationalStatus", "Functional",
157 [asyncResp](const boost::system::error_code& ec, const bool value) {
158 if (ec)
159 {
160 if (ec.value() != EBADR)
161 {
162 BMCWEB_LOG_ERROR << "DBUS response error for Health "
163 << ec.value();
164 messages::internalError(asyncResp->res);
165 }
166 return;
167 }
168
169 if (!value)
170 {
171 asyncResp->res.jsonValue["Status"]["Health"] = "Critical";
172 }
173 });
174}
175
176inline void
Ed Tanousac106bf2023-06-07 09:24:59 -0700177 getPCIeDeviceState(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
178 const std::string& pcieDevicePath,
179 const std::string& service)
Lakshmi Yadlapatic6bb3282023-04-12 16:56:49 -0500180{
181 sdbusplus::asio::getProperty<bool>(
182 *crow::connections::systemBus, service, pcieDevicePath,
183 "xyz.openbmc_project.Inventory.Item", "Present",
Ed Tanousac106bf2023-06-07 09:24:59 -0700184 [asyncResp](const boost::system::error_code& ec, const bool value) {
Lakshmi Yadlapatic6bb3282023-04-12 16:56:49 -0500185 if (ec)
186 {
187 if (ec.value() != EBADR)
188 {
189 BMCWEB_LOG_ERROR << "DBUS response error for State";
Ed Tanousac106bf2023-06-07 09:24:59 -0700190 messages::internalError(asyncResp->res);
Lakshmi Yadlapatic6bb3282023-04-12 16:56:49 -0500191 }
192 return;
193 }
194
195 if (!value)
196 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700197 asyncResp->res.jsonValue["Status"]["State"] = "Absent";
Lakshmi Yadlapatic6bb3282023-04-12 16:56:49 -0500198 }
199 });
200}
201
Ed Tanousac106bf2023-06-07 09:24:59 -0700202inline void
203 getPCIeDeviceAsset(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
204 const std::string& pcieDevicePath,
205 const std::string& service)
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600206{
207 sdbusplus::asio::getAllProperties(
208 *crow::connections::systemBus, service, pcieDevicePath,
209 "xyz.openbmc_project.Inventory.Decorator.Asset",
Ed Tanousac106bf2023-06-07 09:24:59 -0700210 [pcieDevicePath, asyncResp{asyncResp}](
211 const boost::system::error_code& ec,
212 const dbus::utility::DBusPropertiesMap& assetList) {
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600213 if (ec)
214 {
215 if (ec.value() != EBADR)
216 {
217 BMCWEB_LOG_ERROR << "DBUS response error for Properties"
218 << ec.value();
Ed Tanousac106bf2023-06-07 09:24:59 -0700219 messages::internalError(asyncResp->res);
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600220 }
221 return;
222 }
223
224 const std::string* manufacturer = nullptr;
225 const std::string* model = nullptr;
226 const std::string* partNumber = nullptr;
227 const std::string* serialNumber = nullptr;
228 const std::string* sparePartNumber = nullptr;
229
230 const bool success = sdbusplus::unpackPropertiesNoThrow(
231 dbus_utils::UnpackErrorPrinter(), assetList, "Manufacturer",
232 manufacturer, "Model", model, "PartNumber", partNumber,
233 "SerialNumber", serialNumber, "SparePartNumber", sparePartNumber);
234
235 if (!success)
236 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700237 messages::internalError(asyncResp->res);
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600238 return;
239 }
240
241 if (manufacturer != nullptr)
242 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700243 asyncResp->res.jsonValue["Manufacturer"] = *manufacturer;
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600244 }
245 if (model != nullptr)
246 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700247 asyncResp->res.jsonValue["Model"] = *model;
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600248 }
249
250 if (partNumber != nullptr)
251 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700252 asyncResp->res.jsonValue["PartNumber"] = *partNumber;
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600253 }
254
255 if (serialNumber != nullptr)
256 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700257 asyncResp->res.jsonValue["SerialNumber"] = *serialNumber;
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600258 }
259
260 if (sparePartNumber != nullptr && !sparePartNumber->empty())
261 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700262 asyncResp->res.jsonValue["SparePartNumber"] = *sparePartNumber;
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600263 }
264 });
265}
266
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600267inline void addPCIeDeviceProperties(
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600268 crow::Response& resp, const std::string& pcieDeviceId,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600269 const dbus::utility::DBusPropertiesMap& pcieDevProperties)
270{
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600271 const std::string* deviceType = nullptr;
272 const std::string* generationInUse = nullptr;
273 const int64_t* lanesInUse = nullptr;
274
275 const bool success = sdbusplus::unpackPropertiesNoThrow(
276 dbus_utils::UnpackErrorPrinter(), pcieDevProperties, "DeviceType",
277 deviceType, "GenerationInUse", generationInUse, "LanesInUse",
Lakshmi Yadlapatibad2c4a2023-04-07 09:14:37 -0500278 lanesInUse);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600279
280 if (!success)
281 {
282 messages::internalError(resp);
283 return;
284 }
285
286 if (deviceType != nullptr && !deviceType->empty())
287 {
288 resp.jsonValue["PCIeInterface"]["DeviceType"] = *deviceType;
289 }
290
291 if (generationInUse != nullptr)
292 {
293 std::optional<pcie_device::PCIeTypes> redfishGenerationInUse =
Lakshmi Yadlapatic49c3292023-04-19 16:42:35 -0500294 pcie_util::redfishPcieGenerationFromDbus(*generationInUse);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600295
296 if (!redfishGenerationInUse)
297 {
Lakshmi Yadlapaticf3b4842023-06-27 02:36:53 -0500298 BMCWEB_LOG_WARNING << "Unknown PCIe Device Generation: "
299 << *generationInUse;
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600300 }
Lakshmi Yadlapaticf3b4842023-06-27 02:36:53 -0500301 else
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600302 {
Lakshmi Yadlapaticf3b4842023-06-27 02:36:53 -0500303 if (*redfishGenerationInUse == pcie_device::PCIeTypes::Invalid)
304 {
305 BMCWEB_LOG_ERROR << "Invalid PCIe Device Generation: "
306 << *generationInUse;
307 messages::internalError(resp);
308 return;
309 }
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600310 resp.jsonValue["PCIeInterface"]["PCIeType"] =
311 *redfishGenerationInUse;
312 }
313 }
314
315 // The default value of LanesInUse is 0, and the field will be
316 // left as off if it is a default value.
317 if (lanesInUse != nullptr && *lanesInUse != 0)
318 {
319 resp.jsonValue["PCIeInterface"]["LanesInUse"] = *lanesInUse;
320 }
321
Ed Tanousef4c65b2023-04-24 15:28:50 -0700322 resp.jsonValue["PCIeFunctions"]["@odata.id"] = boost::urls::format(
323 "/redfish/v1/Systems/system/PCIeDevices/{}/PCIeFunctions",
324 pcieDeviceId);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600325}
326
327inline void getPCIeDeviceProperties(
Ed Tanousac106bf2023-06-07 09:24:59 -0700328 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600329 const std::string& pcieDevicePath, const std::string& service,
330 const std::function<void(
331 const dbus::utility::DBusPropertiesMap& pcieDevProperties)>&& callback)
332{
333 sdbusplus::asio::getAllProperties(
334 *crow::connections::systemBus, service, pcieDevicePath,
335 "xyz.openbmc_project.Inventory.Item.PCIeDevice",
Ed Tanousac106bf2023-06-07 09:24:59 -0700336 [asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600337 callback](const boost::system::error_code& ec,
338 const dbus::utility::DBusPropertiesMap& pcieDevProperties) {
339 if (ec)
340 {
341 if (ec.value() != EBADR)
342 {
343 BMCWEB_LOG_ERROR << "DBUS response error for Properties";
Ed Tanousac106bf2023-06-07 09:24:59 -0700344 messages::internalError(asyncResp->res);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600345 }
346 return;
347 }
348 callback(pcieDevProperties);
349 });
350}
351
352inline void addPCIeDeviceCommonProperties(
Ed Tanousac106bf2023-06-07 09:24:59 -0700353 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600354 const std::string& pcieDeviceId)
355{
Ed Tanousac106bf2023-06-07 09:24:59 -0700356 asyncResp->res.addHeader(
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600357 boost::beast::http::field::link,
358 "</redfish/v1/JsonSchemas/PCIeDevice/PCIeDevice.json>; rel=describedby");
Ed Tanousac106bf2023-06-07 09:24:59 -0700359 asyncResp->res.jsonValue["@odata.type"] = "#PCIeDevice.v1_9_0.PCIeDevice";
360 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
Ed Tanousef4c65b2023-04-24 15:28:50 -0700361 "/redfish/v1/Systems/system/PCIeDevices/{}", pcieDeviceId);
Ed Tanousac106bf2023-06-07 09:24:59 -0700362 asyncResp->res.jsonValue["Name"] = "PCIe Device";
363 asyncResp->res.jsonValue["Id"] = pcieDeviceId;
364 asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
Lakshmi Yadlapatie164f1b2023-04-12 17:01:34 -0500365 asyncResp->res.jsonValue["Status"]["Health"] = "OK";
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600366}
367
Ed Tanousac106bf2023-06-07 09:24:59 -0700368inline void
369 handlePCIeDeviceGet(App& app, const crow::Request& req,
370 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
371 const std::string& systemName,
372 const std::string& pcieDeviceId)
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600373{
Ed Tanousac106bf2023-06-07 09:24:59 -0700374 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600375 {
376 return;
377 }
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800378 if constexpr (bmcwebEnableMultiHost)
379 {
380 // Option currently returns no systems. TBD
381 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
382 systemName);
383 return;
384 }
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600385 if (systemName != "system")
386 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700387 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
388 systemName);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600389 return;
390 }
391
392 getValidPCIeDevicePath(
Ed Tanousac106bf2023-06-07 09:24:59 -0700393 pcieDeviceId, asyncResp,
394 [asyncResp, pcieDeviceId](const std::string& pcieDevicePath,
395 const std::string& service) {
396 addPCIeDeviceCommonProperties(asyncResp, pcieDeviceId);
397 getPCIeDeviceAsset(asyncResp, pcieDevicePath, service);
398 getPCIeDeviceState(asyncResp, pcieDevicePath, service);
Lakshmi Yadlapatie164f1b2023-04-12 17:01:34 -0500399 getPCIeDeviceHealth(asyncResp, pcieDevicePath, service);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600400 getPCIeDeviceProperties(
Ed Tanousac106bf2023-06-07 09:24:59 -0700401 asyncResp, pcieDevicePath, service,
402 [asyncResp, pcieDeviceId](
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600403 const dbus::utility::DBusPropertiesMap& pcieDevProperties) {
Ed Tanousac106bf2023-06-07 09:24:59 -0700404 addPCIeDeviceProperties(asyncResp->res, pcieDeviceId,
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600405 pcieDevProperties);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600406 });
407 });
408}
409
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700410inline void requestRoutesSystemPCIeDevice(App& app)
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -0800411{
Ed Tanous22d268c2022-05-19 09:39:07 -0700412 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/PCIeDevices/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700413 .privileges(redfish::privileges::getPCIeDevice)
Ed Tanous002d39b2022-05-31 08:59:27 -0700414 .methods(boost::beast::http::verb::get)(
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600415 std::bind_front(handlePCIeDeviceGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700416}
417
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600418inline void addPCIeFunctionList(
419 crow::Response& res, const std::string& pcieDeviceId,
420 const dbus::utility::DBusPropertiesMap& pcieDevProperties)
421{
422 nlohmann::json& pcieFunctionList = res.jsonValue["Members"];
423 pcieFunctionList = nlohmann::json::array();
424 static constexpr const int maxPciFunctionNum = 8;
425
426 for (int functionNum = 0; functionNum < maxPciFunctionNum; functionNum++)
427 {
428 // Check if this function exists by
429 // looking for a device ID
Patrick Williams89492a12023-05-10 07:51:34 -0500430 std::string devIDProperty = "Function" + std::to_string(functionNum) +
431 "DeviceId";
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600432 const std::string* property = nullptr;
433 for (const auto& propEntry : pcieDevProperties)
434 {
435 if (propEntry.first == devIDProperty)
436 {
437 property = std::get_if<std::string>(&propEntry.second);
438 break;
439 }
440 }
441 if (property == nullptr || property->empty())
442 {
443 continue;
444 }
445
446 nlohmann::json::object_t pcieFunction;
Ed Tanousef4c65b2023-04-24 15:28:50 -0700447 pcieFunction["@odata.id"] = boost::urls::format(
448 "/redfish/v1/Systems/system/PCIeDevices/{}/PCIeFunctions/{}",
449 pcieDeviceId, std::to_string(functionNum));
Patrick Williamsb2ba3072023-05-12 10:27:39 -0500450 pcieFunctionList.emplace_back(std::move(pcieFunction));
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600451 }
452 res.jsonValue["PCIeFunctions@odata.count"] = pcieFunctionList.size();
453}
454
455inline void handlePCIeFunctionCollectionGet(
456 App& app, const crow::Request& req,
Ed Tanousac106bf2023-06-07 09:24:59 -0700457 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800458 const std::string& systemName, const std::string& pcieDeviceId)
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600459{
Ed Tanousac106bf2023-06-07 09:24:59 -0700460 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600461 {
462 return;
463 }
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800464 if constexpr (bmcwebEnableMultiHost)
465 {
466 // Option currently returns no systems. TBD
467 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
468 systemName);
469 return;
470 }
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600471
472 getValidPCIeDevicePath(
Ed Tanousac106bf2023-06-07 09:24:59 -0700473 pcieDeviceId, asyncResp,
474 [asyncResp, pcieDeviceId](const std::string& pcieDevicePath,
475 const std::string& service) {
476 asyncResp->res.addHeader(
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600477 boost::beast::http::field::link,
478 "</redfish/v1/JsonSchemas/PCIeFunctionCollection/PCIeFunctionCollection.json>; rel=describedby");
Ed Tanousac106bf2023-06-07 09:24:59 -0700479 asyncResp->res.jsonValue["@odata.type"] =
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600480 "#PCIeFunctionCollection.PCIeFunctionCollection";
Ed Tanousac106bf2023-06-07 09:24:59 -0700481 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
Ed Tanousef4c65b2023-04-24 15:28:50 -0700482 "/redfish/v1/Systems/system/PCIeDevices/{}/PCIeFunctions",
483 pcieDeviceId);
Ed Tanousac106bf2023-06-07 09:24:59 -0700484 asyncResp->res.jsonValue["Name"] = "PCIe Function Collection";
485 asyncResp->res.jsonValue["Description"] =
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600486 "Collection of PCIe Functions for PCIe Device " + pcieDeviceId;
487 getPCIeDeviceProperties(
Ed Tanousac106bf2023-06-07 09:24:59 -0700488 asyncResp, pcieDevicePath, service,
489 [asyncResp, pcieDeviceId](
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600490 const dbus::utility::DBusPropertiesMap& pcieDevProperties) {
Ed Tanousac106bf2023-06-07 09:24:59 -0700491 addPCIeFunctionList(asyncResp->res, pcieDeviceId,
492 pcieDevProperties);
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600493 });
494 });
495}
496
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700497inline void requestRoutesSystemPCIeFunctionCollection(App& app)
498{
499 /**
500 * Functions triggers appropriate requests on DBus
501 */
502 BMCWEB_ROUTE(app,
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800503 "/redfish/v1/Systems/<str>/PCIeDevices/<str>/PCIeFunctions/")
Ed Tanoused398212021-06-09 17:05:54 -0700504 .privileges(redfish::privileges::getPCIeFunctionCollection)
Ed Tanous002d39b2022-05-31 08:59:27 -0700505 .methods(boost::beast::http::verb::get)(
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600506 std::bind_front(handlePCIeFunctionCollectionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700507}
508
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600509inline bool validatePCIeFunctionId(
Myung Baed5e74b82023-05-31 11:28:02 -0500510 uint64_t pcieFunctionId,
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600511 const dbus::utility::DBusPropertiesMap& pcieDevProperties)
512{
Myung Baed5e74b82023-05-31 11:28:02 -0500513 std::string functionName = "Function" + std::to_string(pcieFunctionId);
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600514 std::string devIDProperty = functionName + "DeviceId";
515
516 const std::string* devIdProperty = nullptr;
517 for (const auto& property : pcieDevProperties)
518 {
519 if (property.first == devIDProperty)
520 {
521 devIdProperty = std::get_if<std::string>(&property.second);
522 break;
523 }
524 }
525 return (devIdProperty != nullptr && !devIdProperty->empty());
526}
527
528inline void addPCIeFunctionProperties(
Ed Tanouse14742c2023-05-31 10:27:49 -0700529 crow::Response& resp, uint64_t pcieFunctionId,
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600530 const dbus::utility::DBusPropertiesMap& pcieDevProperties)
531{
Ed Tanouse14742c2023-05-31 10:27:49 -0700532 std::string functionName = "Function" + std::to_string(pcieFunctionId);
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600533 for (const auto& property : pcieDevProperties)
534 {
535 const std::string* strProperty =
536 std::get_if<std::string>(&property.second);
537
538 if (property.first == functionName + "DeviceId")
539 {
540 resp.jsonValue["DeviceId"] = *strProperty;
541 }
542 if (property.first == functionName + "VendorId")
543 {
544 resp.jsonValue["VendorId"] = *strProperty;
545 }
546 // TODO: FunctionType and DeviceClass are Redfish enums. The D-Bus
547 // property strings should be mapped correctly to ensure these
548 // strings are Redfish enum values. For now just check for empty.
549 if (property.first == functionName + "FunctionType")
550 {
551 if (!strProperty->empty())
552 {
553 resp.jsonValue["FunctionType"] = *strProperty;
554 }
555 }
556 if (property.first == functionName + "DeviceClass")
557 {
558 if (!strProperty->empty())
559 {
560 resp.jsonValue["DeviceClass"] = *strProperty;
561 }
562 }
563 if (property.first == functionName + "ClassCode")
564 {
565 resp.jsonValue["ClassCode"] = *strProperty;
566 }
567 if (property.first == functionName + "RevisionId")
568 {
569 resp.jsonValue["RevisionId"] = *strProperty;
570 }
571 if (property.first == functionName + "SubsystemId")
572 {
573 resp.jsonValue["SubsystemId"] = *strProperty;
574 }
575 if (property.first == functionName + "SubsystemVendorId")
576 {
577 resp.jsonValue["SubsystemVendorId"] = *strProperty;
578 }
579 }
580}
581
582inline void addPCIeFunctionCommonProperties(crow::Response& resp,
583 const std::string& pcieDeviceId,
Ed Tanouse14742c2023-05-31 10:27:49 -0700584 uint64_t pcieFunctionId)
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600585{
586 resp.addHeader(
587 boost::beast::http::field::link,
588 "</redfish/v1/JsonSchemas/PCIeFunction/PCIeFunction.json>; rel=describedby");
589 resp.jsonValue["@odata.type"] = "#PCIeFunction.v1_2_3.PCIeFunction";
Ed Tanousef4c65b2023-04-24 15:28:50 -0700590 resp.jsonValue["@odata.id"] = boost::urls::format(
591 "/redfish/v1/Systems/system/PCIeDevices/{}/PCIeFunctions/{}",
Lakshmi Yadlapati768a1432023-06-14 12:45:54 -0500592 pcieDeviceId, std::to_string(pcieFunctionId));
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600593 resp.jsonValue["Name"] = "PCIe Function";
Ed Tanouse14742c2023-05-31 10:27:49 -0700594 resp.jsonValue["Id"] = std::to_string(pcieFunctionId);
595 resp.jsonValue["FunctionId"] = pcieFunctionId;
Ed Tanousef4c65b2023-04-24 15:28:50 -0700596 resp.jsonValue["Links"]["PCIeDevice"]["@odata.id"] = boost::urls::format(
597 "/redfish/v1/Systems/system/PCIeDevices/{}", pcieDeviceId);
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600598}
599
600inline void
601 handlePCIeFunctionGet(App& app, const crow::Request& req,
Ed Tanousac106bf2023-06-07 09:24:59 -0700602 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800603 const std::string& systemName,
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600604 const std::string& pcieDeviceId,
Ed Tanouse14742c2023-05-31 10:27:49 -0700605 const std::string& pcieFunctionIdStr)
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600606{
Ed Tanousac106bf2023-06-07 09:24:59 -0700607 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600608 {
609 return;
610 }
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800611 if constexpr (bmcwebEnableMultiHost)
612 {
613 // Option currently returns no systems. TBD
614 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
615 systemName);
616 return;
617 }
618 if (systemName != "system")
619 {
620 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
621 systemName);
622 return;
623 }
624
Ed Tanouse14742c2023-05-31 10:27:49 -0700625 uint64_t pcieFunctionId = 0;
626 std::from_chars_result result = std::from_chars(
627 &*pcieFunctionIdStr.begin(), &*pcieFunctionIdStr.end(), pcieFunctionId);
628 if (result.ec != std::errc{} || result.ptr != &*pcieFunctionIdStr.end())
629 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700630 messages::resourceNotFound(asyncResp->res, "PCIeFunction",
Ed Tanouse14742c2023-05-31 10:27:49 -0700631 pcieFunctionIdStr);
632 return;
633 }
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600634
Ed Tanousac106bf2023-06-07 09:24:59 -0700635 getValidPCIeDevicePath(pcieDeviceId, asyncResp,
636 [asyncResp, pcieDeviceId,
637 pcieFunctionId](const std::string& pcieDevicePath,
638 const std::string& service) {
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600639 getPCIeDeviceProperties(
Ed Tanousac106bf2023-06-07 09:24:59 -0700640 asyncResp, pcieDevicePath, service,
641 [asyncResp, pcieDeviceId, pcieFunctionId](
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600642 const dbus::utility::DBusPropertiesMap& pcieDevProperties) {
Ed Tanousac106bf2023-06-07 09:24:59 -0700643 addPCIeFunctionCommonProperties(asyncResp->res, pcieDeviceId,
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600644 pcieFunctionId);
Ed Tanousac106bf2023-06-07 09:24:59 -0700645 addPCIeFunctionProperties(asyncResp->res, pcieFunctionId,
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600646 pcieDevProperties);
647 });
Ed Tanousac106bf2023-06-07 09:24:59 -0700648 });
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600649}
650
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700651inline void requestRoutesSystemPCIeFunction(App& app)
652{
653 BMCWEB_ROUTE(
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800654 app, "/redfish/v1/Systems/<str>/PCIeDevices/<str>/PCIeFunctions/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700655 .privileges(redfish::privileges::getPCIeFunction)
Ed Tanous002d39b2022-05-31 08:59:27 -0700656 .methods(boost::beast::http::verb::get)(
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600657 std::bind_front(handlePCIeFunctionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700658}
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -0800659
660} // namespace redfish