1f5c9f8bdSJason M. Bills /* 2f5c9f8bdSJason M. Bills // Copyright (c) 2018 Intel Corporation 3f5c9f8bdSJason M. Bills // 4f5c9f8bdSJason M. Bills // Licensed under the Apache License, Version 2.0 (the "License"); 5f5c9f8bdSJason M. Bills // you may not use this file except in compliance with the License. 6f5c9f8bdSJason M. Bills // You may obtain a copy of the License at 7f5c9f8bdSJason M. Bills // 8f5c9f8bdSJason M. Bills // http://www.apache.org/licenses/LICENSE-2.0 9f5c9f8bdSJason M. Bills // 10f5c9f8bdSJason M. Bills // Unless required by applicable law or agreed to in writing, software 11f5c9f8bdSJason M. Bills // distributed under the License is distributed on an "AS IS" BASIS, 12f5c9f8bdSJason M. Bills // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f5c9f8bdSJason M. Bills // See the License for the specific language governing permissions and 14f5c9f8bdSJason M. Bills // limitations under the License. 15f5c9f8bdSJason M. Bills */ 16f5c9f8bdSJason M. Bills 17f5c9f8bdSJason M. Bills #pragma once 18f5c9f8bdSJason M. Bills 193ccb3adbSEd Tanous #include "app.hpp" 207a1dbc48SGeorge Liu #include "dbus_utility.hpp" 213ccb3adbSEd Tanous #include "query.hpp" 223ccb3adbSEd Tanous #include "registries/privilege_registry.hpp" 23b38fa2abSLakshmi Yadlapati #include "utils/collection.hpp" 243ccb3adbSEd Tanous #include "utils/dbus_utils.hpp" 25c49c329dSLakshmi Yadlapati #include "utils/pcie_util.hpp" 260ec8b83dSEd Tanous 27f5c9f8bdSJason M. Bills #include <boost/system/linux_error.hpp> 28ef4c65b7SEd Tanous #include <boost/url/format.hpp> 29d1bde9e5SKrzysztof Grobelny #include <sdbusplus/asio/property.hpp> 30d1bde9e5SKrzysztof Grobelny #include <sdbusplus/unpack_properties.hpp> 31f5c9f8bdSJason M. Bills 32f5c9f8bdSJason M. Bills namespace redfish 33f5c9f8bdSJason M. Bills { 34f5c9f8bdSJason M. Bills 3589492a15SPatrick Williams static constexpr const char* inventoryPath = "/xyz/openbmc_project/inventory"; 3694c3a10bSLakshmi Yadlapati static constexpr std::array<std::string_view, 1> pcieDeviceInterface = { 3794c3a10bSLakshmi Yadlapati "xyz.openbmc_project.Inventory.Item.PCIeDevice"}; 38a5409991SLakshmi Yadlapati static constexpr std::array<std::string_view, 1> pcieSlotInterface = { 39a5409991SLakshmi Yadlapati "xyz.openbmc_project.Inventory.Item.PCIeSlot"}; 40f5c9f8bdSJason M. Bills 41543f9a75SLakshmi Yadlapati static inline void handlePCIeDevicePath( 42543f9a75SLakshmi Yadlapati const std::string& pcieDeviceId, 43ac106bf6SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 44543f9a75SLakshmi Yadlapati const dbus::utility::MapperGetSubTreePathsResponse& pcieDevicePaths, 45543f9a75SLakshmi Yadlapati const std::function<void(const std::string& pcieDevicePath, 46543f9a75SLakshmi Yadlapati const std::string& service)>& callback) 47543f9a75SLakshmi Yadlapati 48543f9a75SLakshmi Yadlapati { 49543f9a75SLakshmi Yadlapati for (const std::string& pcieDevicePath : pcieDevicePaths) 50543f9a75SLakshmi Yadlapati { 51543f9a75SLakshmi Yadlapati std::string pciecDeviceName = 52543f9a75SLakshmi Yadlapati sdbusplus::message::object_path(pcieDevicePath).filename(); 53543f9a75SLakshmi Yadlapati if (pciecDeviceName.empty() || pciecDeviceName != pcieDeviceId) 54543f9a75SLakshmi Yadlapati { 55543f9a75SLakshmi Yadlapati continue; 56543f9a75SLakshmi Yadlapati } 57543f9a75SLakshmi Yadlapati 58543f9a75SLakshmi Yadlapati dbus::utility::getDbusObject( 59543f9a75SLakshmi Yadlapati pcieDevicePath, {}, 60ac106bf6SEd Tanous [pcieDevicePath, asyncResp, 61543f9a75SLakshmi Yadlapati callback](const boost::system::error_code& ec, 62543f9a75SLakshmi Yadlapati const dbus::utility::MapperGetObject& object) { 63543f9a75SLakshmi Yadlapati if (ec || object.empty()) 64543f9a75SLakshmi Yadlapati { 65543f9a75SLakshmi Yadlapati BMCWEB_LOG_ERROR << "DBUS response error " << ec; 66ac106bf6SEd Tanous messages::internalError(asyncResp->res); 67543f9a75SLakshmi Yadlapati return; 68543f9a75SLakshmi Yadlapati } 69543f9a75SLakshmi Yadlapati callback(pcieDevicePath, object.begin()->first); 70543f9a75SLakshmi Yadlapati }); 71543f9a75SLakshmi Yadlapati return; 72543f9a75SLakshmi Yadlapati } 73543f9a75SLakshmi Yadlapati 74543f9a75SLakshmi Yadlapati BMCWEB_LOG_WARNING << "PCIe Device not found"; 75ac106bf6SEd Tanous messages::resourceNotFound(asyncResp->res, "PCIeDevice", pcieDeviceId); 76543f9a75SLakshmi Yadlapati } 77543f9a75SLakshmi Yadlapati 78543f9a75SLakshmi Yadlapati static inline void getValidPCIeDevicePath( 79543f9a75SLakshmi Yadlapati const std::string& pcieDeviceId, 80ac106bf6SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 81543f9a75SLakshmi Yadlapati const std::function<void(const std::string& pcieDevicePath, 82543f9a75SLakshmi Yadlapati const std::string& service)>& callback) 83543f9a75SLakshmi Yadlapati { 84543f9a75SLakshmi Yadlapati dbus::utility::getSubTreePaths( 8594c3a10bSLakshmi Yadlapati inventoryPath, 0, pcieDeviceInterface, 86ac106bf6SEd Tanous [pcieDeviceId, asyncResp, 87543f9a75SLakshmi Yadlapati callback](const boost::system::error_code& ec, 88543f9a75SLakshmi Yadlapati const dbus::utility::MapperGetSubTreePathsResponse& 89543f9a75SLakshmi Yadlapati pcieDevicePaths) { 90543f9a75SLakshmi Yadlapati if (ec) 91543f9a75SLakshmi Yadlapati { 92543f9a75SLakshmi Yadlapati BMCWEB_LOG_ERROR << "D-Bus response error on GetSubTree " << ec; 93ac106bf6SEd Tanous messages::internalError(asyncResp->res); 94543f9a75SLakshmi Yadlapati return; 95543f9a75SLakshmi Yadlapati } 96ac106bf6SEd Tanous handlePCIeDevicePath(pcieDeviceId, asyncResp, pcieDevicePaths, 97ac106bf6SEd Tanous callback); 98543f9a75SLakshmi Yadlapati return; 99543f9a75SLakshmi Yadlapati }); 100543f9a75SLakshmi Yadlapati } 101543f9a75SLakshmi Yadlapati 102b38fa2abSLakshmi Yadlapati static inline void handlePCIeDeviceCollectionGet( 103b38fa2abSLakshmi Yadlapati crow::App& app, const crow::Request& req, 104ac106bf6SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 105b38fa2abSLakshmi Yadlapati const std::string& systemName) 106b38fa2abSLakshmi Yadlapati { 107ac106bf6SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 108b38fa2abSLakshmi Yadlapati { 109b38fa2abSLakshmi Yadlapati return; 110b38fa2abSLakshmi Yadlapati } 1117f3e84a1SEd Tanous if constexpr (bmcwebEnableMultiHost) 1127f3e84a1SEd Tanous { 1137f3e84a1SEd Tanous // Option currently returns no systems. TBD 1147f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 1157f3e84a1SEd Tanous systemName); 1167f3e84a1SEd Tanous return; 1177f3e84a1SEd Tanous } 118b38fa2abSLakshmi Yadlapati if (systemName != "system") 119b38fa2abSLakshmi Yadlapati { 120ac106bf6SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 121ac106bf6SEd Tanous systemName); 122b38fa2abSLakshmi Yadlapati return; 123b38fa2abSLakshmi Yadlapati } 124543f9a75SLakshmi Yadlapati 125ac106bf6SEd Tanous asyncResp->res.addHeader(boost::beast::http::field::link, 126b38fa2abSLakshmi Yadlapati "</redfish/v1/JsonSchemas/PCIeDeviceCollection/" 127b38fa2abSLakshmi Yadlapati "PCIeDeviceCollection.json>; rel=describedby"); 128ac106bf6SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 129b38fa2abSLakshmi Yadlapati "#PCIeDeviceCollection.PCIeDeviceCollection"; 130ac106bf6SEd Tanous asyncResp->res.jsonValue["@odata.id"] = 131b38fa2abSLakshmi Yadlapati "/redfish/v1/Systems/system/PCIeDevices"; 132ac106bf6SEd Tanous asyncResp->res.jsonValue["Name"] = "PCIe Device Collection"; 133ac106bf6SEd Tanous asyncResp->res.jsonValue["Description"] = "Collection of PCIe Devices"; 134ac106bf6SEd Tanous asyncResp->res.jsonValue["Members"] = nlohmann::json::array(); 135ac106bf6SEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = 0; 136b38fa2abSLakshmi Yadlapati 1379e9325e6SLakshmi Yadlapati pcie_util::getPCIeDeviceList(asyncResp, "Members"); 138b38fa2abSLakshmi Yadlapati } 139b38fa2abSLakshmi Yadlapati 1407e860f15SJohn Edward Broadbent inline void requestRoutesSystemPCIeDeviceCollection(App& app) 141adbe192aSJason M. Bills { 142adbe192aSJason M. Bills /** 143adbe192aSJason M. Bills * Functions triggers appropriate requests on DBus 144adbe192aSJason M. Bills */ 14522d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/PCIeDevices/") 146ed398213SEd Tanous .privileges(redfish::privileges::getPCIeDeviceCollection) 1477e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 148b38fa2abSLakshmi Yadlapati std::bind_front(handlePCIeDeviceCollectionGet, std::ref(app))); 149f5c9f8bdSJason M. Bills } 150f5c9f8bdSJason M. Bills 151a5409991SLakshmi Yadlapati inline void addPCIeSlotProperties( 152a5409991SLakshmi Yadlapati crow::Response& res, const boost::system::error_code& ec, 153a5409991SLakshmi Yadlapati const dbus::utility::DBusPropertiesMap& pcieSlotProperties) 154a5409991SLakshmi Yadlapati { 155a5409991SLakshmi Yadlapati if (ec) 156a5409991SLakshmi Yadlapati { 157a5409991SLakshmi Yadlapati BMCWEB_LOG_ERROR << "DBUS response error for getAllProperties" 158a5409991SLakshmi Yadlapati << ec.value(); 159a5409991SLakshmi Yadlapati messages::internalError(res); 160a5409991SLakshmi Yadlapati return; 161a5409991SLakshmi Yadlapati } 162a5409991SLakshmi Yadlapati std::string generation; 163a5409991SLakshmi Yadlapati size_t lanes = 0; 164a5409991SLakshmi Yadlapati std::string slotType; 165a5409991SLakshmi Yadlapati 166a5409991SLakshmi Yadlapati bool success = sdbusplus::unpackPropertiesNoThrow( 167a5409991SLakshmi Yadlapati dbus_utils::UnpackErrorPrinter(), pcieSlotProperties, "Generation", 168a5409991SLakshmi Yadlapati generation, "Lanes", lanes, "SlotType", slotType); 169a5409991SLakshmi Yadlapati 170a5409991SLakshmi Yadlapati if (!success) 171a5409991SLakshmi Yadlapati { 172a5409991SLakshmi Yadlapati messages::internalError(res); 173a5409991SLakshmi Yadlapati return; 174a5409991SLakshmi Yadlapati } 175a5409991SLakshmi Yadlapati 176a5409991SLakshmi Yadlapati std::optional<pcie_device::PCIeTypes> pcieType = 177a5409991SLakshmi Yadlapati pcie_util::redfishPcieGenerationFromDbus(generation); 178a5409991SLakshmi Yadlapati if (!pcieType) 179a5409991SLakshmi Yadlapati { 180a5409991SLakshmi Yadlapati BMCWEB_LOG_WARNING << "Unknown PCIeType: " << generation; 181a5409991SLakshmi Yadlapati } 182a5409991SLakshmi Yadlapati else 183a5409991SLakshmi Yadlapati { 184a5409991SLakshmi Yadlapati if (*pcieType == pcie_device::PCIeTypes::Invalid) 185a5409991SLakshmi Yadlapati { 186a5409991SLakshmi Yadlapati BMCWEB_LOG_ERROR << "Invalid PCIeType: " << generation; 187a5409991SLakshmi Yadlapati messages::internalError(res); 188a5409991SLakshmi Yadlapati return; 189a5409991SLakshmi Yadlapati } 190a5409991SLakshmi Yadlapati res.jsonValue["Slot"]["PCIeType"] = *pcieType; 191a5409991SLakshmi Yadlapati } 192a5409991SLakshmi Yadlapati 193a5409991SLakshmi Yadlapati res.jsonValue["Slot"]["Lanes"] = lanes; 194a5409991SLakshmi Yadlapati 195a5409991SLakshmi Yadlapati std::optional<pcie_slots::SlotTypes> redfishSlotType = 196a5409991SLakshmi Yadlapati pcie_util::dbusSlotTypeToRf(slotType); 197a5409991SLakshmi Yadlapati if (!redfishSlotType) 198a5409991SLakshmi Yadlapati { 199a5409991SLakshmi Yadlapati BMCWEB_LOG_WARNING << "Unknown PCIeSlot Type: " << slotType; 200a5409991SLakshmi Yadlapati } 201a5409991SLakshmi Yadlapati else 202a5409991SLakshmi Yadlapati { 203a5409991SLakshmi Yadlapati if (*redfishSlotType == pcie_slots::SlotTypes::Invalid) 204a5409991SLakshmi Yadlapati { 205a5409991SLakshmi Yadlapati BMCWEB_LOG_ERROR << "Invalid PCIeSlot type: " << slotType; 206a5409991SLakshmi Yadlapati messages::internalError(res); 207a5409991SLakshmi Yadlapati return; 208a5409991SLakshmi Yadlapati } 209a5409991SLakshmi Yadlapati res.jsonValue["Slot"]["SlotType"] = *redfishSlotType; 210a5409991SLakshmi Yadlapati } 211a5409991SLakshmi Yadlapati } 212a5409991SLakshmi Yadlapati 213a5409991SLakshmi Yadlapati inline void getPCIeDeviceSlotPath( 214a5409991SLakshmi Yadlapati const std::string& pcieDevicePath, 215a5409991SLakshmi Yadlapati const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 216a5409991SLakshmi Yadlapati std::function<void(const std::string& pcieDeviceSlot)>&& callback) 217a5409991SLakshmi Yadlapati { 218a5409991SLakshmi Yadlapati std::string associationPath = pcieDevicePath + "/contained_by"; 219a5409991SLakshmi Yadlapati dbus::utility::getAssociatedSubTreePaths( 220a5409991SLakshmi Yadlapati associationPath, sdbusplus::message::object_path(inventoryPath), 0, 221a5409991SLakshmi Yadlapati pcieSlotInterface, 222a5409991SLakshmi Yadlapati [callback, asyncResp, pcieDevicePath]( 223a5409991SLakshmi Yadlapati const boost::system::error_code& ec, 224a5409991SLakshmi Yadlapati const dbus::utility::MapperGetSubTreePathsResponse& endpoints) { 225a5409991SLakshmi Yadlapati if (ec) 226a5409991SLakshmi Yadlapati { 227a5409991SLakshmi Yadlapati if (ec.value() == EBADR) 228a5409991SLakshmi Yadlapati { 229a5409991SLakshmi Yadlapati // Missing association is not an error 230a5409991SLakshmi Yadlapati return; 231a5409991SLakshmi Yadlapati } 232a5409991SLakshmi Yadlapati BMCWEB_LOG_ERROR 233a5409991SLakshmi Yadlapati << "DBUS response error for getAssociatedSubTreePaths " 234a5409991SLakshmi Yadlapati << ec.value(); 235a5409991SLakshmi Yadlapati messages::internalError(asyncResp->res); 236a5409991SLakshmi Yadlapati return; 237a5409991SLakshmi Yadlapati } 238a5409991SLakshmi Yadlapati if (endpoints.size() > 1) 239a5409991SLakshmi Yadlapati { 240a5409991SLakshmi Yadlapati BMCWEB_LOG_ERROR 241a5409991SLakshmi Yadlapati << "PCIeDevice is associated with more than one PCIeSlot: " 242a5409991SLakshmi Yadlapati << endpoints.size(); 243a5409991SLakshmi Yadlapati messages::internalError(asyncResp->res); 244a5409991SLakshmi Yadlapati return; 245a5409991SLakshmi Yadlapati } 246a5409991SLakshmi Yadlapati if (endpoints.empty()) 247a5409991SLakshmi Yadlapati { 248a5409991SLakshmi Yadlapati // If the device doesn't have an association, return without PCIe 249a5409991SLakshmi Yadlapati // Slot properties 250a5409991SLakshmi Yadlapati BMCWEB_LOG_DEBUG << "PCIeDevice is not associated with PCIeSlot"; 251a5409991SLakshmi Yadlapati return; 252a5409991SLakshmi Yadlapati } 253a5409991SLakshmi Yadlapati callback(endpoints[0]); 254a5409991SLakshmi Yadlapati }); 255a5409991SLakshmi Yadlapati } 256a5409991SLakshmi Yadlapati 257a5409991SLakshmi Yadlapati inline void 258a5409991SLakshmi Yadlapati afterGetDbusObject(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 259a5409991SLakshmi Yadlapati const std::string& pcieDeviceSlot, 260a5409991SLakshmi Yadlapati const boost::system::error_code& ec, 261a5409991SLakshmi Yadlapati const dbus::utility::MapperGetObject& object) 262a5409991SLakshmi Yadlapati { 263a5409991SLakshmi Yadlapati if (ec || object.empty()) 264a5409991SLakshmi Yadlapati { 265a5409991SLakshmi Yadlapati BMCWEB_LOG_ERROR << "DBUS response error for getDbusObject " 266a5409991SLakshmi Yadlapati << ec.value(); 267a5409991SLakshmi Yadlapati messages::internalError(asyncResp->res); 268a5409991SLakshmi Yadlapati return; 269a5409991SLakshmi Yadlapati } 270a5409991SLakshmi Yadlapati sdbusplus::asio::getAllProperties( 271a5409991SLakshmi Yadlapati *crow::connections::systemBus, object.begin()->first, pcieDeviceSlot, 272a5409991SLakshmi Yadlapati "xyz.openbmc_project.Inventory.Item.PCIeSlot", 273a5409991SLakshmi Yadlapati [asyncResp]( 274a5409991SLakshmi Yadlapati const boost::system::error_code& ec2, 275a5409991SLakshmi Yadlapati const dbus::utility::DBusPropertiesMap& pcieSlotProperties) { 276a5409991SLakshmi Yadlapati addPCIeSlotProperties(asyncResp->res, ec2, pcieSlotProperties); 277a5409991SLakshmi Yadlapati }); 278a5409991SLakshmi Yadlapati } 279a5409991SLakshmi Yadlapati 280a5409991SLakshmi Yadlapati inline void afterGetPCIeDeviceSlotPath( 281a5409991SLakshmi Yadlapati const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 282a5409991SLakshmi Yadlapati const std::string& pcieDeviceSlot) 283a5409991SLakshmi Yadlapati { 284a5409991SLakshmi Yadlapati dbus::utility::getDbusObject( 285a5409991SLakshmi Yadlapati pcieDeviceSlot, pcieSlotInterface, 286a5409991SLakshmi Yadlapati [asyncResp, 287a5409991SLakshmi Yadlapati pcieDeviceSlot](const boost::system::error_code& ec, 288a5409991SLakshmi Yadlapati const dbus::utility::MapperGetObject& object) { 289a5409991SLakshmi Yadlapati afterGetDbusObject(asyncResp, pcieDeviceSlot, ec, object); 290a5409991SLakshmi Yadlapati }); 291a5409991SLakshmi Yadlapati } 292a5409991SLakshmi Yadlapati 293ac106bf6SEd Tanous inline void 294e164f1b6SLakshmi Yadlapati getPCIeDeviceHealth(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 295e164f1b6SLakshmi Yadlapati const std::string& pcieDevicePath, 296e164f1b6SLakshmi Yadlapati const std::string& service) 297e164f1b6SLakshmi Yadlapati { 298e164f1b6SLakshmi Yadlapati sdbusplus::asio::getProperty<bool>( 299e164f1b6SLakshmi Yadlapati *crow::connections::systemBus, service, pcieDevicePath, 300e164f1b6SLakshmi Yadlapati "xyz.openbmc_project.State.Decorator.OperationalStatus", "Functional", 301e164f1b6SLakshmi Yadlapati [asyncResp](const boost::system::error_code& ec, const bool value) { 302e164f1b6SLakshmi Yadlapati if (ec) 303e164f1b6SLakshmi Yadlapati { 304e164f1b6SLakshmi Yadlapati if (ec.value() != EBADR) 305e164f1b6SLakshmi Yadlapati { 306e164f1b6SLakshmi Yadlapati BMCWEB_LOG_ERROR << "DBUS response error for Health " 307e164f1b6SLakshmi Yadlapati << ec.value(); 308e164f1b6SLakshmi Yadlapati messages::internalError(asyncResp->res); 309e164f1b6SLakshmi Yadlapati } 310e164f1b6SLakshmi Yadlapati return; 311e164f1b6SLakshmi Yadlapati } 312e164f1b6SLakshmi Yadlapati 313e164f1b6SLakshmi Yadlapati if (!value) 314e164f1b6SLakshmi Yadlapati { 315e164f1b6SLakshmi Yadlapati asyncResp->res.jsonValue["Status"]["Health"] = "Critical"; 316e164f1b6SLakshmi Yadlapati } 317e164f1b6SLakshmi Yadlapati }); 318e164f1b6SLakshmi Yadlapati } 319e164f1b6SLakshmi Yadlapati 320e164f1b6SLakshmi Yadlapati inline void 321ac106bf6SEd Tanous getPCIeDeviceState(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 322c6bb3285SLakshmi Yadlapati const std::string& pcieDevicePath, 323c6bb3285SLakshmi Yadlapati const std::string& service) 324c6bb3285SLakshmi Yadlapati { 325c6bb3285SLakshmi Yadlapati sdbusplus::asio::getProperty<bool>( 326c6bb3285SLakshmi Yadlapati *crow::connections::systemBus, service, pcieDevicePath, 327c6bb3285SLakshmi Yadlapati "xyz.openbmc_project.Inventory.Item", "Present", 328a5409991SLakshmi Yadlapati [asyncResp](const boost::system::error_code& ec, bool value) { 329c6bb3285SLakshmi Yadlapati if (ec) 330c6bb3285SLakshmi Yadlapati { 331c6bb3285SLakshmi Yadlapati if (ec.value() != EBADR) 332c6bb3285SLakshmi Yadlapati { 333c6bb3285SLakshmi Yadlapati BMCWEB_LOG_ERROR << "DBUS response error for State"; 334ac106bf6SEd Tanous messages::internalError(asyncResp->res); 335c6bb3285SLakshmi Yadlapati } 336c6bb3285SLakshmi Yadlapati return; 337c6bb3285SLakshmi Yadlapati } 338c6bb3285SLakshmi Yadlapati 339c6bb3285SLakshmi Yadlapati if (!value) 340c6bb3285SLakshmi Yadlapati { 341ac106bf6SEd Tanous asyncResp->res.jsonValue["Status"]["State"] = "Absent"; 342c6bb3285SLakshmi Yadlapati } 343c6bb3285SLakshmi Yadlapati }); 344c6bb3285SLakshmi Yadlapati } 345c6bb3285SLakshmi Yadlapati 346ac106bf6SEd Tanous inline void 347ac106bf6SEd Tanous getPCIeDeviceAsset(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 348913e7732SSunnySrivastava1984 const std::string& pcieDevicePath, 349913e7732SSunnySrivastava1984 const std::string& service) 350913e7732SSunnySrivastava1984 { 351913e7732SSunnySrivastava1984 sdbusplus::asio::getAllProperties( 352913e7732SSunnySrivastava1984 *crow::connections::systemBus, service, pcieDevicePath, 353913e7732SSunnySrivastava1984 "xyz.openbmc_project.Inventory.Decorator.Asset", 354ac106bf6SEd Tanous [pcieDevicePath, asyncResp{asyncResp}]( 355ac106bf6SEd Tanous const boost::system::error_code& ec, 356913e7732SSunnySrivastava1984 const dbus::utility::DBusPropertiesMap& assetList) { 357913e7732SSunnySrivastava1984 if (ec) 358913e7732SSunnySrivastava1984 { 359913e7732SSunnySrivastava1984 if (ec.value() != EBADR) 360913e7732SSunnySrivastava1984 { 361913e7732SSunnySrivastava1984 BMCWEB_LOG_ERROR << "DBUS response error for Properties" 362913e7732SSunnySrivastava1984 << ec.value(); 363ac106bf6SEd Tanous messages::internalError(asyncResp->res); 364913e7732SSunnySrivastava1984 } 365913e7732SSunnySrivastava1984 return; 366913e7732SSunnySrivastava1984 } 367913e7732SSunnySrivastava1984 368913e7732SSunnySrivastava1984 const std::string* manufacturer = nullptr; 369913e7732SSunnySrivastava1984 const std::string* model = nullptr; 370913e7732SSunnySrivastava1984 const std::string* partNumber = nullptr; 371913e7732SSunnySrivastava1984 const std::string* serialNumber = nullptr; 372913e7732SSunnySrivastava1984 const std::string* sparePartNumber = nullptr; 373913e7732SSunnySrivastava1984 374913e7732SSunnySrivastava1984 const bool success = sdbusplus::unpackPropertiesNoThrow( 375913e7732SSunnySrivastava1984 dbus_utils::UnpackErrorPrinter(), assetList, "Manufacturer", 376913e7732SSunnySrivastava1984 manufacturer, "Model", model, "PartNumber", partNumber, 377913e7732SSunnySrivastava1984 "SerialNumber", serialNumber, "SparePartNumber", sparePartNumber); 378913e7732SSunnySrivastava1984 379913e7732SSunnySrivastava1984 if (!success) 380913e7732SSunnySrivastava1984 { 381ac106bf6SEd Tanous messages::internalError(asyncResp->res); 382913e7732SSunnySrivastava1984 return; 383913e7732SSunnySrivastava1984 } 384913e7732SSunnySrivastava1984 385913e7732SSunnySrivastava1984 if (manufacturer != nullptr) 386913e7732SSunnySrivastava1984 { 387ac106bf6SEd Tanous asyncResp->res.jsonValue["Manufacturer"] = *manufacturer; 388913e7732SSunnySrivastava1984 } 389913e7732SSunnySrivastava1984 if (model != nullptr) 390913e7732SSunnySrivastava1984 { 391ac106bf6SEd Tanous asyncResp->res.jsonValue["Model"] = *model; 392913e7732SSunnySrivastava1984 } 393913e7732SSunnySrivastava1984 394913e7732SSunnySrivastava1984 if (partNumber != nullptr) 395913e7732SSunnySrivastava1984 { 396ac106bf6SEd Tanous asyncResp->res.jsonValue["PartNumber"] = *partNumber; 397913e7732SSunnySrivastava1984 } 398913e7732SSunnySrivastava1984 399913e7732SSunnySrivastava1984 if (serialNumber != nullptr) 400913e7732SSunnySrivastava1984 { 401ac106bf6SEd Tanous asyncResp->res.jsonValue["SerialNumber"] = *serialNumber; 402913e7732SSunnySrivastava1984 } 403913e7732SSunnySrivastava1984 404913e7732SSunnySrivastava1984 if (sparePartNumber != nullptr && !sparePartNumber->empty()) 405913e7732SSunnySrivastava1984 { 406ac106bf6SEd Tanous asyncResp->res.jsonValue["SparePartNumber"] = *sparePartNumber; 407913e7732SSunnySrivastava1984 } 408913e7732SSunnySrivastava1984 }); 409913e7732SSunnySrivastava1984 } 410913e7732SSunnySrivastava1984 411543f9a75SLakshmi Yadlapati inline void addPCIeDeviceProperties( 412a5409991SLakshmi Yadlapati const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 413a5409991SLakshmi Yadlapati const std::string& pcieDeviceId, 414543f9a75SLakshmi Yadlapati const dbus::utility::DBusPropertiesMap& pcieDevProperties) 415f5c9f8bdSJason M. Bills { 416d1bde9e5SKrzysztof Grobelny const std::string* deviceType = nullptr; 417d1bde9e5SKrzysztof Grobelny const std::string* generationInUse = nullptr; 418*9bb0a7feSKonstantin Aladyshev const size_t* lanesInUse = nullptr; 419d1bde9e5SKrzysztof Grobelny 420d1bde9e5SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 421543f9a75SLakshmi Yadlapati dbus_utils::UnpackErrorPrinter(), pcieDevProperties, "DeviceType", 422543f9a75SLakshmi Yadlapati deviceType, "GenerationInUse", generationInUse, "LanesInUse", 423bad2c4a9SLakshmi Yadlapati lanesInUse); 424d1bde9e5SKrzysztof Grobelny 425d1bde9e5SKrzysztof Grobelny if (!success) 426d1bde9e5SKrzysztof Grobelny { 427a5409991SLakshmi Yadlapati messages::internalError(asyncResp->res); 428d1bde9e5SKrzysztof Grobelny return; 429d1bde9e5SKrzysztof Grobelny } 430d1bde9e5SKrzysztof Grobelny 431543f9a75SLakshmi Yadlapati if (deviceType != nullptr && !deviceType->empty()) 432703f6741SMyung Bae { 433a5409991SLakshmi Yadlapati asyncResp->res.jsonValue["PCIeInterface"]["DeviceType"] = *deviceType; 434703f6741SMyung Bae } 435703f6741SMyung Bae 436d1bde9e5SKrzysztof Grobelny if (generationInUse != nullptr) 437d1bde9e5SKrzysztof Grobelny { 4380ec8b83dSEd Tanous std::optional<pcie_device::PCIeTypes> redfishGenerationInUse = 439c49c329dSLakshmi Yadlapati pcie_util::redfishPcieGenerationFromDbus(*generationInUse); 440543f9a75SLakshmi Yadlapati 441d1bde9e5SKrzysztof Grobelny if (!redfishGenerationInUse) 442d1bde9e5SKrzysztof Grobelny { 443cf3b484eSLakshmi Yadlapati BMCWEB_LOG_WARNING << "Unknown PCIe Device Generation: " 444cf3b484eSLakshmi Yadlapati << *generationInUse; 445cf3b484eSLakshmi Yadlapati } 446cf3b484eSLakshmi Yadlapati else 447cf3b484eSLakshmi Yadlapati { 448cf3b484eSLakshmi Yadlapati if (*redfishGenerationInUse == pcie_device::PCIeTypes::Invalid) 449cf3b484eSLakshmi Yadlapati { 450cf3b484eSLakshmi Yadlapati BMCWEB_LOG_ERROR << "Invalid PCIe Device Generation: " 451cf3b484eSLakshmi Yadlapati << *generationInUse; 452a5409991SLakshmi Yadlapati messages::internalError(asyncResp->res); 453d1bde9e5SKrzysztof Grobelny return; 454d1bde9e5SKrzysztof Grobelny } 455a5409991SLakshmi Yadlapati asyncResp->res.jsonValue["PCIeInterface"]["PCIeType"] = 456d1bde9e5SKrzysztof Grobelny *redfishGenerationInUse; 457d1bde9e5SKrzysztof Grobelny } 458a9f68bb5STony Lee } 459d1bde9e5SKrzysztof Grobelny 460543f9a75SLakshmi Yadlapati // The default value of LanesInUse is 0, and the field will be 461543f9a75SLakshmi Yadlapati // left as off if it is a default value. 462543f9a75SLakshmi Yadlapati if (lanesInUse != nullptr && *lanesInUse != 0) 463543f9a75SLakshmi Yadlapati { 464a5409991SLakshmi Yadlapati asyncResp->res.jsonValue["PCIeInterface"]["LanesInUse"] = *lanesInUse; 465543f9a75SLakshmi Yadlapati } 466543f9a75SLakshmi Yadlapati 467a5409991SLakshmi Yadlapati asyncResp->res.jsonValue["PCIeFunctions"]["@odata.id"] = 468a5409991SLakshmi Yadlapati boost::urls::format( 469ef4c65b7SEd Tanous "/redfish/v1/Systems/system/PCIeDevices/{}/PCIeFunctions", 470ef4c65b7SEd Tanous pcieDeviceId); 471d1bde9e5SKrzysztof Grobelny } 472d1bde9e5SKrzysztof Grobelny 473543f9a75SLakshmi Yadlapati inline void getPCIeDeviceProperties( 474ac106bf6SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 475543f9a75SLakshmi Yadlapati const std::string& pcieDevicePath, const std::string& service, 476543f9a75SLakshmi Yadlapati const std::function<void( 477543f9a75SLakshmi Yadlapati const dbus::utility::DBusPropertiesMap& pcieDevProperties)>&& callback) 478d1bde9e5SKrzysztof Grobelny { 479543f9a75SLakshmi Yadlapati sdbusplus::asio::getAllProperties( 480543f9a75SLakshmi Yadlapati *crow::connections::systemBus, service, pcieDevicePath, 481543f9a75SLakshmi Yadlapati "xyz.openbmc_project.Inventory.Item.PCIeDevice", 482ac106bf6SEd Tanous [asyncResp, 483543f9a75SLakshmi Yadlapati callback](const boost::system::error_code& ec, 484543f9a75SLakshmi Yadlapati const dbus::utility::DBusPropertiesMap& pcieDevProperties) { 485543f9a75SLakshmi Yadlapati if (ec) 486543f9a75SLakshmi Yadlapati { 487543f9a75SLakshmi Yadlapati if (ec.value() != EBADR) 488543f9a75SLakshmi Yadlapati { 489543f9a75SLakshmi Yadlapati BMCWEB_LOG_ERROR << "DBUS response error for Properties"; 490ac106bf6SEd Tanous messages::internalError(asyncResp->res); 491543f9a75SLakshmi Yadlapati } 492543f9a75SLakshmi Yadlapati return; 493543f9a75SLakshmi Yadlapati } 494543f9a75SLakshmi Yadlapati callback(pcieDevProperties); 495543f9a75SLakshmi Yadlapati }); 496d1bde9e5SKrzysztof Grobelny } 497d1bde9e5SKrzysztof Grobelny 498543f9a75SLakshmi Yadlapati inline void addPCIeDeviceCommonProperties( 499ac106bf6SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 500543f9a75SLakshmi Yadlapati const std::string& pcieDeviceId) 501543f9a75SLakshmi Yadlapati { 502ac106bf6SEd Tanous asyncResp->res.addHeader( 503543f9a75SLakshmi Yadlapati boost::beast::http::field::link, 504543f9a75SLakshmi Yadlapati "</redfish/v1/JsonSchemas/PCIeDevice/PCIeDevice.json>; rel=describedby"); 505ac106bf6SEd Tanous asyncResp->res.jsonValue["@odata.type"] = "#PCIeDevice.v1_9_0.PCIeDevice"; 506ac106bf6SEd Tanous asyncResp->res.jsonValue["@odata.id"] = boost::urls::format( 507ef4c65b7SEd Tanous "/redfish/v1/Systems/system/PCIeDevices/{}", pcieDeviceId); 508ac106bf6SEd Tanous asyncResp->res.jsonValue["Name"] = "PCIe Device"; 509ac106bf6SEd Tanous asyncResp->res.jsonValue["Id"] = pcieDeviceId; 510ac106bf6SEd Tanous asyncResp->res.jsonValue["Status"]["State"] = "Enabled"; 511e164f1b6SLakshmi Yadlapati asyncResp->res.jsonValue["Status"]["Health"] = "OK"; 512543f9a75SLakshmi Yadlapati } 5131476687dSEd Tanous 514a5409991SLakshmi Yadlapati inline void afterGetValidPcieDevicePath( 515a5409991SLakshmi Yadlapati const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 516a5409991SLakshmi Yadlapati const std::string& pcieDeviceId, const std::string& pcieDevicePath, 517a5409991SLakshmi Yadlapati const std::string& service) 518a5409991SLakshmi Yadlapati { 519a5409991SLakshmi Yadlapati addPCIeDeviceCommonProperties(asyncResp, pcieDeviceId); 520a5409991SLakshmi Yadlapati getPCIeDeviceAsset(asyncResp, pcieDevicePath, service); 521a5409991SLakshmi Yadlapati getPCIeDeviceState(asyncResp, pcieDevicePath, service); 522a5409991SLakshmi Yadlapati getPCIeDeviceHealth(asyncResp, pcieDevicePath, service); 523a5409991SLakshmi Yadlapati getPCIeDeviceProperties( 524a5409991SLakshmi Yadlapati asyncResp, pcieDevicePath, service, 525a5409991SLakshmi Yadlapati std::bind_front(addPCIeDeviceProperties, asyncResp, pcieDeviceId)); 526a5409991SLakshmi Yadlapati getPCIeDeviceSlotPath( 527a5409991SLakshmi Yadlapati pcieDevicePath, asyncResp, 528a5409991SLakshmi Yadlapati std::bind_front(afterGetPCIeDeviceSlotPath, asyncResp)); 529a5409991SLakshmi Yadlapati } 530a5409991SLakshmi Yadlapati 531ac106bf6SEd Tanous inline void 532ac106bf6SEd Tanous handlePCIeDeviceGet(App& app, const crow::Request& req, 533ac106bf6SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 534543f9a75SLakshmi Yadlapati const std::string& systemName, 535543f9a75SLakshmi Yadlapati const std::string& pcieDeviceId) 536543f9a75SLakshmi Yadlapati { 537ac106bf6SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 538543f9a75SLakshmi Yadlapati { 539543f9a75SLakshmi Yadlapati return; 540543f9a75SLakshmi Yadlapati } 5417f3e84a1SEd Tanous if constexpr (bmcwebEnableMultiHost) 5427f3e84a1SEd Tanous { 5437f3e84a1SEd Tanous // Option currently returns no systems. TBD 5447f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 5457f3e84a1SEd Tanous systemName); 5467f3e84a1SEd Tanous return; 5477f3e84a1SEd Tanous } 548543f9a75SLakshmi Yadlapati if (systemName != "system") 549543f9a75SLakshmi Yadlapati { 550ac106bf6SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 551ac106bf6SEd Tanous systemName); 552543f9a75SLakshmi Yadlapati return; 553543f9a75SLakshmi Yadlapati } 554543f9a75SLakshmi Yadlapati 555543f9a75SLakshmi Yadlapati getValidPCIeDevicePath( 556ac106bf6SEd Tanous pcieDeviceId, asyncResp, 557a5409991SLakshmi Yadlapati std::bind_front(afterGetValidPcieDevicePath, asyncResp, pcieDeviceId)); 558543f9a75SLakshmi Yadlapati } 559543f9a75SLakshmi Yadlapati 560543f9a75SLakshmi Yadlapati inline void requestRoutesSystemPCIeDevice(App& app) 561543f9a75SLakshmi Yadlapati { 562543f9a75SLakshmi Yadlapati BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/PCIeDevices/<str>/") 563543f9a75SLakshmi Yadlapati .privileges(redfish::privileges::getPCIeDevice) 564543f9a75SLakshmi Yadlapati .methods(boost::beast::http::verb::get)( 565543f9a75SLakshmi Yadlapati std::bind_front(handlePCIeDeviceGet, std::ref(app))); 566dede6a98SJason M. Bills } 567dede6a98SJason M. Bills 56835ad613dSLakshmi Yadlapati inline void addPCIeFunctionList( 56935ad613dSLakshmi Yadlapati crow::Response& res, const std::string& pcieDeviceId, 57035ad613dSLakshmi Yadlapati const dbus::utility::DBusPropertiesMap& pcieDevProperties) 57135ad613dSLakshmi Yadlapati { 57235ad613dSLakshmi Yadlapati nlohmann::json& pcieFunctionList = res.jsonValue["Members"]; 57335ad613dSLakshmi Yadlapati pcieFunctionList = nlohmann::json::array(); 57435ad613dSLakshmi Yadlapati static constexpr const int maxPciFunctionNum = 8; 57535ad613dSLakshmi Yadlapati 57635ad613dSLakshmi Yadlapati for (int functionNum = 0; functionNum < maxPciFunctionNum; functionNum++) 57735ad613dSLakshmi Yadlapati { 57835ad613dSLakshmi Yadlapati // Check if this function exists by 57935ad613dSLakshmi Yadlapati // looking for a device ID 58089492a15SPatrick Williams std::string devIDProperty = "Function" + std::to_string(functionNum) + 58189492a15SPatrick Williams "DeviceId"; 58235ad613dSLakshmi Yadlapati const std::string* property = nullptr; 58335ad613dSLakshmi Yadlapati for (const auto& propEntry : pcieDevProperties) 58435ad613dSLakshmi Yadlapati { 58535ad613dSLakshmi Yadlapati if (propEntry.first == devIDProperty) 58635ad613dSLakshmi Yadlapati { 58735ad613dSLakshmi Yadlapati property = std::get_if<std::string>(&propEntry.second); 58835ad613dSLakshmi Yadlapati break; 58935ad613dSLakshmi Yadlapati } 59035ad613dSLakshmi Yadlapati } 59135ad613dSLakshmi Yadlapati if (property == nullptr || property->empty()) 59235ad613dSLakshmi Yadlapati { 59335ad613dSLakshmi Yadlapati continue; 59435ad613dSLakshmi Yadlapati } 59535ad613dSLakshmi Yadlapati 59635ad613dSLakshmi Yadlapati nlohmann::json::object_t pcieFunction; 597ef4c65b7SEd Tanous pcieFunction["@odata.id"] = boost::urls::format( 598ef4c65b7SEd Tanous "/redfish/v1/Systems/system/PCIeDevices/{}/PCIeFunctions/{}", 599ef4c65b7SEd Tanous pcieDeviceId, std::to_string(functionNum)); 600b2ba3072SPatrick Williams pcieFunctionList.emplace_back(std::move(pcieFunction)); 60135ad613dSLakshmi Yadlapati } 60235ad613dSLakshmi Yadlapati res.jsonValue["PCIeFunctions@odata.count"] = pcieFunctionList.size(); 60335ad613dSLakshmi Yadlapati } 60435ad613dSLakshmi Yadlapati 60535ad613dSLakshmi Yadlapati inline void handlePCIeFunctionCollectionGet( 60635ad613dSLakshmi Yadlapati App& app, const crow::Request& req, 607ac106bf6SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 6087f3e84a1SEd Tanous const std::string& systemName, const std::string& pcieDeviceId) 60935ad613dSLakshmi Yadlapati { 610ac106bf6SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 61135ad613dSLakshmi Yadlapati { 61235ad613dSLakshmi Yadlapati return; 61335ad613dSLakshmi Yadlapati } 6147f3e84a1SEd Tanous if constexpr (bmcwebEnableMultiHost) 6157f3e84a1SEd Tanous { 6167f3e84a1SEd Tanous // Option currently returns no systems. TBD 6177f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 6187f3e84a1SEd Tanous systemName); 6197f3e84a1SEd Tanous return; 6207f3e84a1SEd Tanous } 62135ad613dSLakshmi Yadlapati 62235ad613dSLakshmi Yadlapati getValidPCIeDevicePath( 623ac106bf6SEd Tanous pcieDeviceId, asyncResp, 624ac106bf6SEd Tanous [asyncResp, pcieDeviceId](const std::string& pcieDevicePath, 62535ad613dSLakshmi Yadlapati const std::string& service) { 626ac106bf6SEd Tanous asyncResp->res.addHeader( 62735ad613dSLakshmi Yadlapati boost::beast::http::field::link, 62835ad613dSLakshmi Yadlapati "</redfish/v1/JsonSchemas/PCIeFunctionCollection/PCIeFunctionCollection.json>; rel=describedby"); 629ac106bf6SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 63035ad613dSLakshmi Yadlapati "#PCIeFunctionCollection.PCIeFunctionCollection"; 631ac106bf6SEd Tanous asyncResp->res.jsonValue["@odata.id"] = boost::urls::format( 632ef4c65b7SEd Tanous "/redfish/v1/Systems/system/PCIeDevices/{}/PCIeFunctions", 633ef4c65b7SEd Tanous pcieDeviceId); 634ac106bf6SEd Tanous asyncResp->res.jsonValue["Name"] = "PCIe Function Collection"; 635ac106bf6SEd Tanous asyncResp->res.jsonValue["Description"] = 63635ad613dSLakshmi Yadlapati "Collection of PCIe Functions for PCIe Device " + pcieDeviceId; 63735ad613dSLakshmi Yadlapati getPCIeDeviceProperties( 638ac106bf6SEd Tanous asyncResp, pcieDevicePath, service, 639ac106bf6SEd Tanous [asyncResp, pcieDeviceId]( 64035ad613dSLakshmi Yadlapati const dbus::utility::DBusPropertiesMap& pcieDevProperties) { 641ac106bf6SEd Tanous addPCIeFunctionList(asyncResp->res, pcieDeviceId, 642ac106bf6SEd Tanous pcieDevProperties); 64335ad613dSLakshmi Yadlapati }); 64435ad613dSLakshmi Yadlapati }); 64535ad613dSLakshmi Yadlapati } 64635ad613dSLakshmi Yadlapati 6477e860f15SJohn Edward Broadbent inline void requestRoutesSystemPCIeFunctionCollection(App& app) 6487e860f15SJohn Edward Broadbent { 649dede6a98SJason M. Bills /** 650dede6a98SJason M. Bills * Functions triggers appropriate requests on DBus 651dede6a98SJason M. Bills */ 6527e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 6537f3e84a1SEd Tanous "/redfish/v1/Systems/<str>/PCIeDevices/<str>/PCIeFunctions/") 654ed398213SEd Tanous .privileges(redfish::privileges::getPCIeFunctionCollection) 655002d39b4SEd Tanous .methods(boost::beast::http::verb::get)( 65635ad613dSLakshmi Yadlapati std::bind_front(handlePCIeFunctionCollectionGet, std::ref(app))); 6577e860f15SJohn Edward Broadbent } 6587e860f15SJohn Edward Broadbent 659727a046cSLakshmi Yadlapati inline bool validatePCIeFunctionId( 660d5e74b80SMyung Bae uint64_t pcieFunctionId, 661727a046cSLakshmi Yadlapati const dbus::utility::DBusPropertiesMap& pcieDevProperties) 6627e860f15SJohn Edward Broadbent { 663d5e74b80SMyung Bae std::string functionName = "Function" + std::to_string(pcieFunctionId); 664b9d36b47SEd Tanous std::string devIDProperty = functionName + "DeviceId"; 665b9d36b47SEd Tanous 666b9d36b47SEd Tanous const std::string* devIdProperty = nullptr; 667b9d36b47SEd Tanous for (const auto& property : pcieDevProperties) 668b9d36b47SEd Tanous { 669b9d36b47SEd Tanous if (property.first == devIDProperty) 670b9d36b47SEd Tanous { 671002d39b4SEd Tanous devIdProperty = std::get_if<std::string>(&property.second); 672727a046cSLakshmi Yadlapati break; 673b9d36b47SEd Tanous } 674b9d36b47SEd Tanous } 675727a046cSLakshmi Yadlapati return (devIdProperty != nullptr && !devIdProperty->empty()); 676727a046cSLakshmi Yadlapati } 677727a046cSLakshmi Yadlapati 678727a046cSLakshmi Yadlapati inline void addPCIeFunctionProperties( 679e14742caSEd Tanous crow::Response& resp, uint64_t pcieFunctionId, 680727a046cSLakshmi Yadlapati const dbus::utility::DBusPropertiesMap& pcieDevProperties) 681f5c9f8bdSJason M. Bills { 682e14742caSEd Tanous std::string functionName = "Function" + std::to_string(pcieFunctionId); 683b9d36b47SEd Tanous for (const auto& property : pcieDevProperties) 684f5c9f8bdSJason M. Bills { 685b9d36b47SEd Tanous const std::string* strProperty = 686b9d36b47SEd Tanous std::get_if<std::string>(&property.second); 687727a046cSLakshmi Yadlapati 688b9d36b47SEd Tanous if (property.first == functionName + "DeviceId") 689f5c9f8bdSJason M. Bills { 690727a046cSLakshmi Yadlapati resp.jsonValue["DeviceId"] = *strProperty; 691f5c9f8bdSJason M. Bills } 692b9d36b47SEd Tanous if (property.first == functionName + "VendorId") 693f5c9f8bdSJason M. Bills { 694727a046cSLakshmi Yadlapati resp.jsonValue["VendorId"] = *strProperty; 695f5c9f8bdSJason M. Bills } 696727a046cSLakshmi Yadlapati // TODO: FunctionType and DeviceClass are Redfish enums. The D-Bus 697727a046cSLakshmi Yadlapati // property strings should be mapped correctly to ensure these 698727a046cSLakshmi Yadlapati // strings are Redfish enum values. For now just check for empty. 699b9d36b47SEd Tanous if (property.first == functionName + "FunctionType") 700f5c9f8bdSJason M. Bills { 701727a046cSLakshmi Yadlapati if (!strProperty->empty()) 702727a046cSLakshmi Yadlapati { 703727a046cSLakshmi Yadlapati resp.jsonValue["FunctionType"] = *strProperty; 704727a046cSLakshmi Yadlapati } 705f5c9f8bdSJason M. Bills } 706b9d36b47SEd Tanous if (property.first == functionName + "DeviceClass") 707f5c9f8bdSJason M. Bills { 708727a046cSLakshmi Yadlapati if (!strProperty->empty()) 709727a046cSLakshmi Yadlapati { 710727a046cSLakshmi Yadlapati resp.jsonValue["DeviceClass"] = *strProperty; 711727a046cSLakshmi Yadlapati } 712f5c9f8bdSJason M. Bills } 713b9d36b47SEd Tanous if (property.first == functionName + "ClassCode") 714f5c9f8bdSJason M. Bills { 715727a046cSLakshmi Yadlapati resp.jsonValue["ClassCode"] = *strProperty; 716f5c9f8bdSJason M. Bills } 717b9d36b47SEd Tanous if (property.first == functionName + "RevisionId") 718f5c9f8bdSJason M. Bills { 719727a046cSLakshmi Yadlapati resp.jsonValue["RevisionId"] = *strProperty; 720f5c9f8bdSJason M. Bills } 721b9d36b47SEd Tanous if (property.first == functionName + "SubsystemId") 722b9d36b47SEd Tanous { 723727a046cSLakshmi Yadlapati resp.jsonValue["SubsystemId"] = *strProperty; 724b9d36b47SEd Tanous } 725002d39b4SEd Tanous if (property.first == functionName + "SubsystemVendorId") 726f5c9f8bdSJason M. Bills { 727727a046cSLakshmi Yadlapati resp.jsonValue["SubsystemVendorId"] = *strProperty; 728b9d36b47SEd Tanous } 729f5c9f8bdSJason M. Bills } 730727a046cSLakshmi Yadlapati } 731727a046cSLakshmi Yadlapati 732727a046cSLakshmi Yadlapati inline void addPCIeFunctionCommonProperties(crow::Response& resp, 733727a046cSLakshmi Yadlapati const std::string& pcieDeviceId, 734e14742caSEd Tanous uint64_t pcieFunctionId) 735727a046cSLakshmi Yadlapati { 736727a046cSLakshmi Yadlapati resp.addHeader( 737727a046cSLakshmi Yadlapati boost::beast::http::field::link, 738727a046cSLakshmi Yadlapati "</redfish/v1/JsonSchemas/PCIeFunction/PCIeFunction.json>; rel=describedby"); 739727a046cSLakshmi Yadlapati resp.jsonValue["@odata.type"] = "#PCIeFunction.v1_2_3.PCIeFunction"; 740ef4c65b7SEd Tanous resp.jsonValue["@odata.id"] = boost::urls::format( 741ef4c65b7SEd Tanous "/redfish/v1/Systems/system/PCIeDevices/{}/PCIeFunctions/{}", 742768a143dSLakshmi Yadlapati pcieDeviceId, std::to_string(pcieFunctionId)); 743727a046cSLakshmi Yadlapati resp.jsonValue["Name"] = "PCIe Function"; 744e14742caSEd Tanous resp.jsonValue["Id"] = std::to_string(pcieFunctionId); 745e14742caSEd Tanous resp.jsonValue["FunctionId"] = pcieFunctionId; 746ef4c65b7SEd Tanous resp.jsonValue["Links"]["PCIeDevice"]["@odata.id"] = boost::urls::format( 747ef4c65b7SEd Tanous "/redfish/v1/Systems/system/PCIeDevices/{}", pcieDeviceId); 748727a046cSLakshmi Yadlapati } 749727a046cSLakshmi Yadlapati 750727a046cSLakshmi Yadlapati inline void 751727a046cSLakshmi Yadlapati handlePCIeFunctionGet(App& app, const crow::Request& req, 752ac106bf6SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 7537f3e84a1SEd Tanous const std::string& systemName, 754727a046cSLakshmi Yadlapati const std::string& pcieDeviceId, 755e14742caSEd Tanous const std::string& pcieFunctionIdStr) 756727a046cSLakshmi Yadlapati { 757ac106bf6SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 758727a046cSLakshmi Yadlapati { 759727a046cSLakshmi Yadlapati return; 760727a046cSLakshmi Yadlapati } 7617f3e84a1SEd Tanous if constexpr (bmcwebEnableMultiHost) 7627f3e84a1SEd Tanous { 7637f3e84a1SEd Tanous // Option currently returns no systems. TBD 7647f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 7657f3e84a1SEd Tanous systemName); 7667f3e84a1SEd Tanous return; 7677f3e84a1SEd Tanous } 7687f3e84a1SEd Tanous if (systemName != "system") 7697f3e84a1SEd Tanous { 7707f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 7717f3e84a1SEd Tanous systemName); 7727f3e84a1SEd Tanous return; 7737f3e84a1SEd Tanous } 7747f3e84a1SEd Tanous 775e14742caSEd Tanous uint64_t pcieFunctionId = 0; 776e14742caSEd Tanous std::from_chars_result result = std::from_chars( 777e14742caSEd Tanous &*pcieFunctionIdStr.begin(), &*pcieFunctionIdStr.end(), pcieFunctionId); 778e14742caSEd Tanous if (result.ec != std::errc{} || result.ptr != &*pcieFunctionIdStr.end()) 779e14742caSEd Tanous { 780ac106bf6SEd Tanous messages::resourceNotFound(asyncResp->res, "PCIeFunction", 781e14742caSEd Tanous pcieFunctionIdStr); 782e14742caSEd Tanous return; 783e14742caSEd Tanous } 784727a046cSLakshmi Yadlapati 785ac106bf6SEd Tanous getValidPCIeDevicePath(pcieDeviceId, asyncResp, 786ac106bf6SEd Tanous [asyncResp, pcieDeviceId, 787ac106bf6SEd Tanous pcieFunctionId](const std::string& pcieDevicePath, 788727a046cSLakshmi Yadlapati const std::string& service) { 789727a046cSLakshmi Yadlapati getPCIeDeviceProperties( 790ac106bf6SEd Tanous asyncResp, pcieDevicePath, service, 791ac106bf6SEd Tanous [asyncResp, pcieDeviceId, pcieFunctionId]( 792727a046cSLakshmi Yadlapati const dbus::utility::DBusPropertiesMap& pcieDevProperties) { 793ac106bf6SEd Tanous addPCIeFunctionCommonProperties(asyncResp->res, pcieDeviceId, 794727a046cSLakshmi Yadlapati pcieFunctionId); 795ac106bf6SEd Tanous addPCIeFunctionProperties(asyncResp->res, pcieFunctionId, 796727a046cSLakshmi Yadlapati pcieDevProperties); 7977e860f15SJohn Edward Broadbent }); 798727a046cSLakshmi Yadlapati }); 799727a046cSLakshmi Yadlapati } 800727a046cSLakshmi Yadlapati 801727a046cSLakshmi Yadlapati inline void requestRoutesSystemPCIeFunction(App& app) 802727a046cSLakshmi Yadlapati { 803727a046cSLakshmi Yadlapati BMCWEB_ROUTE( 8047f3e84a1SEd Tanous app, "/redfish/v1/Systems/<str>/PCIeDevices/<str>/PCIeFunctions/<str>/") 805727a046cSLakshmi Yadlapati .privileges(redfish::privileges::getPCIeFunction) 806727a046cSLakshmi Yadlapati .methods(boost::beast::http::verb::get)( 807727a046cSLakshmi Yadlapati std::bind_front(handlePCIeFunctionGet, std::ref(app))); 808f5c9f8bdSJason M. Bills } 809f5c9f8bdSJason M. Bills 810f5c9f8bdSJason M. Bills } // namespace redfish 811