blob: 1c36b181ae68a3834caec54b9835a9fd9c6c0cd4 [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 Tanous0ec8b832022-03-14 14:56:47 -070021#include "generated/enums/pcie_device.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080022#include "query.hpp"
23#include "registries/privilege_registry.hpp"
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -060024#include "utils/collection.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080025#include "utils/dbus_utils.hpp"
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 }
109 if (systemName != "system")
110 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700111 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
112 systemName);
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600113 return;
114 }
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600115
Ed Tanousac106bf2023-06-07 09:24:59 -0700116 asyncResp->res.addHeader(boost::beast::http::field::link,
117 "</redfish/v1/JsonSchemas/PCIeDeviceCollection/"
118 "PCIeDeviceCollection.json>; rel=describedby");
119 asyncResp->res.jsonValue["@odata.type"] =
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600120 "#PCIeDeviceCollection.PCIeDeviceCollection";
Ed Tanousac106bf2023-06-07 09:24:59 -0700121 asyncResp->res.jsonValue["@odata.id"] =
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600122 "/redfish/v1/Systems/system/PCIeDevices";
Ed Tanousac106bf2023-06-07 09:24:59 -0700123 asyncResp->res.jsonValue["Name"] = "PCIe Device Collection";
124 asyncResp->res.jsonValue["Description"] = "Collection of PCIe Devices";
125 asyncResp->res.jsonValue["Members"] = nlohmann::json::array();
126 asyncResp->res.jsonValue["Members@odata.count"] = 0;
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600127
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600128 collection_util::getCollectionMembers(
Ed Tanousac106bf2023-06-07 09:24:59 -0700129 asyncResp, boost::urls::url("/redfish/v1/Systems/system/PCIeDevices"),
Lakshmi Yadlapati94c3a102023-04-05 18:11:22 -0500130 pcieDeviceInterface);
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600131}
132
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700133inline void requestRoutesSystemPCIeDeviceCollection(App& app)
Jason M. Billsadbe1922019-10-14 15:44:35 -0700134{
Jason M. Billsadbe1922019-10-14 15:44:35 -0700135 /**
136 * Functions triggers appropriate requests on DBus
137 */
Ed Tanous22d268c2022-05-19 09:39:07 -0700138 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/PCIeDevices/")
Ed Tanoused398212021-06-09 17:05:54 -0700139 .privileges(redfish::privileges::getPCIeDeviceCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700140 .methods(boost::beast::http::verb::get)(
Lakshmi Yadlapatib38fa2a2023-03-10 16:19:46 -0600141 std::bind_front(handlePCIeDeviceCollectionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700142}
143
Ed Tanous0ec8b832022-03-14 14:56:47 -0700144inline std::optional<pcie_device::PCIeTypes>
Spencer Ku62cd45a2021-11-22 16:41:25 +0800145 redfishPcieGenerationFromDbus(const std::string& generationInUse)
146{
147 if (generationInUse ==
148 "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen1")
149 {
Ed Tanous0ec8b832022-03-14 14:56:47 -0700150 return pcie_device::PCIeTypes::Gen1;
Spencer Ku62cd45a2021-11-22 16:41:25 +0800151 }
152 if (generationInUse ==
153 "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen2")
154 {
Ed Tanous0ec8b832022-03-14 14:56:47 -0700155 return pcie_device::PCIeTypes::Gen2;
Spencer Ku62cd45a2021-11-22 16:41:25 +0800156 }
157 if (generationInUse ==
158 "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen3")
159 {
Ed Tanous0ec8b832022-03-14 14:56:47 -0700160 return pcie_device::PCIeTypes::Gen3;
Spencer Ku62cd45a2021-11-22 16:41:25 +0800161 }
162 if (generationInUse ==
163 "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen4")
164 {
Ed Tanous0ec8b832022-03-14 14:56:47 -0700165 return pcie_device::PCIeTypes::Gen4;
Spencer Ku62cd45a2021-11-22 16:41:25 +0800166 }
167 if (generationInUse ==
168 "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen5")
169 {
Ed Tanous0ec8b832022-03-14 14:56:47 -0700170 return pcie_device::PCIeTypes::Gen5;
Spencer Ku62cd45a2021-11-22 16:41:25 +0800171 }
Ed Tanouse825cbc2022-06-17 11:39:22 -0700172 if (generationInUse.empty() ||
173 generationInUse ==
174 "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Unknown")
Spencer Ku62cd45a2021-11-22 16:41:25 +0800175 {
Ed Tanous0ec8b832022-03-14 14:56:47 -0700176 return pcie_device::PCIeTypes::Invalid;
Spencer Ku62cd45a2021-11-22 16:41:25 +0800177 }
178
179 // The value is not unknown or Gen1-5, need return an internal error.
180 return std::nullopt;
181}
182
Ed Tanousac106bf2023-06-07 09:24:59 -0700183inline void
184 getPCIeDeviceState(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
185 const std::string& pcieDevicePath,
186 const std::string& service)
Lakshmi Yadlapatic6bb3282023-04-12 16:56:49 -0500187{
188 sdbusplus::asio::getProperty<bool>(
189 *crow::connections::systemBus, service, pcieDevicePath,
190 "xyz.openbmc_project.Inventory.Item", "Present",
Ed Tanousac106bf2023-06-07 09:24:59 -0700191 [asyncResp](const boost::system::error_code& ec, const bool value) {
Lakshmi Yadlapatic6bb3282023-04-12 16:56:49 -0500192 if (ec)
193 {
194 if (ec.value() != EBADR)
195 {
196 BMCWEB_LOG_ERROR << "DBUS response error for State";
Ed Tanousac106bf2023-06-07 09:24:59 -0700197 messages::internalError(asyncResp->res);
Lakshmi Yadlapatic6bb3282023-04-12 16:56:49 -0500198 }
199 return;
200 }
201
202 if (!value)
203 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700204 asyncResp->res.jsonValue["Status"]["State"] = "Absent";
Lakshmi Yadlapatic6bb3282023-04-12 16:56:49 -0500205 }
206 });
207}
208
Ed Tanousac106bf2023-06-07 09:24:59 -0700209inline void
210 getPCIeDeviceAsset(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
211 const std::string& pcieDevicePath,
212 const std::string& service)
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600213{
214 sdbusplus::asio::getAllProperties(
215 *crow::connections::systemBus, service, pcieDevicePath,
216 "xyz.openbmc_project.Inventory.Decorator.Asset",
Ed Tanousac106bf2023-06-07 09:24:59 -0700217 [pcieDevicePath, asyncResp{asyncResp}](
218 const boost::system::error_code& ec,
219 const dbus::utility::DBusPropertiesMap& assetList) {
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600220 if (ec)
221 {
222 if (ec.value() != EBADR)
223 {
224 BMCWEB_LOG_ERROR << "DBUS response error for Properties"
225 << ec.value();
Ed Tanousac106bf2023-06-07 09:24:59 -0700226 messages::internalError(asyncResp->res);
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600227 }
228 return;
229 }
230
231 const std::string* manufacturer = nullptr;
232 const std::string* model = nullptr;
233 const std::string* partNumber = nullptr;
234 const std::string* serialNumber = nullptr;
235 const std::string* sparePartNumber = nullptr;
236
237 const bool success = sdbusplus::unpackPropertiesNoThrow(
238 dbus_utils::UnpackErrorPrinter(), assetList, "Manufacturer",
239 manufacturer, "Model", model, "PartNumber", partNumber,
240 "SerialNumber", serialNumber, "SparePartNumber", sparePartNumber);
241
242 if (!success)
243 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700244 messages::internalError(asyncResp->res);
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600245 return;
246 }
247
248 if (manufacturer != nullptr)
249 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700250 asyncResp->res.jsonValue["Manufacturer"] = *manufacturer;
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600251 }
252 if (model != nullptr)
253 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700254 asyncResp->res.jsonValue["Model"] = *model;
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600255 }
256
257 if (partNumber != nullptr)
258 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700259 asyncResp->res.jsonValue["PartNumber"] = *partNumber;
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600260 }
261
262 if (serialNumber != nullptr)
263 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700264 asyncResp->res.jsonValue["SerialNumber"] = *serialNumber;
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600265 }
266
267 if (sparePartNumber != nullptr && !sparePartNumber->empty())
268 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700269 asyncResp->res.jsonValue["SparePartNumber"] = *sparePartNumber;
SunnySrivastava1984913e7732021-01-27 06:23:24 -0600270 }
271 });
272}
273
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600274inline void addPCIeDeviceProperties(
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600275 crow::Response& resp, const std::string& pcieDeviceId,
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600276 const dbus::utility::DBusPropertiesMap& pcieDevProperties)
277{
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600278 const std::string* deviceType = nullptr;
279 const std::string* generationInUse = nullptr;
280 const int64_t* lanesInUse = nullptr;
281
282 const bool success = sdbusplus::unpackPropertiesNoThrow(
283 dbus_utils::UnpackErrorPrinter(), pcieDevProperties, "DeviceType",
284 deviceType, "GenerationInUse", generationInUse, "LanesInUse",
Lakshmi Yadlapatibad2c4a2023-04-07 09:14:37 -0500285 lanesInUse);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600286
287 if (!success)
288 {
289 messages::internalError(resp);
290 return;
291 }
292
293 if (deviceType != nullptr && !deviceType->empty())
294 {
295 resp.jsonValue["PCIeInterface"]["DeviceType"] = *deviceType;
296 }
297
298 if (generationInUse != nullptr)
299 {
300 std::optional<pcie_device::PCIeTypes> redfishGenerationInUse =
301 redfishPcieGenerationFromDbus(*generationInUse);
302
303 if (!redfishGenerationInUse)
304 {
305 messages::internalError(resp);
306 return;
307 }
308 if (*redfishGenerationInUse != pcie_device::PCIeTypes::Invalid)
309 {
310 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 Yadlapati543f9a72023-03-10 17:06:05 -0600365}
366
Ed Tanousac106bf2023-06-07 09:24:59 -0700367inline void
368 handlePCIeDeviceGet(App& app, const crow::Request& req,
369 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
370 const std::string& systemName,
371 const std::string& pcieDeviceId)
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600372{
Ed Tanousac106bf2023-06-07 09:24:59 -0700373 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600374 {
375 return;
376 }
377 if (systemName != "system")
378 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700379 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
380 systemName);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600381 return;
382 }
383
384 getValidPCIeDevicePath(
Ed Tanousac106bf2023-06-07 09:24:59 -0700385 pcieDeviceId, asyncResp,
386 [asyncResp, pcieDeviceId](const std::string& pcieDevicePath,
387 const std::string& service) {
388 addPCIeDeviceCommonProperties(asyncResp, pcieDeviceId);
389 getPCIeDeviceAsset(asyncResp, pcieDevicePath, service);
390 getPCIeDeviceState(asyncResp, pcieDevicePath, service);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600391 getPCIeDeviceProperties(
Ed Tanousac106bf2023-06-07 09:24:59 -0700392 asyncResp, pcieDevicePath, service,
393 [asyncResp, pcieDeviceId](
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600394 const dbus::utility::DBusPropertiesMap& pcieDevProperties) {
Ed Tanousac106bf2023-06-07 09:24:59 -0700395 addPCIeDeviceProperties(asyncResp->res, pcieDeviceId,
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600396 pcieDevProperties);
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600397 });
398 });
399}
400
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700401inline void requestRoutesSystemPCIeDevice(App& app)
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -0800402{
Ed Tanous22d268c2022-05-19 09:39:07 -0700403 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/PCIeDevices/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700404 .privileges(redfish::privileges::getPCIeDevice)
Ed Tanous002d39b2022-05-31 08:59:27 -0700405 .methods(boost::beast::http::verb::get)(
Lakshmi Yadlapati543f9a72023-03-10 17:06:05 -0600406 std::bind_front(handlePCIeDeviceGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700407}
408
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600409inline void addPCIeFunctionList(
410 crow::Response& res, const std::string& pcieDeviceId,
411 const dbus::utility::DBusPropertiesMap& pcieDevProperties)
412{
413 nlohmann::json& pcieFunctionList = res.jsonValue["Members"];
414 pcieFunctionList = nlohmann::json::array();
415 static constexpr const int maxPciFunctionNum = 8;
416
417 for (int functionNum = 0; functionNum < maxPciFunctionNum; functionNum++)
418 {
419 // Check if this function exists by
420 // looking for a device ID
Patrick Williams89492a12023-05-10 07:51:34 -0500421 std::string devIDProperty = "Function" + std::to_string(functionNum) +
422 "DeviceId";
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600423 const std::string* property = nullptr;
424 for (const auto& propEntry : pcieDevProperties)
425 {
426 if (propEntry.first == devIDProperty)
427 {
428 property = std::get_if<std::string>(&propEntry.second);
429 break;
430 }
431 }
432 if (property == nullptr || property->empty())
433 {
434 continue;
435 }
436
437 nlohmann::json::object_t pcieFunction;
Ed Tanousef4c65b2023-04-24 15:28:50 -0700438 pcieFunction["@odata.id"] = boost::urls::format(
439 "/redfish/v1/Systems/system/PCIeDevices/{}/PCIeFunctions/{}",
440 pcieDeviceId, std::to_string(functionNum));
Patrick Williamsb2ba3072023-05-12 10:27:39 -0500441 pcieFunctionList.emplace_back(std::move(pcieFunction));
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600442 }
443 res.jsonValue["PCIeFunctions@odata.count"] = pcieFunctionList.size();
444}
445
446inline void handlePCIeFunctionCollectionGet(
447 App& app, const crow::Request& req,
Ed Tanousac106bf2023-06-07 09:24:59 -0700448 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600449 const std::string& pcieDeviceId)
450{
Ed Tanousac106bf2023-06-07 09:24:59 -0700451 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600452 {
453 return;
454 }
455
456 getValidPCIeDevicePath(
Ed Tanousac106bf2023-06-07 09:24:59 -0700457 pcieDeviceId, asyncResp,
458 [asyncResp, pcieDeviceId](const std::string& pcieDevicePath,
459 const std::string& service) {
460 asyncResp->res.addHeader(
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600461 boost::beast::http::field::link,
462 "</redfish/v1/JsonSchemas/PCIeFunctionCollection/PCIeFunctionCollection.json>; rel=describedby");
Ed Tanousac106bf2023-06-07 09:24:59 -0700463 asyncResp->res.jsonValue["@odata.type"] =
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600464 "#PCIeFunctionCollection.PCIeFunctionCollection";
Ed Tanousac106bf2023-06-07 09:24:59 -0700465 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
Ed Tanousef4c65b2023-04-24 15:28:50 -0700466 "/redfish/v1/Systems/system/PCIeDevices/{}/PCIeFunctions",
467 pcieDeviceId);
Ed Tanousac106bf2023-06-07 09:24:59 -0700468 asyncResp->res.jsonValue["Name"] = "PCIe Function Collection";
469 asyncResp->res.jsonValue["Description"] =
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600470 "Collection of PCIe Functions for PCIe Device " + pcieDeviceId;
471 getPCIeDeviceProperties(
Ed Tanousac106bf2023-06-07 09:24:59 -0700472 asyncResp, pcieDevicePath, service,
473 [asyncResp, pcieDeviceId](
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600474 const dbus::utility::DBusPropertiesMap& pcieDevProperties) {
Ed Tanousac106bf2023-06-07 09:24:59 -0700475 addPCIeFunctionList(asyncResp->res, pcieDeviceId,
476 pcieDevProperties);
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600477 });
478 });
479}
480
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700481inline void requestRoutesSystemPCIeFunctionCollection(App& app)
482{
483 /**
484 * Functions triggers appropriate requests on DBus
485 */
486 BMCWEB_ROUTE(app,
487 "/redfish/v1/Systems/system/PCIeDevices/<str>/PCIeFunctions/")
Ed Tanoused398212021-06-09 17:05:54 -0700488 .privileges(redfish::privileges::getPCIeFunctionCollection)
Ed Tanous002d39b2022-05-31 08:59:27 -0700489 .methods(boost::beast::http::verb::get)(
Lakshmi Yadlapati35ad6132023-03-10 22:31:49 -0600490 std::bind_front(handlePCIeFunctionCollectionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700491}
492
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600493inline bool validatePCIeFunctionId(
Myung Baed5e74b82023-05-31 11:28:02 -0500494 uint64_t pcieFunctionId,
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600495 const dbus::utility::DBusPropertiesMap& pcieDevProperties)
496{
Myung Baed5e74b82023-05-31 11:28:02 -0500497 std::string functionName = "Function" + std::to_string(pcieFunctionId);
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600498 std::string devIDProperty = functionName + "DeviceId";
499
500 const std::string* devIdProperty = nullptr;
501 for (const auto& property : pcieDevProperties)
502 {
503 if (property.first == devIDProperty)
504 {
505 devIdProperty = std::get_if<std::string>(&property.second);
506 break;
507 }
508 }
509 return (devIdProperty != nullptr && !devIdProperty->empty());
510}
511
512inline void addPCIeFunctionProperties(
Ed Tanouse14742c2023-05-31 10:27:49 -0700513 crow::Response& resp, uint64_t pcieFunctionId,
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600514 const dbus::utility::DBusPropertiesMap& pcieDevProperties)
515{
Ed Tanouse14742c2023-05-31 10:27:49 -0700516 std::string functionName = "Function" + std::to_string(pcieFunctionId);
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600517 for (const auto& property : pcieDevProperties)
518 {
519 const std::string* strProperty =
520 std::get_if<std::string>(&property.second);
521
522 if (property.first == functionName + "DeviceId")
523 {
524 resp.jsonValue["DeviceId"] = *strProperty;
525 }
526 if (property.first == functionName + "VendorId")
527 {
528 resp.jsonValue["VendorId"] = *strProperty;
529 }
530 // TODO: FunctionType and DeviceClass are Redfish enums. The D-Bus
531 // property strings should be mapped correctly to ensure these
532 // strings are Redfish enum values. For now just check for empty.
533 if (property.first == functionName + "FunctionType")
534 {
535 if (!strProperty->empty())
536 {
537 resp.jsonValue["FunctionType"] = *strProperty;
538 }
539 }
540 if (property.first == functionName + "DeviceClass")
541 {
542 if (!strProperty->empty())
543 {
544 resp.jsonValue["DeviceClass"] = *strProperty;
545 }
546 }
547 if (property.first == functionName + "ClassCode")
548 {
549 resp.jsonValue["ClassCode"] = *strProperty;
550 }
551 if (property.first == functionName + "RevisionId")
552 {
553 resp.jsonValue["RevisionId"] = *strProperty;
554 }
555 if (property.first == functionName + "SubsystemId")
556 {
557 resp.jsonValue["SubsystemId"] = *strProperty;
558 }
559 if (property.first == functionName + "SubsystemVendorId")
560 {
561 resp.jsonValue["SubsystemVendorId"] = *strProperty;
562 }
563 }
564}
565
566inline void addPCIeFunctionCommonProperties(crow::Response& resp,
567 const std::string& pcieDeviceId,
Ed Tanouse14742c2023-05-31 10:27:49 -0700568 uint64_t pcieFunctionId)
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600569{
570 resp.addHeader(
571 boost::beast::http::field::link,
572 "</redfish/v1/JsonSchemas/PCIeFunction/PCIeFunction.json>; rel=describedby");
573 resp.jsonValue["@odata.type"] = "#PCIeFunction.v1_2_3.PCIeFunction";
Ed Tanousef4c65b2023-04-24 15:28:50 -0700574 resp.jsonValue["@odata.id"] = boost::urls::format(
575 "/redfish/v1/Systems/system/PCIeDevices/{}/PCIeFunctions/{}",
576 pcieDeviceId, pcieFunctionId);
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600577 resp.jsonValue["Name"] = "PCIe Function";
Ed Tanouse14742c2023-05-31 10:27:49 -0700578 resp.jsonValue["Id"] = std::to_string(pcieFunctionId);
579 resp.jsonValue["FunctionId"] = pcieFunctionId;
Ed Tanousef4c65b2023-04-24 15:28:50 -0700580 resp.jsonValue["Links"]["PCIeDevice"]["@odata.id"] = boost::urls::format(
581 "/redfish/v1/Systems/system/PCIeDevices/{}", pcieDeviceId);
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600582}
583
584inline void
585 handlePCIeFunctionGet(App& app, const crow::Request& req,
Ed Tanousac106bf2023-06-07 09:24:59 -0700586 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600587 const std::string& pcieDeviceId,
Ed Tanouse14742c2023-05-31 10:27:49 -0700588 const std::string& pcieFunctionIdStr)
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600589{
Ed Tanousac106bf2023-06-07 09:24:59 -0700590 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600591 {
592 return;
593 }
Ed Tanouse14742c2023-05-31 10:27:49 -0700594 uint64_t pcieFunctionId = 0;
595 std::from_chars_result result = std::from_chars(
596 &*pcieFunctionIdStr.begin(), &*pcieFunctionIdStr.end(), pcieFunctionId);
597 if (result.ec != std::errc{} || result.ptr != &*pcieFunctionIdStr.end())
598 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700599 messages::resourceNotFound(asyncResp->res, "PCIeFunction",
Ed Tanouse14742c2023-05-31 10:27:49 -0700600 pcieFunctionIdStr);
601 return;
602 }
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600603
Ed Tanousac106bf2023-06-07 09:24:59 -0700604 getValidPCIeDevicePath(pcieDeviceId, asyncResp,
605 [asyncResp, pcieDeviceId,
606 pcieFunctionId](const std::string& pcieDevicePath,
607 const std::string& service) {
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600608 getPCIeDeviceProperties(
Ed Tanousac106bf2023-06-07 09:24:59 -0700609 asyncResp, pcieDevicePath, service,
610 [asyncResp, pcieDeviceId, pcieFunctionId](
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600611 const dbus::utility::DBusPropertiesMap& pcieDevProperties) {
Ed Tanousac106bf2023-06-07 09:24:59 -0700612 addPCIeFunctionCommonProperties(asyncResp->res, pcieDeviceId,
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600613 pcieFunctionId);
Ed Tanousac106bf2023-06-07 09:24:59 -0700614 addPCIeFunctionProperties(asyncResp->res, pcieFunctionId,
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600615 pcieDevProperties);
616 });
Ed Tanousac106bf2023-06-07 09:24:59 -0700617 });
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600618}
619
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700620inline void requestRoutesSystemPCIeFunction(App& app)
621{
622 BMCWEB_ROUTE(
623 app,
624 "/redfish/v1/Systems/system/PCIeDevices/<str>/PCIeFunctions/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700625 .privileges(redfish::privileges::getPCIeFunction)
Ed Tanous002d39b2022-05-31 08:59:27 -0700626 .methods(boost::beast::http::verb::get)(
Lakshmi Yadlapati727a0462023-03-10 23:49:00 -0600627 std::bind_front(handlePCIeFunctionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700628}
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -0800629
630} // namespace redfish