140e9b92eSEd Tanous // SPDX-License-Identifier: Apache-2.0
240e9b92eSEd Tanous // SPDX-FileCopyrightText: Copyright OpenBMC Authors
340e9b92eSEd Tanous // SPDX-FileCopyrightText: Copyright 2018 Intel Corporation
4f5c9f8bdSJason M. Bills
5f5c9f8bdSJason M. Bills #pragma once
6f5c9f8bdSJason M. Bills
7*d7857201SEd Tanous #include "bmcweb_config.h"
8*d7857201SEd Tanous
93ccb3adbSEd Tanous #include "app.hpp"
10*d7857201SEd Tanous #include "async_resp.hpp"
117a1dbc48SGeorge Liu #include "dbus_utility.hpp"
12*d7857201SEd Tanous #include "error_messages.hpp"
13*d7857201SEd Tanous #include "generated/enums/pcie_device.hpp"
14*d7857201SEd Tanous #include "generated/enums/pcie_slots.hpp"
15539d8c6bSEd Tanous #include "generated/enums/resource.hpp"
16*d7857201SEd Tanous #include "http_request.hpp"
17*d7857201SEd Tanous #include "logging.hpp"
183ccb3adbSEd Tanous #include "query.hpp"
193ccb3adbSEd Tanous #include "registries/privilege_registry.hpp"
203ccb3adbSEd Tanous #include "utils/dbus_utils.hpp"
21c49c329dSLakshmi Yadlapati #include "utils/pcie_util.hpp"
220ec8b83dSEd Tanous
23*d7857201SEd Tanous #include <asm-generic/errno.h>
24*d7857201SEd Tanous
25*d7857201SEd Tanous #include <boost/beast/http/field.hpp>
26*d7857201SEd Tanous #include <boost/beast/http/verb.hpp>
27ef4c65b7SEd Tanous #include <boost/url/format.hpp>
28d1bde9e5SKrzysztof Grobelny #include <sdbusplus/unpack_properties.hpp>
29f5c9f8bdSJason M. Bills
30*d7857201SEd Tanous #include <array>
31*d7857201SEd Tanous #include <charconv>
32*d7857201SEd Tanous #include <cstddef>
33*d7857201SEd Tanous #include <cstdint>
34*d7857201SEd Tanous #include <format>
35*d7857201SEd Tanous #include <functional>
368c1d0549SMyung Bae #include <limits>
37*d7857201SEd Tanous #include <memory>
38*d7857201SEd Tanous #include <optional>
39*d7857201SEd Tanous #include <string>
40*d7857201SEd Tanous #include <string_view>
41*d7857201SEd Tanous #include <system_error>
42*d7857201SEd Tanous #include <utility>
43*d7857201SEd Tanous #include <variant>
448c1d0549SMyung Bae
45f5c9f8bdSJason M. Bills namespace redfish
46f5c9f8bdSJason M. Bills {
47f5c9f8bdSJason M. Bills
4889492a15SPatrick Williams static constexpr const char* inventoryPath = "/xyz/openbmc_project/inventory";
4994c3a10bSLakshmi Yadlapati static constexpr std::array<std::string_view, 1> pcieDeviceInterface = {
5094c3a10bSLakshmi Yadlapati "xyz.openbmc_project.Inventory.Item.PCIeDevice"};
51a5409991SLakshmi Yadlapati static constexpr std::array<std::string_view, 1> pcieSlotInterface = {
52a5409991SLakshmi Yadlapati "xyz.openbmc_project.Inventory.Item.PCIeSlot"};
53f5c9f8bdSJason M. Bills
handlePCIeDevicePath(const std::string & pcieDeviceId,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const dbus::utility::MapperGetSubTreePathsResponse & pcieDevicePaths,const std::function<void (const std::string & pcieDevicePath,const std::string & service)> & callback)544ff0f1f4SEd Tanous inline void handlePCIeDevicePath(
55543f9a75SLakshmi Yadlapati const std::string& pcieDeviceId,
56ac106bf6SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
57543f9a75SLakshmi Yadlapati const dbus::utility::MapperGetSubTreePathsResponse& pcieDevicePaths,
58543f9a75SLakshmi Yadlapati const std::function<void(const std::string& pcieDevicePath,
59543f9a75SLakshmi Yadlapati const std::string& service)>& callback)
60543f9a75SLakshmi Yadlapati
61543f9a75SLakshmi Yadlapati {
62543f9a75SLakshmi Yadlapati for (const std::string& pcieDevicePath : pcieDevicePaths)
63543f9a75SLakshmi Yadlapati {
64543f9a75SLakshmi Yadlapati std::string pciecDeviceName =
65543f9a75SLakshmi Yadlapati sdbusplus::message::object_path(pcieDevicePath).filename();
66543f9a75SLakshmi Yadlapati if (pciecDeviceName.empty() || pciecDeviceName != pcieDeviceId)
67543f9a75SLakshmi Yadlapati {
68543f9a75SLakshmi Yadlapati continue;
69543f9a75SLakshmi Yadlapati }
70543f9a75SLakshmi Yadlapati
71543f9a75SLakshmi Yadlapati dbus::utility::getDbusObject(
723a58c5a8SKonstantin Aladyshev pcieDevicePath, pcieDeviceInterface,
73ac106bf6SEd Tanous [pcieDevicePath, asyncResp,
74543f9a75SLakshmi Yadlapati callback](const boost::system::error_code& ec,
75543f9a75SLakshmi Yadlapati const dbus::utility::MapperGetObject& object) {
76543f9a75SLakshmi Yadlapati if (ec || object.empty())
77543f9a75SLakshmi Yadlapati {
7862598e31SEd Tanous BMCWEB_LOG_ERROR("DBUS response error {}", ec);
79ac106bf6SEd Tanous messages::internalError(asyncResp->res);
80543f9a75SLakshmi Yadlapati return;
81543f9a75SLakshmi Yadlapati }
82543f9a75SLakshmi Yadlapati callback(pcieDevicePath, object.begin()->first);
83543f9a75SLakshmi Yadlapati });
84543f9a75SLakshmi Yadlapati return;
85543f9a75SLakshmi Yadlapati }
86543f9a75SLakshmi Yadlapati
8762598e31SEd Tanous BMCWEB_LOG_WARNING("PCIe Device not found");
88ac106bf6SEd Tanous messages::resourceNotFound(asyncResp->res, "PCIeDevice", pcieDeviceId);
89543f9a75SLakshmi Yadlapati }
90543f9a75SLakshmi Yadlapati
getValidPCIeDevicePath(const std::string & pcieDeviceId,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::function<void (const std::string & pcieDevicePath,const std::string & service)> & callback)914ff0f1f4SEd Tanous inline void getValidPCIeDevicePath(
92543f9a75SLakshmi Yadlapati const std::string& pcieDeviceId,
93ac106bf6SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
94543f9a75SLakshmi Yadlapati const std::function<void(const std::string& pcieDevicePath,
95543f9a75SLakshmi Yadlapati const std::string& service)>& callback)
96543f9a75SLakshmi Yadlapati {
97543f9a75SLakshmi Yadlapati dbus::utility::getSubTreePaths(
9894c3a10bSLakshmi Yadlapati inventoryPath, 0, pcieDeviceInterface,
99ac106bf6SEd Tanous [pcieDeviceId, asyncResp,
100543f9a75SLakshmi Yadlapati callback](const boost::system::error_code& ec,
101543f9a75SLakshmi Yadlapati const dbus::utility::MapperGetSubTreePathsResponse&
102543f9a75SLakshmi Yadlapati pcieDevicePaths) {
103543f9a75SLakshmi Yadlapati if (ec)
104543f9a75SLakshmi Yadlapati {
10562598e31SEd Tanous BMCWEB_LOG_ERROR("D-Bus response error on GetSubTree {}", ec);
106ac106bf6SEd Tanous messages::internalError(asyncResp->res);
107543f9a75SLakshmi Yadlapati return;
108543f9a75SLakshmi Yadlapati }
109ac106bf6SEd Tanous handlePCIeDevicePath(pcieDeviceId, asyncResp, pcieDevicePaths,
110ac106bf6SEd Tanous callback);
111543f9a75SLakshmi Yadlapati return;
112543f9a75SLakshmi Yadlapati });
113543f9a75SLakshmi Yadlapati }
114543f9a75SLakshmi Yadlapati
handlePCIeDeviceCollectionGet(crow::App & app,const crow::Request & req,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & systemName)1154ff0f1f4SEd Tanous inline void handlePCIeDeviceCollectionGet(
116b38fa2abSLakshmi Yadlapati crow::App& app, const crow::Request& req,
117ac106bf6SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
118b38fa2abSLakshmi Yadlapati const std::string& systemName)
119b38fa2abSLakshmi Yadlapati {
120ac106bf6SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp))
121b38fa2abSLakshmi Yadlapati {
122b38fa2abSLakshmi Yadlapati return;
123b38fa2abSLakshmi Yadlapati }
12425b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1257f3e84a1SEd Tanous {
1267f3e84a1SEd Tanous // Option currently returns no systems. TBD
1277f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1287f3e84a1SEd Tanous systemName);
1297f3e84a1SEd Tanous return;
1307f3e84a1SEd Tanous }
131253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
132b38fa2abSLakshmi Yadlapati {
133ac106bf6SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem",
134ac106bf6SEd Tanous systemName);
135b38fa2abSLakshmi Yadlapati return;
136b38fa2abSLakshmi Yadlapati }
137543f9a75SLakshmi Yadlapati
138ac106bf6SEd Tanous asyncResp->res.addHeader(boost::beast::http::field::link,
139b38fa2abSLakshmi Yadlapati "</redfish/v1/JsonSchemas/PCIeDeviceCollection/"
140b38fa2abSLakshmi Yadlapati "PCIeDeviceCollection.json>; rel=describedby");
141ac106bf6SEd Tanous asyncResp->res.jsonValue["@odata.type"] =
142b38fa2abSLakshmi Yadlapati "#PCIeDeviceCollection.PCIeDeviceCollection";
143253f11b8SEd Tanous asyncResp->res.jsonValue["@odata.id"] = std::format(
144253f11b8SEd Tanous "/redfish/v1/Systems/{}/PCIeDevices", BMCWEB_REDFISH_SYSTEM_URI_NAME);
145ac106bf6SEd Tanous asyncResp->res.jsonValue["Name"] = "PCIe Device Collection";
146ac106bf6SEd Tanous asyncResp->res.jsonValue["Description"] = "Collection of PCIe Devices";
147b38fa2abSLakshmi Yadlapati
14870c4d545SLakshmi Yadlapati pcie_util::getPCIeDeviceList(asyncResp,
14970c4d545SLakshmi Yadlapati nlohmann::json::json_pointer("/Members"));
150b38fa2abSLakshmi Yadlapati }
151b38fa2abSLakshmi Yadlapati
requestRoutesSystemPCIeDeviceCollection(App & app)1527e860f15SJohn Edward Broadbent inline void requestRoutesSystemPCIeDeviceCollection(App& app)
153adbe192aSJason M. Bills {
154adbe192aSJason M. Bills /**
155adbe192aSJason M. Bills * Functions triggers appropriate requests on DBus
156adbe192aSJason M. Bills */
15722d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/PCIeDevices/")
158ed398213SEd Tanous .privileges(redfish::privileges::getPCIeDeviceCollection)
1597e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)(
160b38fa2abSLakshmi Yadlapati std::bind_front(handlePCIeDeviceCollectionGet, std::ref(app)));
161f5c9f8bdSJason M. Bills }
162f5c9f8bdSJason M. Bills
addPCIeSlotProperties(crow::Response & res,const boost::system::error_code & ec,const dbus::utility::DBusPropertiesMap & pcieSlotProperties)163a5409991SLakshmi Yadlapati inline void addPCIeSlotProperties(
164a5409991SLakshmi Yadlapati crow::Response& res, const boost::system::error_code& ec,
165a5409991SLakshmi Yadlapati const dbus::utility::DBusPropertiesMap& pcieSlotProperties)
166a5409991SLakshmi Yadlapati {
167a5409991SLakshmi Yadlapati if (ec)
168a5409991SLakshmi Yadlapati {
16962598e31SEd Tanous BMCWEB_LOG_ERROR("DBUS response error for getAllProperties{}",
17062598e31SEd Tanous ec.value());
171a5409991SLakshmi Yadlapati messages::internalError(res);
172a5409991SLakshmi Yadlapati return;
173a5409991SLakshmi Yadlapati }
174a5409991SLakshmi Yadlapati std::string generation;
175a5409991SLakshmi Yadlapati size_t lanes = 0;
176a5409991SLakshmi Yadlapati std::string slotType;
177a5409991SLakshmi Yadlapati
178a5409991SLakshmi Yadlapati bool success = sdbusplus::unpackPropertiesNoThrow(
179a5409991SLakshmi Yadlapati dbus_utils::UnpackErrorPrinter(), pcieSlotProperties, "Generation",
180a5409991SLakshmi Yadlapati generation, "Lanes", lanes, "SlotType", slotType);
181a5409991SLakshmi Yadlapati
182a5409991SLakshmi Yadlapati if (!success)
183a5409991SLakshmi Yadlapati {
184a5409991SLakshmi Yadlapati messages::internalError(res);
185a5409991SLakshmi Yadlapati return;
186a5409991SLakshmi Yadlapati }
187a5409991SLakshmi Yadlapati
188a5409991SLakshmi Yadlapati std::optional<pcie_device::PCIeTypes> pcieType =
189a5409991SLakshmi Yadlapati pcie_util::redfishPcieGenerationFromDbus(generation);
190a5409991SLakshmi Yadlapati if (!pcieType)
191a5409991SLakshmi Yadlapati {
19262598e31SEd Tanous BMCWEB_LOG_WARNING("Unknown PCIeType: {}", generation);
193a5409991SLakshmi Yadlapati }
194a5409991SLakshmi Yadlapati else
195a5409991SLakshmi Yadlapati {
196a5409991SLakshmi Yadlapati if (*pcieType == pcie_device::PCIeTypes::Invalid)
197a5409991SLakshmi Yadlapati {
19862598e31SEd Tanous BMCWEB_LOG_ERROR("Invalid PCIeType: {}", generation);
199a5409991SLakshmi Yadlapati messages::internalError(res);
200a5409991SLakshmi Yadlapati return;
201a5409991SLakshmi Yadlapati }
202a5409991SLakshmi Yadlapati res.jsonValue["Slot"]["PCIeType"] = *pcieType;
203a5409991SLakshmi Yadlapati }
204a5409991SLakshmi Yadlapati
20582f80326SKonstantin Aladyshev if (lanes != 0)
20682f80326SKonstantin Aladyshev {
207a5409991SLakshmi Yadlapati res.jsonValue["Slot"]["Lanes"] = lanes;
20882f80326SKonstantin Aladyshev }
209a5409991SLakshmi Yadlapati
210a5409991SLakshmi Yadlapati std::optional<pcie_slots::SlotTypes> redfishSlotType =
211a5409991SLakshmi Yadlapati pcie_util::dbusSlotTypeToRf(slotType);
212a5409991SLakshmi Yadlapati if (!redfishSlotType)
213a5409991SLakshmi Yadlapati {
21462598e31SEd Tanous BMCWEB_LOG_WARNING("Unknown PCIeSlot Type: {}", slotType);
215a5409991SLakshmi Yadlapati }
216a5409991SLakshmi Yadlapati else
217a5409991SLakshmi Yadlapati {
218a5409991SLakshmi Yadlapati if (*redfishSlotType == pcie_slots::SlotTypes::Invalid)
219a5409991SLakshmi Yadlapati {
22062598e31SEd Tanous BMCWEB_LOG_ERROR("Invalid PCIeSlot type: {}", slotType);
221a5409991SLakshmi Yadlapati messages::internalError(res);
222a5409991SLakshmi Yadlapati return;
223a5409991SLakshmi Yadlapati }
224a5409991SLakshmi Yadlapati res.jsonValue["Slot"]["SlotType"] = *redfishSlotType;
225a5409991SLakshmi Yadlapati }
226a5409991SLakshmi Yadlapati }
227a5409991SLakshmi Yadlapati
getPCIeDeviceSlotPath(const std::string & pcieDevicePath,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,std::function<void (const std::string & pcieDeviceSlot)> && callback)228a5409991SLakshmi Yadlapati inline void getPCIeDeviceSlotPath(
229a5409991SLakshmi Yadlapati const std::string& pcieDevicePath,
230a5409991SLakshmi Yadlapati const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
231a5409991SLakshmi Yadlapati std::function<void(const std::string& pcieDeviceSlot)>&& callback)
232a5409991SLakshmi Yadlapati {
233a5409991SLakshmi Yadlapati std::string associationPath = pcieDevicePath + "/contained_by";
234a5409991SLakshmi Yadlapati dbus::utility::getAssociatedSubTreePaths(
235a5409991SLakshmi Yadlapati associationPath, sdbusplus::message::object_path(inventoryPath), 0,
236a5409991SLakshmi Yadlapati pcieSlotInterface,
2378cb2c024SEd Tanous [callback = std::move(callback), asyncResp, pcieDevicePath](
238a5409991SLakshmi Yadlapati const boost::system::error_code& ec,
239a5409991SLakshmi Yadlapati const dbus::utility::MapperGetSubTreePathsResponse& endpoints) {
240a5409991SLakshmi Yadlapati if (ec)
241a5409991SLakshmi Yadlapati {
242a5409991SLakshmi Yadlapati if (ec.value() == EBADR)
243a5409991SLakshmi Yadlapati {
244a5409991SLakshmi Yadlapati // Missing association is not an error
245a5409991SLakshmi Yadlapati return;
246a5409991SLakshmi Yadlapati }
24762598e31SEd Tanous BMCWEB_LOG_ERROR(
24862598e31SEd Tanous "DBUS response error for getAssociatedSubTreePaths {}",
24962598e31SEd Tanous ec.value());
250a5409991SLakshmi Yadlapati messages::internalError(asyncResp->res);
251a5409991SLakshmi Yadlapati return;
252a5409991SLakshmi Yadlapati }
253a5409991SLakshmi Yadlapati if (endpoints.size() > 1)
254a5409991SLakshmi Yadlapati {
25562598e31SEd Tanous BMCWEB_LOG_ERROR(
256a6bd55b0SGunnar Mills "PCIeDevice {} is associated with more than one PCIeSlot: {}",
257a6bd55b0SGunnar Mills pcieDevicePath, endpoints.size());
258a5409991SLakshmi Yadlapati messages::internalError(asyncResp->res);
259a5409991SLakshmi Yadlapati return;
260a5409991SLakshmi Yadlapati }
261a5409991SLakshmi Yadlapati if (endpoints.empty())
262a5409991SLakshmi Yadlapati {
263bd79bce8SPatrick Williams // If the device doesn't have an association, return without
264bd79bce8SPatrick Williams // PCIe Slot properties
26562598e31SEd Tanous BMCWEB_LOG_DEBUG("PCIeDevice is not associated with PCIeSlot");
266a5409991SLakshmi Yadlapati return;
267a5409991SLakshmi Yadlapati }
268a5409991SLakshmi Yadlapati callback(endpoints[0]);
269a5409991SLakshmi Yadlapati });
270a5409991SLakshmi Yadlapati }
271a5409991SLakshmi Yadlapati
afterGetDbusObject(const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & pcieDeviceSlot,const boost::system::error_code & ec,const dbus::utility::MapperGetObject & object)272bd79bce8SPatrick Williams inline void afterGetDbusObject(
273bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
274bd79bce8SPatrick Williams const std::string& pcieDeviceSlot, const boost::system::error_code& ec,
275a5409991SLakshmi Yadlapati const dbus::utility::MapperGetObject& object)
276a5409991SLakshmi Yadlapati {
277a5409991SLakshmi Yadlapati if (ec || object.empty())
278a5409991SLakshmi Yadlapati {
27962598e31SEd Tanous BMCWEB_LOG_ERROR("DBUS response error for getDbusObject {}",
28062598e31SEd Tanous ec.value());
281a5409991SLakshmi Yadlapati messages::internalError(asyncResp->res);
282a5409991SLakshmi Yadlapati return;
283a5409991SLakshmi Yadlapati }
284deae6a78SEd Tanous dbus::utility::getAllProperties(
285deae6a78SEd Tanous object.begin()->first, pcieDeviceSlot,
286a5409991SLakshmi Yadlapati "xyz.openbmc_project.Inventory.Item.PCIeSlot",
287a5409991SLakshmi Yadlapati [asyncResp](
288a5409991SLakshmi Yadlapati const boost::system::error_code& ec2,
289a5409991SLakshmi Yadlapati const dbus::utility::DBusPropertiesMap& pcieSlotProperties) {
290a5409991SLakshmi Yadlapati addPCIeSlotProperties(asyncResp->res, ec2, pcieSlotProperties);
291a5409991SLakshmi Yadlapati });
292a5409991SLakshmi Yadlapati }
293a5409991SLakshmi Yadlapati
afterGetPCIeDeviceSlotPath(const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & pcieDeviceSlot)294a5409991SLakshmi Yadlapati inline void afterGetPCIeDeviceSlotPath(
295a5409991SLakshmi Yadlapati const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
296a5409991SLakshmi Yadlapati const std::string& pcieDeviceSlot)
297a5409991SLakshmi Yadlapati {
298a5409991SLakshmi Yadlapati dbus::utility::getDbusObject(
299a5409991SLakshmi Yadlapati pcieDeviceSlot, pcieSlotInterface,
300a5409991SLakshmi Yadlapati [asyncResp,
301a5409991SLakshmi Yadlapati pcieDeviceSlot](const boost::system::error_code& ec,
302a5409991SLakshmi Yadlapati const dbus::utility::MapperGetObject& object) {
303a5409991SLakshmi Yadlapati afterGetDbusObject(asyncResp, pcieDeviceSlot, ec, object);
304a5409991SLakshmi Yadlapati });
305a5409991SLakshmi Yadlapati }
306a5409991SLakshmi Yadlapati
getPCIeDeviceHealth(const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & pcieDevicePath,const std::string & service)307bd79bce8SPatrick Williams inline void getPCIeDeviceHealth(
308bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
309bd79bce8SPatrick Williams const std::string& pcieDevicePath, const std::string& service)
310e164f1b6SLakshmi Yadlapati {
311deae6a78SEd Tanous dbus::utility::getProperty<bool>(
312deae6a78SEd Tanous service, pcieDevicePath,
313e164f1b6SLakshmi Yadlapati "xyz.openbmc_project.State.Decorator.OperationalStatus", "Functional",
314e164f1b6SLakshmi Yadlapati [asyncResp](const boost::system::error_code& ec, const bool value) {
315e164f1b6SLakshmi Yadlapati if (ec)
316e164f1b6SLakshmi Yadlapati {
317e164f1b6SLakshmi Yadlapati if (ec.value() != EBADR)
318e164f1b6SLakshmi Yadlapati {
31962598e31SEd Tanous BMCWEB_LOG_ERROR("DBUS response error for Health {}",
32062598e31SEd Tanous ec.value());
321e164f1b6SLakshmi Yadlapati messages::internalError(asyncResp->res);
322e164f1b6SLakshmi Yadlapati }
323e164f1b6SLakshmi Yadlapati return;
324e164f1b6SLakshmi Yadlapati }
325e164f1b6SLakshmi Yadlapati
326e164f1b6SLakshmi Yadlapati if (!value)
327e164f1b6SLakshmi Yadlapati {
328539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["Health"] =
329539d8c6bSEd Tanous resource::Health::Critical;
330e164f1b6SLakshmi Yadlapati }
331e164f1b6SLakshmi Yadlapati });
332e164f1b6SLakshmi Yadlapati }
333e164f1b6SLakshmi Yadlapati
getPCIeDeviceState(const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & pcieDevicePath,const std::string & service)334bd79bce8SPatrick Williams inline void getPCIeDeviceState(
335bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
336bd79bce8SPatrick Williams const std::string& pcieDevicePath, const std::string& service)
337c6bb3285SLakshmi Yadlapati {
338deae6a78SEd Tanous dbus::utility::getProperty<bool>(
339deae6a78SEd Tanous service, pcieDevicePath, "xyz.openbmc_project.Inventory.Item",
340deae6a78SEd Tanous "Present",
341a5409991SLakshmi Yadlapati [asyncResp](const boost::system::error_code& ec, bool value) {
342c6bb3285SLakshmi Yadlapati if (ec)
343c6bb3285SLakshmi Yadlapati {
344c6bb3285SLakshmi Yadlapati if (ec.value() != EBADR)
345c6bb3285SLakshmi Yadlapati {
34662598e31SEd Tanous BMCWEB_LOG_ERROR("DBUS response error for State");
347ac106bf6SEd Tanous messages::internalError(asyncResp->res);
348c6bb3285SLakshmi Yadlapati }
349c6bb3285SLakshmi Yadlapati return;
350c6bb3285SLakshmi Yadlapati }
351c6bb3285SLakshmi Yadlapati
352c6bb3285SLakshmi Yadlapati if (!value)
353c6bb3285SLakshmi Yadlapati {
354539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["State"] =
355539d8c6bSEd Tanous resource::State::Absent;
356c6bb3285SLakshmi Yadlapati }
357c6bb3285SLakshmi Yadlapati });
358c6bb3285SLakshmi Yadlapati }
359c6bb3285SLakshmi Yadlapati
getPCIeDeviceAsset(const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & pcieDevicePath,const std::string & service)360bd79bce8SPatrick Williams inline void getPCIeDeviceAsset(
361bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
362bd79bce8SPatrick Williams const std::string& pcieDevicePath, const std::string& service)
363913e7732SSunnySrivastava1984 {
364deae6a78SEd Tanous dbus::utility::getAllProperties(
365deae6a78SEd Tanous service, pcieDevicePath,
366913e7732SSunnySrivastava1984 "xyz.openbmc_project.Inventory.Decorator.Asset",
367ac106bf6SEd Tanous [pcieDevicePath, asyncResp{asyncResp}](
368ac106bf6SEd Tanous const boost::system::error_code& ec,
369913e7732SSunnySrivastava1984 const dbus::utility::DBusPropertiesMap& assetList) {
370913e7732SSunnySrivastava1984 if (ec)
371913e7732SSunnySrivastava1984 {
372913e7732SSunnySrivastava1984 if (ec.value() != EBADR)
373913e7732SSunnySrivastava1984 {
37462598e31SEd Tanous BMCWEB_LOG_ERROR("DBUS response error for Properties{}",
37562598e31SEd Tanous ec.value());
376ac106bf6SEd Tanous messages::internalError(asyncResp->res);
377913e7732SSunnySrivastava1984 }
378913e7732SSunnySrivastava1984 return;
379913e7732SSunnySrivastava1984 }
380913e7732SSunnySrivastava1984
381913e7732SSunnySrivastava1984 const std::string* manufacturer = nullptr;
382913e7732SSunnySrivastava1984 const std::string* model = nullptr;
383913e7732SSunnySrivastava1984 const std::string* partNumber = nullptr;
384913e7732SSunnySrivastava1984 const std::string* serialNumber = nullptr;
385913e7732SSunnySrivastava1984 const std::string* sparePartNumber = nullptr;
386913e7732SSunnySrivastava1984
387913e7732SSunnySrivastava1984 const bool success = sdbusplus::unpackPropertiesNoThrow(
388913e7732SSunnySrivastava1984 dbus_utils::UnpackErrorPrinter(), assetList, "Manufacturer",
389913e7732SSunnySrivastava1984 manufacturer, "Model", model, "PartNumber", partNumber,
390bd79bce8SPatrick Williams "SerialNumber", serialNumber, "SparePartNumber",
391bd79bce8SPatrick Williams sparePartNumber);
392913e7732SSunnySrivastava1984
393913e7732SSunnySrivastava1984 if (!success)
394913e7732SSunnySrivastava1984 {
395ac106bf6SEd Tanous messages::internalError(asyncResp->res);
396913e7732SSunnySrivastava1984 return;
397913e7732SSunnySrivastava1984 }
398913e7732SSunnySrivastava1984
399913e7732SSunnySrivastava1984 if (manufacturer != nullptr)
400913e7732SSunnySrivastava1984 {
401ac106bf6SEd Tanous asyncResp->res.jsonValue["Manufacturer"] = *manufacturer;
402913e7732SSunnySrivastava1984 }
403913e7732SSunnySrivastava1984 if (model != nullptr)
404913e7732SSunnySrivastava1984 {
405ac106bf6SEd Tanous asyncResp->res.jsonValue["Model"] = *model;
406913e7732SSunnySrivastava1984 }
407913e7732SSunnySrivastava1984
408913e7732SSunnySrivastava1984 if (partNumber != nullptr)
409913e7732SSunnySrivastava1984 {
410ac106bf6SEd Tanous asyncResp->res.jsonValue["PartNumber"] = *partNumber;
411913e7732SSunnySrivastava1984 }
412913e7732SSunnySrivastava1984
413913e7732SSunnySrivastava1984 if (serialNumber != nullptr)
414913e7732SSunnySrivastava1984 {
415ac106bf6SEd Tanous asyncResp->res.jsonValue["SerialNumber"] = *serialNumber;
416913e7732SSunnySrivastava1984 }
417913e7732SSunnySrivastava1984
418913e7732SSunnySrivastava1984 if (sparePartNumber != nullptr && !sparePartNumber->empty())
419913e7732SSunnySrivastava1984 {
420ac106bf6SEd Tanous asyncResp->res.jsonValue["SparePartNumber"] = *sparePartNumber;
421913e7732SSunnySrivastava1984 }
422913e7732SSunnySrivastava1984 });
423913e7732SSunnySrivastava1984 }
424913e7732SSunnySrivastava1984
addPCIeDeviceProperties(const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & pcieDeviceId,const dbus::utility::DBusPropertiesMap & pcieDevProperties)425543f9a75SLakshmi Yadlapati inline void addPCIeDeviceProperties(
426a5409991SLakshmi Yadlapati const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
427a5409991SLakshmi Yadlapati const std::string& pcieDeviceId,
428543f9a75SLakshmi Yadlapati const dbus::utility::DBusPropertiesMap& pcieDevProperties)
429f5c9f8bdSJason M. Bills {
430d1bde9e5SKrzysztof Grobelny const std::string* generationInUse = nullptr;
431814bf20aSKonstantin Aladyshev const std::string* generationSupported = nullptr;
4329bb0a7feSKonstantin Aladyshev const size_t* lanesInUse = nullptr;
433814bf20aSKonstantin Aladyshev const size_t* maxLanes = nullptr;
434d1bde9e5SKrzysztof Grobelny
435d1bde9e5SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow(
436609ba4c9SEd Tanous dbus_utils::UnpackErrorPrinter(), pcieDevProperties, "GenerationInUse",
437609ba4c9SEd Tanous generationInUse, "GenerationSupported", generationSupported,
438609ba4c9SEd Tanous "LanesInUse", lanesInUse, "MaxLanes", maxLanes);
439d1bde9e5SKrzysztof Grobelny
440d1bde9e5SKrzysztof Grobelny if (!success)
441d1bde9e5SKrzysztof Grobelny {
442a5409991SLakshmi Yadlapati messages::internalError(asyncResp->res);
443d1bde9e5SKrzysztof Grobelny return;
444d1bde9e5SKrzysztof Grobelny }
445d1bde9e5SKrzysztof Grobelny
446d1bde9e5SKrzysztof Grobelny if (generationInUse != nullptr)
447d1bde9e5SKrzysztof Grobelny {
4480ec8b83dSEd Tanous std::optional<pcie_device::PCIeTypes> redfishGenerationInUse =
449c49c329dSLakshmi Yadlapati pcie_util::redfishPcieGenerationFromDbus(*generationInUse);
450543f9a75SLakshmi Yadlapati
451d1bde9e5SKrzysztof Grobelny if (!redfishGenerationInUse)
452d1bde9e5SKrzysztof Grobelny {
45362598e31SEd Tanous BMCWEB_LOG_WARNING("Unknown PCIe Device Generation: {}",
45462598e31SEd Tanous *generationInUse);
455cf3b484eSLakshmi Yadlapati }
456cf3b484eSLakshmi Yadlapati else
457cf3b484eSLakshmi Yadlapati {
458cf3b484eSLakshmi Yadlapati if (*redfishGenerationInUse == pcie_device::PCIeTypes::Invalid)
459cf3b484eSLakshmi Yadlapati {
46062598e31SEd Tanous BMCWEB_LOG_ERROR("Invalid PCIe Device Generation: {}",
46162598e31SEd Tanous *generationInUse);
462a5409991SLakshmi Yadlapati messages::internalError(asyncResp->res);
463d1bde9e5SKrzysztof Grobelny return;
464d1bde9e5SKrzysztof Grobelny }
465a5409991SLakshmi Yadlapati asyncResp->res.jsonValue["PCIeInterface"]["PCIeType"] =
466d1bde9e5SKrzysztof Grobelny *redfishGenerationInUse;
467d1bde9e5SKrzysztof Grobelny }
468a9f68bb5STony Lee }
469d1bde9e5SKrzysztof Grobelny
470814bf20aSKonstantin Aladyshev if (generationSupported != nullptr)
471814bf20aSKonstantin Aladyshev {
472814bf20aSKonstantin Aladyshev std::optional<pcie_device::PCIeTypes> redfishGenerationSupported =
473814bf20aSKonstantin Aladyshev pcie_util::redfishPcieGenerationFromDbus(*generationSupported);
474814bf20aSKonstantin Aladyshev
475814bf20aSKonstantin Aladyshev if (!redfishGenerationSupported)
476814bf20aSKonstantin Aladyshev {
47762598e31SEd Tanous BMCWEB_LOG_WARNING("Unknown PCIe Device Generation: {}",
47862598e31SEd Tanous *generationSupported);
479814bf20aSKonstantin Aladyshev }
480814bf20aSKonstantin Aladyshev else
481814bf20aSKonstantin Aladyshev {
482814bf20aSKonstantin Aladyshev if (*redfishGenerationSupported == pcie_device::PCIeTypes::Invalid)
483814bf20aSKonstantin Aladyshev {
48462598e31SEd Tanous BMCWEB_LOG_ERROR("Invalid PCIe Device Generation: {}",
48562598e31SEd Tanous *generationSupported);
486814bf20aSKonstantin Aladyshev messages::internalError(asyncResp->res);
487814bf20aSKonstantin Aladyshev return;
488814bf20aSKonstantin Aladyshev }
489814bf20aSKonstantin Aladyshev asyncResp->res.jsonValue["PCIeInterface"]["MaxPCIeType"] =
490814bf20aSKonstantin Aladyshev *redfishGenerationSupported;
491814bf20aSKonstantin Aladyshev }
492814bf20aSKonstantin Aladyshev }
493814bf20aSKonstantin Aladyshev
4948c1d0549SMyung Bae if (lanesInUse != nullptr)
495543f9a75SLakshmi Yadlapati {
4968c1d0549SMyung Bae if (*lanesInUse == std::numeric_limits<size_t>::max())
4978c1d0549SMyung Bae {
4988c1d0549SMyung Bae // The default value of LanesInUse is "maxint", and the field will
4998c1d0549SMyung Bae // be null if it is a default value.
5008c1d0549SMyung Bae asyncResp->res.jsonValue["PCIeInterface"]["LanesInUse"] = nullptr;
5018c1d0549SMyung Bae }
5028c1d0549SMyung Bae else
5038c1d0549SMyung Bae {
5048c1d0549SMyung Bae asyncResp->res.jsonValue["PCIeInterface"]["LanesInUse"] =
5058c1d0549SMyung Bae *lanesInUse;
5068c1d0549SMyung Bae }
507543f9a75SLakshmi Yadlapati }
508814bf20aSKonstantin Aladyshev // The default value of MaxLanes is 0, and the field will be
509814bf20aSKonstantin Aladyshev // left as off if it is a default value.
510814bf20aSKonstantin Aladyshev if (maxLanes != nullptr && *maxLanes != 0)
511814bf20aSKonstantin Aladyshev {
512814bf20aSKonstantin Aladyshev asyncResp->res.jsonValue["PCIeInterface"]["MaxLanes"] = *maxLanes;
513814bf20aSKonstantin Aladyshev }
514543f9a75SLakshmi Yadlapati
515a5409991SLakshmi Yadlapati asyncResp->res.jsonValue["PCIeFunctions"]["@odata.id"] =
516a5409991SLakshmi Yadlapati boost::urls::format(
517253f11b8SEd Tanous "/redfish/v1/Systems/{}/PCIeDevices/{}/PCIeFunctions",
518253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME, pcieDeviceId);
519d1bde9e5SKrzysztof Grobelny }
520d1bde9e5SKrzysztof Grobelny
getPCIeDeviceProperties(const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & pcieDevicePath,const std::string & service,const std::function<void (const dbus::utility::DBusPropertiesMap & pcieDevProperties)> && callback)521543f9a75SLakshmi Yadlapati inline void getPCIeDeviceProperties(
522ac106bf6SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
523543f9a75SLakshmi Yadlapati const std::string& pcieDevicePath, const std::string& service,
524543f9a75SLakshmi Yadlapati const std::function<void(
525543f9a75SLakshmi Yadlapati const dbus::utility::DBusPropertiesMap& pcieDevProperties)>&& callback)
526d1bde9e5SKrzysztof Grobelny {
527deae6a78SEd Tanous dbus::utility::getAllProperties(
528deae6a78SEd Tanous service, pcieDevicePath,
529543f9a75SLakshmi Yadlapati "xyz.openbmc_project.Inventory.Item.PCIeDevice",
530ac106bf6SEd Tanous [asyncResp,
531543f9a75SLakshmi Yadlapati callback](const boost::system::error_code& ec,
532543f9a75SLakshmi Yadlapati const dbus::utility::DBusPropertiesMap& pcieDevProperties) {
533543f9a75SLakshmi Yadlapati if (ec)
534543f9a75SLakshmi Yadlapati {
535543f9a75SLakshmi Yadlapati if (ec.value() != EBADR)
536543f9a75SLakshmi Yadlapati {
53762598e31SEd Tanous BMCWEB_LOG_ERROR("DBUS response error for Properties");
538ac106bf6SEd Tanous messages::internalError(asyncResp->res);
539543f9a75SLakshmi Yadlapati }
540543f9a75SLakshmi Yadlapati return;
541543f9a75SLakshmi Yadlapati }
542543f9a75SLakshmi Yadlapati callback(pcieDevProperties);
543543f9a75SLakshmi Yadlapati });
544d1bde9e5SKrzysztof Grobelny }
545d1bde9e5SKrzysztof Grobelny
addPCIeDeviceCommonProperties(const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & pcieDeviceId)546543f9a75SLakshmi Yadlapati inline void addPCIeDeviceCommonProperties(
547ac106bf6SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
548543f9a75SLakshmi Yadlapati const std::string& pcieDeviceId)
549543f9a75SLakshmi Yadlapati {
550ac106bf6SEd Tanous asyncResp->res.addHeader(
551543f9a75SLakshmi Yadlapati boost::beast::http::field::link,
552543f9a75SLakshmi Yadlapati "</redfish/v1/JsonSchemas/PCIeDevice/PCIeDevice.json>; rel=describedby");
553ac106bf6SEd Tanous asyncResp->res.jsonValue["@odata.type"] = "#PCIeDevice.v1_9_0.PCIeDevice";
554253f11b8SEd Tanous asyncResp->res.jsonValue["@odata.id"] =
555253f11b8SEd Tanous boost::urls::format("/redfish/v1/Systems/{}/PCIeDevices/{}",
556253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME, pcieDeviceId);
557ac106bf6SEd Tanous asyncResp->res.jsonValue["Name"] = "PCIe Device";
558ac106bf6SEd Tanous asyncResp->res.jsonValue["Id"] = pcieDeviceId;
559539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled;
560539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["Health"] = resource::Health::OK;
561543f9a75SLakshmi Yadlapati }
5621476687dSEd Tanous
afterGetValidPcieDevicePath(const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & pcieDeviceId,const std::string & pcieDevicePath,const std::string & service)563a5409991SLakshmi Yadlapati inline void afterGetValidPcieDevicePath(
564a5409991SLakshmi Yadlapati const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
565a5409991SLakshmi Yadlapati const std::string& pcieDeviceId, const std::string& pcieDevicePath,
566a5409991SLakshmi Yadlapati const std::string& service)
567a5409991SLakshmi Yadlapati {
568a5409991SLakshmi Yadlapati addPCIeDeviceCommonProperties(asyncResp, pcieDeviceId);
569a5409991SLakshmi Yadlapati getPCIeDeviceAsset(asyncResp, pcieDevicePath, service);
570a5409991SLakshmi Yadlapati getPCIeDeviceState(asyncResp, pcieDevicePath, service);
571a5409991SLakshmi Yadlapati getPCIeDeviceHealth(asyncResp, pcieDevicePath, service);
572a5409991SLakshmi Yadlapati getPCIeDeviceProperties(
573a5409991SLakshmi Yadlapati asyncResp, pcieDevicePath, service,
574a5409991SLakshmi Yadlapati std::bind_front(addPCIeDeviceProperties, asyncResp, pcieDeviceId));
575a5409991SLakshmi Yadlapati getPCIeDeviceSlotPath(
576a5409991SLakshmi Yadlapati pcieDevicePath, asyncResp,
577a5409991SLakshmi Yadlapati std::bind_front(afterGetPCIeDeviceSlotPath, asyncResp));
578a5409991SLakshmi Yadlapati }
579a5409991SLakshmi Yadlapati
handlePCIeDeviceGet(App & app,const crow::Request & req,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & systemName,const std::string & pcieDeviceId)580bd79bce8SPatrick Williams inline void handlePCIeDeviceGet(
581bd79bce8SPatrick Williams App& app, const crow::Request& req,
582ac106bf6SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
583bd79bce8SPatrick Williams const std::string& systemName, const std::string& pcieDeviceId)
584543f9a75SLakshmi Yadlapati {
585ac106bf6SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp))
586543f9a75SLakshmi Yadlapati {
587543f9a75SLakshmi Yadlapati return;
588543f9a75SLakshmi Yadlapati }
58925b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
5907f3e84a1SEd Tanous {
5917f3e84a1SEd Tanous // Option currently returns no systems. TBD
5927f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem",
5937f3e84a1SEd Tanous systemName);
5947f3e84a1SEd Tanous return;
5957f3e84a1SEd Tanous }
596253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
597543f9a75SLakshmi Yadlapati {
598ac106bf6SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem",
599ac106bf6SEd Tanous systemName);
600543f9a75SLakshmi Yadlapati return;
601543f9a75SLakshmi Yadlapati }
602543f9a75SLakshmi Yadlapati
603543f9a75SLakshmi Yadlapati getValidPCIeDevicePath(
604ac106bf6SEd Tanous pcieDeviceId, asyncResp,
605a5409991SLakshmi Yadlapati std::bind_front(afterGetValidPcieDevicePath, asyncResp, pcieDeviceId));
606543f9a75SLakshmi Yadlapati }
607543f9a75SLakshmi Yadlapati
requestRoutesSystemPCIeDevice(App & app)608543f9a75SLakshmi Yadlapati inline void requestRoutesSystemPCIeDevice(App& app)
609543f9a75SLakshmi Yadlapati {
610543f9a75SLakshmi Yadlapati BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/PCIeDevices/<str>/")
611543f9a75SLakshmi Yadlapati .privileges(redfish::privileges::getPCIeDevice)
612543f9a75SLakshmi Yadlapati .methods(boost::beast::http::verb::get)(
613543f9a75SLakshmi Yadlapati std::bind_front(handlePCIeDeviceGet, std::ref(app)));
614dede6a98SJason M. Bills }
615dede6a98SJason M. Bills
addPCIeFunctionList(crow::Response & res,const std::string & pcieDeviceId,const dbus::utility::DBusPropertiesMap & pcieDevProperties)61635ad613dSLakshmi Yadlapati inline void addPCIeFunctionList(
61735ad613dSLakshmi Yadlapati crow::Response& res, const std::string& pcieDeviceId,
61835ad613dSLakshmi Yadlapati const dbus::utility::DBusPropertiesMap& pcieDevProperties)
61935ad613dSLakshmi Yadlapati {
62035ad613dSLakshmi Yadlapati nlohmann::json& pcieFunctionList = res.jsonValue["Members"];
62135ad613dSLakshmi Yadlapati pcieFunctionList = nlohmann::json::array();
62235ad613dSLakshmi Yadlapati static constexpr const int maxPciFunctionNum = 8;
62335ad613dSLakshmi Yadlapati
62435ad613dSLakshmi Yadlapati for (int functionNum = 0; functionNum < maxPciFunctionNum; functionNum++)
62535ad613dSLakshmi Yadlapati {
62635ad613dSLakshmi Yadlapati // Check if this function exists by
62735ad613dSLakshmi Yadlapati // looking for a device ID
628bd79bce8SPatrick Williams std::string devIDProperty =
629bd79bce8SPatrick Williams "Function" + std::to_string(functionNum) + "DeviceId";
63035ad613dSLakshmi Yadlapati const std::string* property = nullptr;
63135ad613dSLakshmi Yadlapati for (const auto& propEntry : pcieDevProperties)
63235ad613dSLakshmi Yadlapati {
63335ad613dSLakshmi Yadlapati if (propEntry.first == devIDProperty)
63435ad613dSLakshmi Yadlapati {
63535ad613dSLakshmi Yadlapati property = std::get_if<std::string>(&propEntry.second);
63635ad613dSLakshmi Yadlapati break;
63735ad613dSLakshmi Yadlapati }
63835ad613dSLakshmi Yadlapati }
63935ad613dSLakshmi Yadlapati if (property == nullptr || property->empty())
64035ad613dSLakshmi Yadlapati {
64135ad613dSLakshmi Yadlapati continue;
64235ad613dSLakshmi Yadlapati }
64335ad613dSLakshmi Yadlapati
64435ad613dSLakshmi Yadlapati nlohmann::json::object_t pcieFunction;
645ef4c65b7SEd Tanous pcieFunction["@odata.id"] = boost::urls::format(
646253f11b8SEd Tanous "/redfish/v1/Systems/{}/PCIeDevices/{}/PCIeFunctions/{}",
647253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME, pcieDeviceId,
648253f11b8SEd Tanous std::to_string(functionNum));
649b2ba3072SPatrick Williams pcieFunctionList.emplace_back(std::move(pcieFunction));
65035ad613dSLakshmi Yadlapati }
65135ad613dSLakshmi Yadlapati res.jsonValue["PCIeFunctions@odata.count"] = pcieFunctionList.size();
65235ad613dSLakshmi Yadlapati }
65335ad613dSLakshmi Yadlapati
handlePCIeFunctionCollectionGet(App & app,const crow::Request & req,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & systemName,const std::string & pcieDeviceId)65435ad613dSLakshmi Yadlapati inline void handlePCIeFunctionCollectionGet(
65535ad613dSLakshmi Yadlapati App& app, const crow::Request& req,
656ac106bf6SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
6577f3e84a1SEd Tanous const std::string& systemName, const std::string& pcieDeviceId)
65835ad613dSLakshmi Yadlapati {
659ac106bf6SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp))
66035ad613dSLakshmi Yadlapati {
66135ad613dSLakshmi Yadlapati return;
66235ad613dSLakshmi Yadlapati }
66325b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
6647f3e84a1SEd Tanous {
6657f3e84a1SEd Tanous // Option currently returns no systems. TBD
6667f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem",
6677f3e84a1SEd Tanous systemName);
6687f3e84a1SEd Tanous return;
6697f3e84a1SEd Tanous }
67035ad613dSLakshmi Yadlapati
67135ad613dSLakshmi Yadlapati getValidPCIeDevicePath(
672ac106bf6SEd Tanous pcieDeviceId, asyncResp,
673ac106bf6SEd Tanous [asyncResp, pcieDeviceId](const std::string& pcieDevicePath,
67435ad613dSLakshmi Yadlapati const std::string& service) {
675ac106bf6SEd Tanous asyncResp->res.addHeader(
67635ad613dSLakshmi Yadlapati boost::beast::http::field::link,
67735ad613dSLakshmi Yadlapati "</redfish/v1/JsonSchemas/PCIeFunctionCollection/PCIeFunctionCollection.json>; rel=describedby");
678ac106bf6SEd Tanous asyncResp->res.jsonValue["@odata.type"] =
67935ad613dSLakshmi Yadlapati "#PCIeFunctionCollection.PCIeFunctionCollection";
680ac106bf6SEd Tanous asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
681253f11b8SEd Tanous "/redfish/v1/Systems/{}/PCIeDevices/{}/PCIeFunctions",
682253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME, pcieDeviceId);
683ac106bf6SEd Tanous asyncResp->res.jsonValue["Name"] = "PCIe Function Collection";
684ac106bf6SEd Tanous asyncResp->res.jsonValue["Description"] =
68535ad613dSLakshmi Yadlapati "Collection of PCIe Functions for PCIe Device " + pcieDeviceId;
68635ad613dSLakshmi Yadlapati getPCIeDeviceProperties(
687ac106bf6SEd Tanous asyncResp, pcieDevicePath, service,
688ac106bf6SEd Tanous [asyncResp, pcieDeviceId](
68935ad613dSLakshmi Yadlapati const dbus::utility::DBusPropertiesMap& pcieDevProperties) {
690ac106bf6SEd Tanous addPCIeFunctionList(asyncResp->res, pcieDeviceId,
691ac106bf6SEd Tanous pcieDevProperties);
69235ad613dSLakshmi Yadlapati });
69335ad613dSLakshmi Yadlapati });
69435ad613dSLakshmi Yadlapati }
69535ad613dSLakshmi Yadlapati
requestRoutesSystemPCIeFunctionCollection(App & app)6967e860f15SJohn Edward Broadbent inline void requestRoutesSystemPCIeFunctionCollection(App& app)
6977e860f15SJohn Edward Broadbent {
698dede6a98SJason M. Bills /**
699dede6a98SJason M. Bills * Functions triggers appropriate requests on DBus
700dede6a98SJason M. Bills */
7017e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app,
7027f3e84a1SEd Tanous "/redfish/v1/Systems/<str>/PCIeDevices/<str>/PCIeFunctions/")
703ed398213SEd Tanous .privileges(redfish::privileges::getPCIeFunctionCollection)
704002d39b4SEd Tanous .methods(boost::beast::http::verb::get)(
70535ad613dSLakshmi Yadlapati std::bind_front(handlePCIeFunctionCollectionGet, std::ref(app)));
7067e860f15SJohn Edward Broadbent }
7077e860f15SJohn Edward Broadbent
validatePCIeFunctionId(uint64_t pcieFunctionId,const dbus::utility::DBusPropertiesMap & pcieDevProperties)708727a046cSLakshmi Yadlapati inline bool validatePCIeFunctionId(
709d5e74b80SMyung Bae uint64_t pcieFunctionId,
710727a046cSLakshmi Yadlapati const dbus::utility::DBusPropertiesMap& pcieDevProperties)
7117e860f15SJohn Edward Broadbent {
712d5e74b80SMyung Bae std::string functionName = "Function" + std::to_string(pcieFunctionId);
713b9d36b47SEd Tanous std::string devIDProperty = functionName + "DeviceId";
714b9d36b47SEd Tanous
715b9d36b47SEd Tanous const std::string* devIdProperty = nullptr;
716b9d36b47SEd Tanous for (const auto& property : pcieDevProperties)
717b9d36b47SEd Tanous {
718b9d36b47SEd Tanous if (property.first == devIDProperty)
719b9d36b47SEd Tanous {
720002d39b4SEd Tanous devIdProperty = std::get_if<std::string>(&property.second);
721727a046cSLakshmi Yadlapati break;
722b9d36b47SEd Tanous }
723b9d36b47SEd Tanous }
724727a046cSLakshmi Yadlapati return (devIdProperty != nullptr && !devIdProperty->empty());
725727a046cSLakshmi Yadlapati }
726727a046cSLakshmi Yadlapati
addPCIeFunctionProperties(crow::Response & resp,uint64_t pcieFunctionId,const dbus::utility::DBusPropertiesMap & pcieDevProperties)727727a046cSLakshmi Yadlapati inline void addPCIeFunctionProperties(
728e14742caSEd Tanous crow::Response& resp, uint64_t pcieFunctionId,
729727a046cSLakshmi Yadlapati const dbus::utility::DBusPropertiesMap& pcieDevProperties)
730f5c9f8bdSJason M. Bills {
731e14742caSEd Tanous std::string functionName = "Function" + std::to_string(pcieFunctionId);
732b9d36b47SEd Tanous for (const auto& property : pcieDevProperties)
733f5c9f8bdSJason M. Bills {
734b9d36b47SEd Tanous const std::string* strProperty =
735b9d36b47SEd Tanous std::get_if<std::string>(&property.second);
736dc8cfa66SEd Tanous if (strProperty == nullptr)
737dc8cfa66SEd Tanous {
738dc8cfa66SEd Tanous continue;
739dc8cfa66SEd Tanous }
740b9d36b47SEd Tanous if (property.first == functionName + "DeviceId")
741f5c9f8bdSJason M. Bills {
742727a046cSLakshmi Yadlapati resp.jsonValue["DeviceId"] = *strProperty;
743f5c9f8bdSJason M. Bills }
744b9d36b47SEd Tanous if (property.first == functionName + "VendorId")
745f5c9f8bdSJason M. Bills {
746727a046cSLakshmi Yadlapati resp.jsonValue["VendorId"] = *strProperty;
747f5c9f8bdSJason M. Bills }
748727a046cSLakshmi Yadlapati // TODO: FunctionType and DeviceClass are Redfish enums. The D-Bus
749727a046cSLakshmi Yadlapati // property strings should be mapped correctly to ensure these
750727a046cSLakshmi Yadlapati // strings are Redfish enum values. For now just check for empty.
751b9d36b47SEd Tanous if (property.first == functionName + "FunctionType")
752f5c9f8bdSJason M. Bills {
753727a046cSLakshmi Yadlapati if (!strProperty->empty())
754727a046cSLakshmi Yadlapati {
755727a046cSLakshmi Yadlapati resp.jsonValue["FunctionType"] = *strProperty;
756727a046cSLakshmi Yadlapati }
757f5c9f8bdSJason M. Bills }
758b9d36b47SEd Tanous if (property.first == functionName + "DeviceClass")
759f5c9f8bdSJason M. Bills {
760727a046cSLakshmi Yadlapati if (!strProperty->empty())
761727a046cSLakshmi Yadlapati {
762727a046cSLakshmi Yadlapati resp.jsonValue["DeviceClass"] = *strProperty;
763727a046cSLakshmi Yadlapati }
764f5c9f8bdSJason M. Bills }
765b9d36b47SEd Tanous if (property.first == functionName + "ClassCode")
766f5c9f8bdSJason M. Bills {
767727a046cSLakshmi Yadlapati resp.jsonValue["ClassCode"] = *strProperty;
768f5c9f8bdSJason M. Bills }
769b9d36b47SEd Tanous if (property.first == functionName + "RevisionId")
770f5c9f8bdSJason M. Bills {
771727a046cSLakshmi Yadlapati resp.jsonValue["RevisionId"] = *strProperty;
772f5c9f8bdSJason M. Bills }
773b9d36b47SEd Tanous if (property.first == functionName + "SubsystemId")
774b9d36b47SEd Tanous {
775727a046cSLakshmi Yadlapati resp.jsonValue["SubsystemId"] = *strProperty;
776b9d36b47SEd Tanous }
777002d39b4SEd Tanous if (property.first == functionName + "SubsystemVendorId")
778f5c9f8bdSJason M. Bills {
779727a046cSLakshmi Yadlapati resp.jsonValue["SubsystemVendorId"] = *strProperty;
780b9d36b47SEd Tanous }
781f5c9f8bdSJason M. Bills }
782727a046cSLakshmi Yadlapati }
783727a046cSLakshmi Yadlapati
addPCIeFunctionCommonProperties(crow::Response & resp,const std::string & pcieDeviceId,uint64_t pcieFunctionId)784727a046cSLakshmi Yadlapati inline void addPCIeFunctionCommonProperties(crow::Response& resp,
785727a046cSLakshmi Yadlapati const std::string& pcieDeviceId,
786e14742caSEd Tanous uint64_t pcieFunctionId)
787727a046cSLakshmi Yadlapati {
788727a046cSLakshmi Yadlapati resp.addHeader(
789727a046cSLakshmi Yadlapati boost::beast::http::field::link,
790727a046cSLakshmi Yadlapati "</redfish/v1/JsonSchemas/PCIeFunction/PCIeFunction.json>; rel=describedby");
791727a046cSLakshmi Yadlapati resp.jsonValue["@odata.type"] = "#PCIeFunction.v1_2_3.PCIeFunction";
792ef4c65b7SEd Tanous resp.jsonValue["@odata.id"] = boost::urls::format(
793253f11b8SEd Tanous "/redfish/v1/Systems/{}/PCIeDevices/{}/PCIeFunctions/{}",
794253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME, pcieDeviceId,
795253f11b8SEd Tanous std::to_string(pcieFunctionId));
796727a046cSLakshmi Yadlapati resp.jsonValue["Name"] = "PCIe Function";
797e14742caSEd Tanous resp.jsonValue["Id"] = std::to_string(pcieFunctionId);
798e14742caSEd Tanous resp.jsonValue["FunctionId"] = pcieFunctionId;
799253f11b8SEd Tanous resp.jsonValue["Links"]["PCIeDevice"]["@odata.id"] =
800253f11b8SEd Tanous boost::urls::format("/redfish/v1/Systems/{}/PCIeDevices/{}",
801253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME, pcieDeviceId);
802727a046cSLakshmi Yadlapati }
803727a046cSLakshmi Yadlapati
handlePCIeFunctionGet(App & app,const crow::Request & req,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & systemName,const std::string & pcieDeviceId,const std::string & pcieFunctionIdStr)804bd79bce8SPatrick Williams inline void handlePCIeFunctionGet(
805bd79bce8SPatrick Williams App& app, const crow::Request& req,
806ac106bf6SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
807bd79bce8SPatrick Williams const std::string& systemName, const std::string& pcieDeviceId,
808e14742caSEd Tanous const std::string& pcieFunctionIdStr)
809727a046cSLakshmi Yadlapati {
810ac106bf6SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp))
811727a046cSLakshmi Yadlapati {
812727a046cSLakshmi Yadlapati return;
813727a046cSLakshmi Yadlapati }
81425b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
8157f3e84a1SEd Tanous {
8167f3e84a1SEd Tanous // Option currently returns no systems. TBD
8177f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem",
8187f3e84a1SEd Tanous systemName);
8197f3e84a1SEd Tanous return;
8207f3e84a1SEd Tanous }
821253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
8227f3e84a1SEd Tanous {
8237f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem",
8247f3e84a1SEd Tanous systemName);
8257f3e84a1SEd Tanous return;
8267f3e84a1SEd Tanous }
827dc8cfa66SEd Tanous std::string_view pcieFunctionIdView = pcieFunctionIdStr;
8287f3e84a1SEd Tanous
829e14742caSEd Tanous uint64_t pcieFunctionId = 0;
830e14742caSEd Tanous std::from_chars_result result = std::from_chars(
831dc8cfa66SEd Tanous pcieFunctionIdView.begin(), pcieFunctionIdView.end(), pcieFunctionId);
832dc8cfa66SEd Tanous if (result.ec != std::errc{} || result.ptr != pcieFunctionIdView.end())
833e14742caSEd Tanous {
834ac106bf6SEd Tanous messages::resourceNotFound(asyncResp->res, "PCIeFunction",
835e14742caSEd Tanous pcieFunctionIdStr);
836e14742caSEd Tanous return;
837e14742caSEd Tanous }
838727a046cSLakshmi Yadlapati
839bd79bce8SPatrick Williams getValidPCIeDevicePath(
840bd79bce8SPatrick Williams pcieDeviceId, asyncResp,
841bd79bce8SPatrick Williams [asyncResp, pcieDeviceId, pcieFunctionId](
842bd79bce8SPatrick Williams const std::string& pcieDevicePath, const std::string& service) {
843727a046cSLakshmi Yadlapati getPCIeDeviceProperties(
844ac106bf6SEd Tanous asyncResp, pcieDevicePath, service,
845ac106bf6SEd Tanous [asyncResp, pcieDeviceId, pcieFunctionId](
846727a046cSLakshmi Yadlapati const dbus::utility::DBusPropertiesMap& pcieDevProperties) {
847bd79bce8SPatrick Williams addPCIeFunctionCommonProperties(
848bd79bce8SPatrick Williams asyncResp->res, pcieDeviceId, pcieFunctionId);
849ac106bf6SEd Tanous addPCIeFunctionProperties(asyncResp->res, pcieFunctionId,
850727a046cSLakshmi Yadlapati pcieDevProperties);
8517e860f15SJohn Edward Broadbent });
852727a046cSLakshmi Yadlapati });
853727a046cSLakshmi Yadlapati }
854727a046cSLakshmi Yadlapati
requestRoutesSystemPCIeFunction(App & app)855727a046cSLakshmi Yadlapati inline void requestRoutesSystemPCIeFunction(App& app)
856727a046cSLakshmi Yadlapati {
857727a046cSLakshmi Yadlapati BMCWEB_ROUTE(
8587f3e84a1SEd Tanous app, "/redfish/v1/Systems/<str>/PCIeDevices/<str>/PCIeFunctions/<str>/")
859727a046cSLakshmi Yadlapati .privileges(redfish::privileges::getPCIeFunction)
860727a046cSLakshmi Yadlapati .methods(boost::beast::http::verb::get)(
861727a046cSLakshmi Yadlapati std::bind_front(handlePCIeFunctionGet, std::ref(app)));
862f5c9f8bdSJason M. Bills }
863f5c9f8bdSJason M. Bills
864f5c9f8bdSJason M. Bills } // namespace redfish
865