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" 210ec8b83dSEd Tanous #include "generated/enums/pcie_device.hpp" 223ccb3adbSEd Tanous #include "query.hpp" 233ccb3adbSEd Tanous #include "registries/privilege_registry.hpp" 243ccb3adbSEd Tanous #include "utils/dbus_utils.hpp" 250ec8b83dSEd Tanous 26f5c9f8bdSJason M. Bills #include <boost/system/linux_error.hpp> 27d1bde9e5SKrzysztof Grobelny #include <sdbusplus/asio/property.hpp> 28d1bde9e5SKrzysztof Grobelny #include <sdbusplus/unpack_properties.hpp> 29f5c9f8bdSJason M. Bills 30f5c9f8bdSJason M. Bills namespace redfish 31f5c9f8bdSJason M. Bills { 32f5c9f8bdSJason M. Bills 33f5c9f8bdSJason M. Bills static constexpr char const* pcieService = "xyz.openbmc_project.PCIe"; 34f5c9f8bdSJason M. Bills static constexpr char const* pciePath = "/xyz/openbmc_project/PCIe"; 35f5c9f8bdSJason M. Bills static constexpr char const* pcieDeviceInterface = 36f5c9f8bdSJason M. Bills "xyz.openbmc_project.PCIe.Device"; 37f5c9f8bdSJason M. Bills 38b5a76932SEd Tanous static inline void 398d1b46d7Szhanghch05 getPCIeDeviceList(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 40adbe192aSJason M. Bills const std::string& name) 41f5c9f8bdSJason M. Bills { 427a1dbc48SGeorge Liu dbus::utility::getSubTreePaths( 437a1dbc48SGeorge Liu pciePath, 1, {}, 447a1dbc48SGeorge Liu [asyncResp, name](const boost::system::error_code& ec, 45b9d36b47SEd Tanous const dbus::utility::MapperGetSubTreePathsResponse& 46b9d36b47SEd Tanous pcieDevicePaths) { 47f5c9f8bdSJason M. Bills if (ec) 48f5c9f8bdSJason M. Bills { 49a2730f01SAndrew Geissler BMCWEB_LOG_DEBUG << "no PCIe device paths found ec: " 50f5c9f8bdSJason M. Bills << ec.message(); 51a2730f01SAndrew Geissler // Not an error, system just doesn't have PCIe info 52f5c9f8bdSJason M. Bills return; 53f5c9f8bdSJason M. Bills } 54adbe192aSJason M. Bills nlohmann::json& pcieDeviceList = asyncResp->res.jsonValue[name]; 55f5c9f8bdSJason M. Bills pcieDeviceList = nlohmann::json::array(); 56f5c9f8bdSJason M. Bills for (const std::string& pcieDevicePath : pcieDevicePaths) 57f5c9f8bdSJason M. Bills { 583174e4dfSEd Tanous size_t devStart = pcieDevicePath.rfind('/'); 59f5c9f8bdSJason M. Bills if (devStart == std::string::npos) 60f5c9f8bdSJason M. Bills { 61f5c9f8bdSJason M. Bills continue; 62f5c9f8bdSJason M. Bills } 63f5c9f8bdSJason M. Bills 64f5c9f8bdSJason M. Bills std::string devName = pcieDevicePath.substr(devStart + 1); 65f5c9f8bdSJason M. Bills if (devName.empty()) 66f5c9f8bdSJason M. Bills { 67f5c9f8bdSJason M. Bills continue; 68f5c9f8bdSJason M. Bills } 691476687dSEd Tanous nlohmann::json::object_t pcieDevice; 70eddfc437SWilly Tu pcieDevice["@odata.id"] = crow::utility::urlFromPieces( 71eddfc437SWilly Tu "redfish", "v1", "Systems", "system", "PCIeDevices", devName); 721476687dSEd Tanous pcieDeviceList.push_back(std::move(pcieDevice)); 73f5c9f8bdSJason M. Bills } 74002d39b4SEd Tanous asyncResp->res.jsonValue[name + "@odata.count"] = pcieDeviceList.size(); 757a1dbc48SGeorge Liu }); 76f5c9f8bdSJason M. Bills } 77f5c9f8bdSJason M. Bills 787e860f15SJohn Edward Broadbent inline void requestRoutesSystemPCIeDeviceCollection(App& app) 79adbe192aSJason M. Bills { 80adbe192aSJason M. Bills /** 81adbe192aSJason M. Bills * Functions triggers appropriate requests on DBus 82adbe192aSJason M. Bills */ 8322d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/PCIeDevices/") 84ed398213SEd Tanous .privileges(redfish::privileges::getPCIeDeviceCollection) 857e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 8645ca1b86SEd Tanous [&app](const crow::Request& req, 8722d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 8822d268cbSEd Tanous const std::string& systemName) { 893ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 90adbe192aSJason M. Bills { 9145ca1b86SEd Tanous return; 9245ca1b86SEd Tanous } 9322d268cbSEd Tanous if (systemName != "system") 9422d268cbSEd Tanous { 9522d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 9622d268cbSEd Tanous systemName); 9722d268cbSEd Tanous return; 9822d268cbSEd Tanous } 991476687dSEd Tanous 1001476687dSEd Tanous asyncResp->res.jsonValue["@odata.type"] = 1011476687dSEd Tanous "#PCIeDeviceCollection.PCIeDeviceCollection"; 1021476687dSEd Tanous asyncResp->res.jsonValue["@odata.id"] = 1031476687dSEd Tanous "/redfish/v1/Systems/system/PCIeDevices"; 1041476687dSEd Tanous asyncResp->res.jsonValue["Name"] = "PCIe Device Collection"; 105002d39b4SEd Tanous asyncResp->res.jsonValue["Description"] = "Collection of PCIe Devices"; 1061476687dSEd Tanous asyncResp->res.jsonValue["Members"] = nlohmann::json::array(); 1071476687dSEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = 0; 108adbe192aSJason M. Bills getPCIeDeviceList(asyncResp, "Members"); 1097e860f15SJohn Edward Broadbent }); 110f5c9f8bdSJason M. Bills } 111f5c9f8bdSJason M. Bills 1120ec8b83dSEd Tanous inline std::optional<pcie_device::PCIeTypes> 11362cd45afSSpencer Ku redfishPcieGenerationFromDbus(const std::string& generationInUse) 11462cd45afSSpencer Ku { 11562cd45afSSpencer Ku if (generationInUse == 11662cd45afSSpencer Ku "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen1") 11762cd45afSSpencer Ku { 1180ec8b83dSEd Tanous return pcie_device::PCIeTypes::Gen1; 11962cd45afSSpencer Ku } 12062cd45afSSpencer Ku if (generationInUse == 12162cd45afSSpencer Ku "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen2") 12262cd45afSSpencer Ku { 1230ec8b83dSEd Tanous return pcie_device::PCIeTypes::Gen2; 12462cd45afSSpencer Ku } 12562cd45afSSpencer Ku if (generationInUse == 12662cd45afSSpencer Ku "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen3") 12762cd45afSSpencer Ku { 1280ec8b83dSEd Tanous return pcie_device::PCIeTypes::Gen3; 12962cd45afSSpencer Ku } 13062cd45afSSpencer Ku if (generationInUse == 13162cd45afSSpencer Ku "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen4") 13262cd45afSSpencer Ku { 1330ec8b83dSEd Tanous return pcie_device::PCIeTypes::Gen4; 13462cd45afSSpencer Ku } 13562cd45afSSpencer Ku if (generationInUse == 13662cd45afSSpencer Ku "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen5") 13762cd45afSSpencer Ku { 1380ec8b83dSEd Tanous return pcie_device::PCIeTypes::Gen5; 13962cd45afSSpencer Ku } 140e825cbc8SEd Tanous if (generationInUse.empty() || 141e825cbc8SEd Tanous generationInUse == 14262cd45afSSpencer Ku "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Unknown") 14362cd45afSSpencer Ku { 1440ec8b83dSEd Tanous return pcie_device::PCIeTypes::Invalid; 14562cd45afSSpencer Ku } 14662cd45afSSpencer Ku 14762cd45afSSpencer Ku // The value is not unknown or Gen1-5, need return an internal error. 14862cd45afSSpencer Ku return std::nullopt; 14962cd45afSSpencer Ku } 15062cd45afSSpencer Ku 1517e860f15SJohn Edward Broadbent inline void requestRoutesSystemPCIeDevice(App& app) 152f5c9f8bdSJason M. Bills { 15322d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/PCIeDevices/<str>/") 154ed398213SEd Tanous .privileges(redfish::privileges::getPCIeDevice) 155002d39b4SEd Tanous .methods(boost::beast::http::verb::get)( 156002d39b4SEd Tanous [&app](const crow::Request& req, 1577e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 15822d268cbSEd Tanous const std::string& systemName, const std::string& device) { 1593ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 1607e860f15SJohn Edward Broadbent { 16145ca1b86SEd Tanous return; 16245ca1b86SEd Tanous } 16322d268cbSEd Tanous if (systemName != "system") 16422d268cbSEd Tanous { 16522d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 16622d268cbSEd Tanous systemName); 16722d268cbSEd Tanous return; 16822d268cbSEd Tanous } 16922d268cbSEd Tanous 170168e20c1SEd Tanous auto getPCIeDeviceCallback = 17145ca1b86SEd Tanous [asyncResp, device]( 172*5e7e2dc5SEd Tanous const boost::system::error_code& ec, 17345ca1b86SEd Tanous const dbus::utility::DBusPropertiesMap& pcieDevProperties) { 174f5c9f8bdSJason M. Bills if (ec) 175f5c9f8bdSJason M. Bills { 176f5c9f8bdSJason M. Bills BMCWEB_LOG_DEBUG 177002d39b4SEd Tanous << "failed to get PCIe Device properties ec: " << ec.value() 178002d39b4SEd Tanous << ": " << ec.message(); 17945ca1b86SEd Tanous if (ec.value() == 18045ca1b86SEd Tanous boost::system::linux_error::bad_request_descriptor) 181f5c9f8bdSJason M. Bills { 182002d39b4SEd Tanous messages::resourceNotFound(asyncResp->res, "PCIeDevice", 183002d39b4SEd Tanous device); 184f5c9f8bdSJason M. Bills } 185f5c9f8bdSJason M. Bills else 186f5c9f8bdSJason M. Bills { 187f5c9f8bdSJason M. Bills messages::internalError(asyncResp->res); 188f5c9f8bdSJason M. Bills } 189f5c9f8bdSJason M. Bills return; 190f5c9f8bdSJason M. Bills } 191f5c9f8bdSJason M. Bills 192d1bde9e5SKrzysztof Grobelny const std::string* manufacturer = nullptr; 193d1bde9e5SKrzysztof Grobelny const std::string* deviceType = nullptr; 194d1bde9e5SKrzysztof Grobelny const std::string* generationInUse = nullptr; 195703f6741SMyung Bae const size_t* lanesInUse = nullptr; 196d1bde9e5SKrzysztof Grobelny 197d1bde9e5SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 198d1bde9e5SKrzysztof Grobelny dbus_utils::UnpackErrorPrinter(), pcieDevProperties, 199d1bde9e5SKrzysztof Grobelny "Manufacturer", manufacturer, "DeviceType", deviceType, 200703f6741SMyung Bae "LanesInUse", lanesInUse, "GenerationInUse", generationInUse); 201d1bde9e5SKrzysztof Grobelny 202d1bde9e5SKrzysztof Grobelny if (!success) 203d1bde9e5SKrzysztof Grobelny { 204d1bde9e5SKrzysztof Grobelny messages::internalError(asyncResp->res); 205d1bde9e5SKrzysztof Grobelny return; 206d1bde9e5SKrzysztof Grobelny } 207d1bde9e5SKrzysztof Grobelny 208703f6741SMyung Bae // The default value of LanesInUse is 0, and the field will be 209703f6741SMyung Bae // left as off if it is a default value. 210703f6741SMyung Bae if (lanesInUse != nullptr && *lanesInUse != 0) 211703f6741SMyung Bae { 212703f6741SMyung Bae asyncResp->res.jsonValue["PCIeInterface"]["LanesInUse"] = 213703f6741SMyung Bae *lanesInUse; 214703f6741SMyung Bae } 215703f6741SMyung Bae 216d1bde9e5SKrzysztof Grobelny if (generationInUse != nullptr) 217d1bde9e5SKrzysztof Grobelny { 2180ec8b83dSEd Tanous std::optional<pcie_device::PCIeTypes> redfishGenerationInUse = 219d1bde9e5SKrzysztof Grobelny redfishPcieGenerationFromDbus(*generationInUse); 220d1bde9e5SKrzysztof Grobelny if (!redfishGenerationInUse) 221d1bde9e5SKrzysztof Grobelny { 222d1bde9e5SKrzysztof Grobelny messages::internalError(asyncResp->res); 223d1bde9e5SKrzysztof Grobelny return; 224d1bde9e5SKrzysztof Grobelny } 2250ec8b83dSEd Tanous if (*redfishGenerationInUse != pcie_device::PCIeTypes::Invalid) 226d1bde9e5SKrzysztof Grobelny { 227d1bde9e5SKrzysztof Grobelny asyncResp->res.jsonValue["PCIeInterface"]["PCIeType"] = 228d1bde9e5SKrzysztof Grobelny *redfishGenerationInUse; 229d1bde9e5SKrzysztof Grobelny } 230a9f68bb5STony Lee } 231d1bde9e5SKrzysztof Grobelny 232d1bde9e5SKrzysztof Grobelny if (manufacturer != nullptr) 233d1bde9e5SKrzysztof Grobelny { 234d1bde9e5SKrzysztof Grobelny asyncResp->res.jsonValue["Manufacturer"] = *manufacturer; 235d1bde9e5SKrzysztof Grobelny } 236d1bde9e5SKrzysztof Grobelny 237d1bde9e5SKrzysztof Grobelny if (deviceType != nullptr) 238d1bde9e5SKrzysztof Grobelny { 239d1bde9e5SKrzysztof Grobelny asyncResp->res.jsonValue["DeviceType"] = *deviceType; 240d1bde9e5SKrzysztof Grobelny } 241d1bde9e5SKrzysztof Grobelny 2421476687dSEd Tanous asyncResp->res.jsonValue["@odata.type"] = 2431476687dSEd Tanous "#PCIeDevice.v1_4_0.PCIeDevice"; 2441476687dSEd Tanous asyncResp->res.jsonValue["@odata.id"] = 245eddfc437SWilly Tu crow::utility::urlFromPieces("redfish", "v1", "Systems", 246eddfc437SWilly Tu "system", "PCIeDevices", device); 2471476687dSEd Tanous asyncResp->res.jsonValue["Name"] = "PCIe Device"; 2481476687dSEd Tanous asyncResp->res.jsonValue["Id"] = device; 2491476687dSEd Tanous 2501476687dSEd Tanous asyncResp->res.jsonValue["PCIeFunctions"]["@odata.id"] = 251eddfc437SWilly Tu crow::utility::urlFromPieces("redfish", "v1", "Systems", 252eddfc437SWilly Tu "system", "PCIeDevices", device, 253eddfc437SWilly Tu "PCIeFunctions"); 254dede6a98SJason M. Bills }; 255dede6a98SJason M. Bills std::string escapedPath = std::string(pciePath) + "/" + device; 256dede6a98SJason M. Bills dbus::utility::escapePathForDbus(escapedPath); 257d1bde9e5SKrzysztof Grobelny sdbusplus::asio::getAllProperties( 258d1bde9e5SKrzysztof Grobelny *crow::connections::systemBus, pcieService, escapedPath, 259d1bde9e5SKrzysztof Grobelny pcieDeviceInterface, std::move(getPCIeDeviceCallback)); 2607e860f15SJohn Edward Broadbent }); 261dede6a98SJason M. Bills } 262dede6a98SJason M. Bills 2637e860f15SJohn Edward Broadbent inline void requestRoutesSystemPCIeFunctionCollection(App& app) 2647e860f15SJohn Edward Broadbent { 265dede6a98SJason M. Bills /** 266dede6a98SJason M. Bills * Functions triggers appropriate requests on DBus 267dede6a98SJason M. Bills */ 2687e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 2697e860f15SJohn Edward Broadbent "/redfish/v1/Systems/system/PCIeDevices/<str>/PCIeFunctions/") 270ed398213SEd Tanous .privileges(redfish::privileges::getPCIeFunctionCollection) 271002d39b4SEd Tanous .methods(boost::beast::http::verb::get)( 272002d39b4SEd Tanous [&app](const crow::Request& req, 2737e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 27445ca1b86SEd Tanous const std::string& device) { 2753ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 276dede6a98SJason M. Bills { 27745ca1b86SEd Tanous return; 27845ca1b86SEd Tanous } 2791476687dSEd Tanous 2801476687dSEd Tanous asyncResp->res.jsonValue["@odata.type"] = 2811476687dSEd Tanous "#PCIeFunctionCollection.PCIeFunctionCollection"; 282eddfc437SWilly Tu asyncResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces( 283eddfc437SWilly Tu "redfish", "v1", "Systems", "system", "PCIeDevices", device, 284eddfc437SWilly Tu "PCIeFunctions"); 2851476687dSEd Tanous asyncResp->res.jsonValue["Name"] = "PCIe Function Collection"; 2861476687dSEd Tanous asyncResp->res.jsonValue["Description"] = 2871476687dSEd Tanous "Collection of PCIe Functions for PCIe Device " + device; 288dede6a98SJason M. Bills 289b9d36b47SEd Tanous auto getPCIeDeviceCallback = 29045ca1b86SEd Tanous [asyncResp, device]( 291*5e7e2dc5SEd Tanous const boost::system::error_code& ec, 29245ca1b86SEd Tanous const dbus::utility::DBusPropertiesMap& pcieDevProperties) { 2937e860f15SJohn Edward Broadbent if (ec) 2947e860f15SJohn Edward Broadbent { 2957e860f15SJohn Edward Broadbent BMCWEB_LOG_DEBUG 296002d39b4SEd Tanous << "failed to get PCIe Device properties ec: " << ec.value() 297002d39b4SEd Tanous << ": " << ec.message(); 29845ca1b86SEd Tanous if (ec.value() == 29945ca1b86SEd Tanous boost::system::linux_error::bad_request_descriptor) 3007e860f15SJohn Edward Broadbent { 301002d39b4SEd Tanous messages::resourceNotFound(asyncResp->res, "PCIeDevice", 302002d39b4SEd Tanous device); 3037e860f15SJohn Edward Broadbent } 3047e860f15SJohn Edward Broadbent else 3057e860f15SJohn Edward Broadbent { 3067e860f15SJohn Edward Broadbent messages::internalError(asyncResp->res); 3077e860f15SJohn Edward Broadbent } 3087e860f15SJohn Edward Broadbent return; 3097e860f15SJohn Edward Broadbent } 3107e860f15SJohn Edward Broadbent 3117e860f15SJohn Edward Broadbent nlohmann::json& pcieFunctionList = 3127e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Members"]; 3137e860f15SJohn Edward Broadbent pcieFunctionList = nlohmann::json::array(); 3147e860f15SJohn Edward Broadbent static constexpr const int maxPciFunctionNum = 8; 31545ca1b86SEd Tanous for (int functionNum = 0; functionNum < maxPciFunctionNum; 31645ca1b86SEd Tanous functionNum++) 3177e860f15SJohn Edward Broadbent { 318b9d36b47SEd Tanous // Check if this function exists by looking for a 319b9d36b47SEd Tanous // device ID 3207e860f15SJohn Edward Broadbent std::string devIDProperty = 321002d39b4SEd Tanous "Function" + std::to_string(functionNum) + "DeviceId"; 322b9d36b47SEd Tanous const std::string* property = nullptr; 323b9d36b47SEd Tanous for (const auto& propEntry : pcieDevProperties) 3247e860f15SJohn Edward Broadbent { 325b9d36b47SEd Tanous if (propEntry.first == devIDProperty) 326b9d36b47SEd Tanous { 327002d39b4SEd Tanous property = std::get_if<std::string>(&propEntry.second); 328b9d36b47SEd Tanous } 329b9d36b47SEd Tanous } 330fb0ecc3eSNan Zhou if (property == nullptr || property->empty()) 331b9d36b47SEd Tanous { 332e28ce0e6SNan Zhou continue; 333b9d36b47SEd Tanous } 3341476687dSEd Tanous nlohmann::json::object_t pcieFunction; 335eddfc437SWilly Tu pcieFunction["@odata.id"] = crow::utility::urlFromPieces( 336eddfc437SWilly Tu "redfish", "v1", "Systems", "system", "PCIeDevices", device, 337eddfc437SWilly Tu "PCIeFunctions", std::to_string(functionNum)); 3381476687dSEd Tanous pcieFunctionList.push_back(std::move(pcieFunction)); 3397e860f15SJohn Edward Broadbent } 340a818d15aSJiaqing Zhao asyncResp->res.jsonValue["Members@odata.count"] = 3417e860f15SJohn Edward Broadbent pcieFunctionList.size(); 3427e860f15SJohn Edward Broadbent }; 3437e860f15SJohn Edward Broadbent std::string escapedPath = std::string(pciePath) + "/" + device; 3447e860f15SJohn Edward Broadbent dbus::utility::escapePathForDbus(escapedPath); 345d1bde9e5SKrzysztof Grobelny sdbusplus::asio::getAllProperties( 346d1bde9e5SKrzysztof Grobelny *crow::connections::systemBus, pcieService, escapedPath, 347d1bde9e5SKrzysztof Grobelny pcieDeviceInterface, std::move(getPCIeDeviceCallback)); 3487e860f15SJohn Edward Broadbent }); 3497e860f15SJohn Edward Broadbent } 3507e860f15SJohn Edward Broadbent 3517e860f15SJohn Edward Broadbent inline void requestRoutesSystemPCIeFunction(App& app) 3527e860f15SJohn Edward Broadbent { 3537e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 3547e860f15SJohn Edward Broadbent app, 3557e860f15SJohn Edward Broadbent "/redfish/v1/Systems/system/PCIeDevices/<str>/PCIeFunctions/<str>/") 356ed398213SEd Tanous .privileges(redfish::privileges::getPCIeFunction) 357002d39b4SEd Tanous .methods(boost::beast::http::verb::get)( 358002d39b4SEd Tanous [&app](const crow::Request& req, 35945ca1b86SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 360002d39b4SEd Tanous const std::string& device, const std::string& function) { 3613ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 36245ca1b86SEd Tanous { 36345ca1b86SEd Tanous return; 36445ca1b86SEd Tanous } 365168e20c1SEd Tanous auto getPCIeDeviceCallback = 366168e20c1SEd Tanous [asyncResp, device, function]( 367*5e7e2dc5SEd Tanous const boost::system::error_code& ec, 368b9d36b47SEd Tanous const dbus::utility::DBusPropertiesMap& pcieDevProperties) { 369dede6a98SJason M. Bills if (ec) 370dede6a98SJason M. Bills { 371dede6a98SJason M. Bills BMCWEB_LOG_DEBUG 372002d39b4SEd Tanous << "failed to get PCIe Device properties ec: " << ec.value() 373002d39b4SEd Tanous << ": " << ec.message(); 374dede6a98SJason M. Bills if (ec.value() == 375dede6a98SJason M. Bills boost::system::linux_error::bad_request_descriptor) 376dede6a98SJason M. Bills { 377002d39b4SEd Tanous messages::resourceNotFound(asyncResp->res, "PCIeDevice", 378002d39b4SEd Tanous device); 379dede6a98SJason M. Bills } 380dede6a98SJason M. Bills else 381dede6a98SJason M. Bills { 382dede6a98SJason M. Bills messages::internalError(asyncResp->res); 383dede6a98SJason M. Bills } 384dede6a98SJason M. Bills return; 385dede6a98SJason M. Bills } 386dede6a98SJason M. Bills 3871476687dSEd Tanous // Check if this function exists by looking for a device 3881476687dSEd Tanous // ID 389b9d36b47SEd Tanous std::string functionName = "Function" + function; 390b9d36b47SEd Tanous std::string devIDProperty = functionName + "DeviceId"; 391b9d36b47SEd Tanous 392b9d36b47SEd Tanous const std::string* devIdProperty = nullptr; 393b9d36b47SEd Tanous for (const auto& property : pcieDevProperties) 394b9d36b47SEd Tanous { 395b9d36b47SEd Tanous if (property.first == devIDProperty) 396b9d36b47SEd Tanous { 397002d39b4SEd Tanous devIdProperty = std::get_if<std::string>(&property.second); 398b9d36b47SEd Tanous continue; 399b9d36b47SEd Tanous } 400b9d36b47SEd Tanous } 401973c1355STony Lee if (devIdProperty == nullptr || devIdProperty->empty()) 402f5c9f8bdSJason M. Bills { 403002d39b4SEd Tanous messages::resourceNotFound(asyncResp->res, "PCIeFunction", 404002d39b4SEd Tanous function); 405f5c9f8bdSJason M. Bills return; 406f5c9f8bdSJason M. Bills } 407f5c9f8bdSJason M. Bills 4081476687dSEd Tanous asyncResp->res.jsonValue["@odata.type"] = 4091476687dSEd Tanous "#PCIeFunction.v1_2_0.PCIeFunction"; 4101476687dSEd Tanous asyncResp->res.jsonValue["@odata.id"] = 411eddfc437SWilly Tu crow::utility::urlFromPieces("redfish", "v1", "Systems", 412eddfc437SWilly Tu "system", "PCIeDevices", device, 413eddfc437SWilly Tu "PCIeFunctions", function); 4141476687dSEd Tanous asyncResp->res.jsonValue["Name"] = "PCIe Function"; 4151476687dSEd Tanous asyncResp->res.jsonValue["Id"] = function; 416002d39b4SEd Tanous asyncResp->res.jsonValue["FunctionId"] = std::stoi(function); 417002d39b4SEd Tanous asyncResp->res.jsonValue["Links"]["PCIeDevice"]["@odata.id"] = 418eddfc437SWilly Tu crow::utility::urlFromPieces("redfish", "v1", "Systems", 419eddfc437SWilly Tu "system", "PCIeDevices", device); 420f5c9f8bdSJason M. Bills 421b9d36b47SEd Tanous for (const auto& property : pcieDevProperties) 422f5c9f8bdSJason M. Bills { 423b9d36b47SEd Tanous const std::string* strProperty = 424b9d36b47SEd Tanous std::get_if<std::string>(&property.second); 425b9d36b47SEd Tanous if (property.first == functionName + "DeviceId") 426f5c9f8bdSJason M. Bills { 427b9d36b47SEd Tanous asyncResp->res.jsonValue["DeviceId"] = *strProperty; 428f5c9f8bdSJason M. Bills } 429b9d36b47SEd Tanous if (property.first == functionName + "VendorId") 430f5c9f8bdSJason M. Bills { 431b9d36b47SEd Tanous asyncResp->res.jsonValue["VendorId"] = *strProperty; 432f5c9f8bdSJason M. Bills } 433b9d36b47SEd Tanous if (property.first == functionName + "FunctionType") 434f5c9f8bdSJason M. Bills { 435002d39b4SEd Tanous asyncResp->res.jsonValue["FunctionType"] = *strProperty; 436f5c9f8bdSJason M. Bills } 437b9d36b47SEd Tanous if (property.first == functionName + "DeviceClass") 438f5c9f8bdSJason M. Bills { 439002d39b4SEd Tanous asyncResp->res.jsonValue["DeviceClass"] = *strProperty; 440f5c9f8bdSJason M. Bills } 441b9d36b47SEd Tanous if (property.first == functionName + "ClassCode") 442f5c9f8bdSJason M. Bills { 443002d39b4SEd Tanous asyncResp->res.jsonValue["ClassCode"] = *strProperty; 444f5c9f8bdSJason M. Bills } 445b9d36b47SEd Tanous if (property.first == functionName + "RevisionId") 446f5c9f8bdSJason M. Bills { 447002d39b4SEd Tanous asyncResp->res.jsonValue["RevisionId"] = *strProperty; 448f5c9f8bdSJason M. Bills } 449b9d36b47SEd Tanous if (property.first == functionName + "SubsystemId") 450b9d36b47SEd Tanous { 451002d39b4SEd Tanous asyncResp->res.jsonValue["SubsystemId"] = *strProperty; 452b9d36b47SEd Tanous } 453002d39b4SEd Tanous if (property.first == functionName + "SubsystemVendorId") 454f5c9f8bdSJason M. Bills { 455168e20c1SEd Tanous asyncResp->res.jsonValue["SubsystemVendorId"] = 456b9d36b47SEd Tanous *strProperty; 457b9d36b47SEd Tanous } 458f5c9f8bdSJason M. Bills } 459f5c9f8bdSJason M. Bills }; 460f5c9f8bdSJason M. Bills std::string escapedPath = std::string(pciePath) + "/" + device; 461f5c9f8bdSJason M. Bills dbus::utility::escapePathForDbus(escapedPath); 462d1bde9e5SKrzysztof Grobelny sdbusplus::asio::getAllProperties( 463d1bde9e5SKrzysztof Grobelny *crow::connections::systemBus, pcieService, escapedPath, 464d1bde9e5SKrzysztof Grobelny pcieDeviceInterface, std::move(getPCIeDeviceCallback)); 4657e860f15SJohn Edward Broadbent }); 466f5c9f8bdSJason M. Bills } 467f5c9f8bdSJason M. Bills 468f5c9f8bdSJason M. Bills } // namespace redfish 469