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 197e860f15SJohn Edward Broadbent #include <app.hpp> 20f5c9f8bdSJason M. Bills #include <boost/system/linux_error.hpp> 21168e20c1SEd Tanous #include <dbus_utility.hpp> 2245ca1b86SEd Tanous #include <query.hpp> 23ed398213SEd Tanous #include <registries/privilege_registry.hpp> 24*d1bde9e5SKrzysztof Grobelny #include <sdbusplus/asio/property.hpp> 25*d1bde9e5SKrzysztof Grobelny #include <sdbusplus/unpack_properties.hpp> 26*d1bde9e5SKrzysztof Grobelny #include <utils/dbus_utils.hpp> 27f5c9f8bdSJason M. Bills 28f5c9f8bdSJason M. Bills namespace redfish 29f5c9f8bdSJason M. Bills { 30f5c9f8bdSJason M. Bills 31f5c9f8bdSJason M. Bills static constexpr char const* pcieService = "xyz.openbmc_project.PCIe"; 32f5c9f8bdSJason M. Bills static constexpr char const* pciePath = "/xyz/openbmc_project/PCIe"; 33f5c9f8bdSJason M. Bills static constexpr char const* pcieDeviceInterface = 34f5c9f8bdSJason M. Bills "xyz.openbmc_project.PCIe.Device"; 35f5c9f8bdSJason M. Bills 36b5a76932SEd Tanous static inline void 378d1b46d7Szhanghch05 getPCIeDeviceList(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 38adbe192aSJason M. Bills const std::string& name) 39f5c9f8bdSJason M. Bills { 40b9d36b47SEd Tanous auto getPCIeMapCallback = 41b9d36b47SEd Tanous [asyncResp, name](const boost::system::error_code ec, 42b9d36b47SEd Tanous const dbus::utility::MapperGetSubTreePathsResponse& 43b9d36b47SEd Tanous pcieDevicePaths) { 44f5c9f8bdSJason M. Bills if (ec) 45f5c9f8bdSJason M. Bills { 46a2730f01SAndrew Geissler BMCWEB_LOG_DEBUG << "no PCIe device paths found ec: " 47f5c9f8bdSJason M. Bills << ec.message(); 48a2730f01SAndrew Geissler // Not an error, system just doesn't have PCIe info 49f5c9f8bdSJason M. Bills return; 50f5c9f8bdSJason M. Bills } 51adbe192aSJason M. Bills nlohmann::json& pcieDeviceList = asyncResp->res.jsonValue[name]; 52f5c9f8bdSJason M. Bills pcieDeviceList = nlohmann::json::array(); 53f5c9f8bdSJason M. Bills for (const std::string& pcieDevicePath : pcieDevicePaths) 54f5c9f8bdSJason M. Bills { 553174e4dfSEd Tanous size_t devStart = pcieDevicePath.rfind('/'); 56f5c9f8bdSJason M. Bills if (devStart == std::string::npos) 57f5c9f8bdSJason M. Bills { 58f5c9f8bdSJason M. Bills continue; 59f5c9f8bdSJason M. Bills } 60f5c9f8bdSJason M. Bills 61f5c9f8bdSJason M. Bills std::string devName = pcieDevicePath.substr(devStart + 1); 62f5c9f8bdSJason M. Bills if (devName.empty()) 63f5c9f8bdSJason M. Bills { 64f5c9f8bdSJason M. Bills continue; 65f5c9f8bdSJason M. Bills } 661476687dSEd Tanous nlohmann::json::object_t pcieDevice; 671476687dSEd Tanous pcieDevice["@odata.id"] = 681476687dSEd Tanous "/redfish/v1/Systems/system/PCIeDevices/" + devName; 691476687dSEd Tanous pcieDeviceList.push_back(std::move(pcieDevice)); 70f5c9f8bdSJason M. Bills } 71002d39b4SEd Tanous asyncResp->res.jsonValue[name + "@odata.count"] = pcieDeviceList.size(); 72f5c9f8bdSJason M. Bills }; 73f5c9f8bdSJason M. Bills crow::connections::systemBus->async_method_call( 74f5c9f8bdSJason M. Bills std::move(getPCIeMapCallback), "xyz.openbmc_project.ObjectMapper", 75f5c9f8bdSJason M. Bills "/xyz/openbmc_project/object_mapper", 76f5c9f8bdSJason M. Bills "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", 77f5c9f8bdSJason M. Bills std::string(pciePath) + "/", 1, std::array<std::string, 0>()); 78f5c9f8bdSJason M. Bills } 79f5c9f8bdSJason M. Bills 807e860f15SJohn Edward Broadbent inline void requestRoutesSystemPCIeDeviceCollection(App& app) 81adbe192aSJason M. Bills { 82adbe192aSJason M. Bills /** 83adbe192aSJason M. Bills * Functions triggers appropriate requests on DBus 84adbe192aSJason M. Bills */ 857e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/PCIeDevices/") 86ed398213SEd Tanous .privileges(redfish::privileges::getPCIeDeviceCollection) 877e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 8845ca1b86SEd Tanous [&app](const crow::Request& req, 8945ca1b86SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 903ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 91adbe192aSJason M. Bills { 9245ca1b86SEd Tanous return; 9345ca1b86SEd Tanous } 941476687dSEd Tanous 951476687dSEd Tanous asyncResp->res.jsonValue["@odata.type"] = 961476687dSEd Tanous "#PCIeDeviceCollection.PCIeDeviceCollection"; 971476687dSEd Tanous asyncResp->res.jsonValue["@odata.id"] = 981476687dSEd Tanous "/redfish/v1/Systems/system/PCIeDevices"; 991476687dSEd Tanous asyncResp->res.jsonValue["Name"] = "PCIe Device Collection"; 100002d39b4SEd Tanous asyncResp->res.jsonValue["Description"] = "Collection of PCIe Devices"; 1011476687dSEd Tanous asyncResp->res.jsonValue["Members"] = nlohmann::json::array(); 1021476687dSEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = 0; 103adbe192aSJason M. Bills getPCIeDeviceList(asyncResp, "Members"); 1047e860f15SJohn Edward Broadbent }); 105f5c9f8bdSJason M. Bills } 106f5c9f8bdSJason M. Bills 10762cd45afSSpencer Ku inline std::optional<std::string> 10862cd45afSSpencer Ku redfishPcieGenerationFromDbus(const std::string& generationInUse) 10962cd45afSSpencer Ku { 11062cd45afSSpencer Ku if (generationInUse == 11162cd45afSSpencer Ku "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen1") 11262cd45afSSpencer Ku { 11362cd45afSSpencer Ku return "Gen1"; 11462cd45afSSpencer Ku } 11562cd45afSSpencer Ku if (generationInUse == 11662cd45afSSpencer Ku "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen2") 11762cd45afSSpencer Ku { 11862cd45afSSpencer Ku return "Gen2"; 11962cd45afSSpencer Ku } 12062cd45afSSpencer Ku if (generationInUse == 12162cd45afSSpencer Ku "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen3") 12262cd45afSSpencer Ku { 12362cd45afSSpencer Ku return "Gen3"; 12462cd45afSSpencer Ku } 12562cd45afSSpencer Ku if (generationInUse == 12662cd45afSSpencer Ku "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen4") 12762cd45afSSpencer Ku { 12862cd45afSSpencer Ku return "Gen4"; 12962cd45afSSpencer Ku } 13062cd45afSSpencer Ku if (generationInUse == 13162cd45afSSpencer Ku "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen5") 13262cd45afSSpencer Ku { 13362cd45afSSpencer Ku return "Gen5"; 13462cd45afSSpencer Ku } 135e825cbc8SEd Tanous if (generationInUse.empty() || 136e825cbc8SEd Tanous generationInUse == 13762cd45afSSpencer Ku "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Unknown") 13862cd45afSSpencer Ku { 13962cd45afSSpencer Ku return ""; 14062cd45afSSpencer Ku } 14162cd45afSSpencer Ku 14262cd45afSSpencer Ku // The value is not unknown or Gen1-5, need return an internal error. 14362cd45afSSpencer Ku return std::nullopt; 14462cd45afSSpencer Ku } 14562cd45afSSpencer Ku 1467e860f15SJohn Edward Broadbent inline void requestRoutesSystemPCIeDevice(App& app) 147f5c9f8bdSJason M. Bills { 1487e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/PCIeDevices/<str>/") 149ed398213SEd Tanous .privileges(redfish::privileges::getPCIeDevice) 150002d39b4SEd Tanous .methods(boost::beast::http::verb::get)( 151002d39b4SEd Tanous [&app](const crow::Request& req, 1527e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 15345ca1b86SEd Tanous const std::string& device) { 1543ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 1557e860f15SJohn Edward Broadbent { 15645ca1b86SEd Tanous return; 15745ca1b86SEd Tanous } 158168e20c1SEd Tanous auto getPCIeDeviceCallback = 15945ca1b86SEd Tanous [asyncResp, device]( 16045ca1b86SEd Tanous const boost::system::error_code ec, 16145ca1b86SEd Tanous const dbus::utility::DBusPropertiesMap& pcieDevProperties) { 162f5c9f8bdSJason M. Bills if (ec) 163f5c9f8bdSJason M. Bills { 164f5c9f8bdSJason M. Bills BMCWEB_LOG_DEBUG 165002d39b4SEd Tanous << "failed to get PCIe Device properties ec: " << ec.value() 166002d39b4SEd Tanous << ": " << ec.message(); 16745ca1b86SEd Tanous if (ec.value() == 16845ca1b86SEd Tanous boost::system::linux_error::bad_request_descriptor) 169f5c9f8bdSJason M. Bills { 170002d39b4SEd Tanous messages::resourceNotFound(asyncResp->res, "PCIeDevice", 171002d39b4SEd Tanous device); 172f5c9f8bdSJason M. Bills } 173f5c9f8bdSJason M. Bills else 174f5c9f8bdSJason M. Bills { 175f5c9f8bdSJason M. Bills messages::internalError(asyncResp->res); 176f5c9f8bdSJason M. Bills } 177f5c9f8bdSJason M. Bills return; 178f5c9f8bdSJason M. Bills } 179f5c9f8bdSJason M. Bills 180*d1bde9e5SKrzysztof Grobelny const std::string* manufacturer = nullptr; 181*d1bde9e5SKrzysztof Grobelny const std::string* deviceType = nullptr; 182*d1bde9e5SKrzysztof Grobelny const std::string* generationInUse = nullptr; 183*d1bde9e5SKrzysztof Grobelny 184*d1bde9e5SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 185*d1bde9e5SKrzysztof Grobelny dbus_utils::UnpackErrorPrinter(), pcieDevProperties, 186*d1bde9e5SKrzysztof Grobelny "Manufacturer", manufacturer, "DeviceType", deviceType, 187*d1bde9e5SKrzysztof Grobelny "GenerationInUse", generationInUse); 188*d1bde9e5SKrzysztof Grobelny 189*d1bde9e5SKrzysztof Grobelny if (!success) 190*d1bde9e5SKrzysztof Grobelny { 191*d1bde9e5SKrzysztof Grobelny messages::internalError(asyncResp->res); 192*d1bde9e5SKrzysztof Grobelny return; 193*d1bde9e5SKrzysztof Grobelny } 194*d1bde9e5SKrzysztof Grobelny 195*d1bde9e5SKrzysztof Grobelny if (generationInUse != nullptr) 196*d1bde9e5SKrzysztof Grobelny { 197*d1bde9e5SKrzysztof Grobelny std::optional<std::string> redfishGenerationInUse = 198*d1bde9e5SKrzysztof Grobelny redfishPcieGenerationFromDbus(*generationInUse); 199*d1bde9e5SKrzysztof Grobelny if (!redfishGenerationInUse) 200*d1bde9e5SKrzysztof Grobelny { 201*d1bde9e5SKrzysztof Grobelny messages::internalError(asyncResp->res); 202*d1bde9e5SKrzysztof Grobelny return; 203*d1bde9e5SKrzysztof Grobelny } 204*d1bde9e5SKrzysztof Grobelny if (redfishGenerationInUse->empty()) 205*d1bde9e5SKrzysztof Grobelny { 206*d1bde9e5SKrzysztof Grobelny // unknown, no need to handle 207*d1bde9e5SKrzysztof Grobelny return; 208*d1bde9e5SKrzysztof Grobelny } 209*d1bde9e5SKrzysztof Grobelny asyncResp->res.jsonValue["PCIeInterface"]["PCIeType"] = 210*d1bde9e5SKrzysztof Grobelny *redfishGenerationInUse; 211*d1bde9e5SKrzysztof Grobelny } 212*d1bde9e5SKrzysztof Grobelny 213*d1bde9e5SKrzysztof Grobelny if (manufacturer != nullptr) 214*d1bde9e5SKrzysztof Grobelny { 215*d1bde9e5SKrzysztof Grobelny asyncResp->res.jsonValue["Manufacturer"] = *manufacturer; 216*d1bde9e5SKrzysztof Grobelny } 217*d1bde9e5SKrzysztof Grobelny 218*d1bde9e5SKrzysztof Grobelny if (deviceType != nullptr) 219*d1bde9e5SKrzysztof Grobelny { 220*d1bde9e5SKrzysztof Grobelny asyncResp->res.jsonValue["DeviceType"] = *deviceType; 221*d1bde9e5SKrzysztof Grobelny } 222*d1bde9e5SKrzysztof Grobelny 2231476687dSEd Tanous asyncResp->res.jsonValue["@odata.type"] = 2241476687dSEd Tanous "#PCIeDevice.v1_4_0.PCIeDevice"; 2251476687dSEd Tanous asyncResp->res.jsonValue["@odata.id"] = 2261476687dSEd Tanous "/redfish/v1/Systems/system/PCIeDevices/" + device; 2271476687dSEd Tanous asyncResp->res.jsonValue["Name"] = "PCIe Device"; 2281476687dSEd Tanous asyncResp->res.jsonValue["Id"] = device; 2291476687dSEd Tanous 2301476687dSEd Tanous asyncResp->res.jsonValue["PCIeFunctions"]["@odata.id"] = 23145ca1b86SEd Tanous "/redfish/v1/Systems/system/PCIeDevices/" + device + 2321476687dSEd Tanous "/PCIeFunctions"; 233dede6a98SJason M. Bills }; 234dede6a98SJason M. Bills std::string escapedPath = std::string(pciePath) + "/" + device; 235dede6a98SJason M. Bills dbus::utility::escapePathForDbus(escapedPath); 236*d1bde9e5SKrzysztof Grobelny sdbusplus::asio::getAllProperties( 237*d1bde9e5SKrzysztof Grobelny *crow::connections::systemBus, pcieService, escapedPath, 238*d1bde9e5SKrzysztof Grobelny pcieDeviceInterface, std::move(getPCIeDeviceCallback)); 2397e860f15SJohn Edward Broadbent }); 240dede6a98SJason M. Bills } 241dede6a98SJason M. Bills 2427e860f15SJohn Edward Broadbent inline void requestRoutesSystemPCIeFunctionCollection(App& app) 2437e860f15SJohn Edward Broadbent { 244dede6a98SJason M. Bills /** 245dede6a98SJason M. Bills * Functions triggers appropriate requests on DBus 246dede6a98SJason M. Bills */ 2477e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 2487e860f15SJohn Edward Broadbent "/redfish/v1/Systems/system/PCIeDevices/<str>/PCIeFunctions/") 249ed398213SEd Tanous .privileges(redfish::privileges::getPCIeFunctionCollection) 250002d39b4SEd Tanous .methods(boost::beast::http::verb::get)( 251002d39b4SEd Tanous [&app](const crow::Request& req, 2527e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 25345ca1b86SEd Tanous const std::string& device) { 2543ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 255dede6a98SJason M. Bills { 25645ca1b86SEd Tanous return; 25745ca1b86SEd Tanous } 2581476687dSEd Tanous 2591476687dSEd Tanous asyncResp->res.jsonValue["@odata.type"] = 2601476687dSEd Tanous "#PCIeFunctionCollection.PCIeFunctionCollection"; 2611476687dSEd Tanous asyncResp->res.jsonValue["@odata.id"] = 2621476687dSEd Tanous "/redfish/v1/Systems/system/PCIeDevices/" + device + 2631476687dSEd Tanous "/PCIeFunctions"; 2641476687dSEd Tanous asyncResp->res.jsonValue["Name"] = "PCIe Function Collection"; 2651476687dSEd Tanous asyncResp->res.jsonValue["Description"] = 2661476687dSEd Tanous "Collection of PCIe Functions for PCIe Device " + device; 267dede6a98SJason M. Bills 268b9d36b47SEd Tanous auto getPCIeDeviceCallback = 26945ca1b86SEd Tanous [asyncResp, device]( 27045ca1b86SEd Tanous const boost::system::error_code ec, 27145ca1b86SEd Tanous const dbus::utility::DBusPropertiesMap& pcieDevProperties) { 2727e860f15SJohn Edward Broadbent if (ec) 2737e860f15SJohn Edward Broadbent { 2747e860f15SJohn Edward Broadbent BMCWEB_LOG_DEBUG 275002d39b4SEd Tanous << "failed to get PCIe Device properties ec: " << ec.value() 276002d39b4SEd Tanous << ": " << ec.message(); 27745ca1b86SEd Tanous if (ec.value() == 27845ca1b86SEd Tanous boost::system::linux_error::bad_request_descriptor) 2797e860f15SJohn Edward Broadbent { 280002d39b4SEd Tanous messages::resourceNotFound(asyncResp->res, "PCIeDevice", 281002d39b4SEd Tanous device); 2827e860f15SJohn Edward Broadbent } 2837e860f15SJohn Edward Broadbent else 2847e860f15SJohn Edward Broadbent { 2857e860f15SJohn Edward Broadbent messages::internalError(asyncResp->res); 2867e860f15SJohn Edward Broadbent } 2877e860f15SJohn Edward Broadbent return; 2887e860f15SJohn Edward Broadbent } 2897e860f15SJohn Edward Broadbent 2907e860f15SJohn Edward Broadbent nlohmann::json& pcieFunctionList = 2917e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Members"]; 2927e860f15SJohn Edward Broadbent pcieFunctionList = nlohmann::json::array(); 2937e860f15SJohn Edward Broadbent static constexpr const int maxPciFunctionNum = 8; 29445ca1b86SEd Tanous for (int functionNum = 0; functionNum < maxPciFunctionNum; 29545ca1b86SEd Tanous functionNum++) 2967e860f15SJohn Edward Broadbent { 297b9d36b47SEd Tanous // Check if this function exists by looking for a 298b9d36b47SEd Tanous // device ID 2997e860f15SJohn Edward Broadbent std::string devIDProperty = 300002d39b4SEd Tanous "Function" + std::to_string(functionNum) + "DeviceId"; 301b9d36b47SEd Tanous const std::string* property = nullptr; 302b9d36b47SEd Tanous for (const auto& propEntry : pcieDevProperties) 3037e860f15SJohn Edward Broadbent { 304b9d36b47SEd Tanous if (propEntry.first == devIDProperty) 305b9d36b47SEd Tanous { 306002d39b4SEd Tanous property = std::get_if<std::string>(&propEntry.second); 307b9d36b47SEd Tanous } 308b9d36b47SEd Tanous } 309b9d36b47SEd Tanous if (property == nullptr || !property->empty()) 310b9d36b47SEd Tanous { 311b9d36b47SEd Tanous return; 312b9d36b47SEd Tanous } 3131476687dSEd Tanous nlohmann::json::object_t pcieFunction; 3141476687dSEd Tanous pcieFunction["@odata.id"] = 3151476687dSEd Tanous "/redfish/v1/Systems/system/PCIeDevices/" + device + 3161476687dSEd Tanous "/PCIeFunctions/" + std::to_string(functionNum); 3171476687dSEd Tanous pcieFunctionList.push_back(std::move(pcieFunction)); 3187e860f15SJohn Edward Broadbent } 319a818d15aSJiaqing Zhao asyncResp->res.jsonValue["Members@odata.count"] = 3207e860f15SJohn Edward Broadbent pcieFunctionList.size(); 3217e860f15SJohn Edward Broadbent }; 3227e860f15SJohn Edward Broadbent std::string escapedPath = std::string(pciePath) + "/" + device; 3237e860f15SJohn Edward Broadbent dbus::utility::escapePathForDbus(escapedPath); 324*d1bde9e5SKrzysztof Grobelny sdbusplus::asio::getAllProperties( 325*d1bde9e5SKrzysztof Grobelny *crow::connections::systemBus, pcieService, escapedPath, 326*d1bde9e5SKrzysztof Grobelny pcieDeviceInterface, std::move(getPCIeDeviceCallback)); 3277e860f15SJohn Edward Broadbent }); 3287e860f15SJohn Edward Broadbent } 3297e860f15SJohn Edward Broadbent 3307e860f15SJohn Edward Broadbent inline void requestRoutesSystemPCIeFunction(App& app) 3317e860f15SJohn Edward Broadbent { 3327e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 3337e860f15SJohn Edward Broadbent app, 3347e860f15SJohn Edward Broadbent "/redfish/v1/Systems/system/PCIeDevices/<str>/PCIeFunctions/<str>/") 335ed398213SEd Tanous .privileges(redfish::privileges::getPCIeFunction) 336002d39b4SEd Tanous .methods(boost::beast::http::verb::get)( 337002d39b4SEd Tanous [&app](const crow::Request& req, 33845ca1b86SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 339002d39b4SEd Tanous const std::string& device, const std::string& function) { 3403ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 34145ca1b86SEd Tanous { 34245ca1b86SEd Tanous return; 34345ca1b86SEd Tanous } 344168e20c1SEd Tanous auto getPCIeDeviceCallback = 345168e20c1SEd Tanous [asyncResp, device, function]( 3467e860f15SJohn Edward Broadbent const boost::system::error_code ec, 347b9d36b47SEd Tanous const dbus::utility::DBusPropertiesMap& pcieDevProperties) { 348dede6a98SJason M. Bills if (ec) 349dede6a98SJason M. Bills { 350dede6a98SJason M. Bills BMCWEB_LOG_DEBUG 351002d39b4SEd Tanous << "failed to get PCIe Device properties ec: " << ec.value() 352002d39b4SEd Tanous << ": " << ec.message(); 353dede6a98SJason M. Bills if (ec.value() == 354dede6a98SJason M. Bills boost::system::linux_error::bad_request_descriptor) 355dede6a98SJason M. Bills { 356002d39b4SEd Tanous messages::resourceNotFound(asyncResp->res, "PCIeDevice", 357002d39b4SEd Tanous device); 358dede6a98SJason M. Bills } 359dede6a98SJason M. Bills else 360dede6a98SJason M. Bills { 361dede6a98SJason M. Bills messages::internalError(asyncResp->res); 362dede6a98SJason M. Bills } 363dede6a98SJason M. Bills return; 364dede6a98SJason M. Bills } 365dede6a98SJason M. Bills 3661476687dSEd Tanous // Check if this function exists by looking for a device 3671476687dSEd Tanous // ID 368b9d36b47SEd Tanous std::string functionName = "Function" + function; 369b9d36b47SEd Tanous std::string devIDProperty = functionName + "DeviceId"; 370b9d36b47SEd Tanous 371b9d36b47SEd Tanous const std::string* devIdProperty = nullptr; 372b9d36b47SEd Tanous for (const auto& property : pcieDevProperties) 373b9d36b47SEd Tanous { 374b9d36b47SEd Tanous if (property.first == devIDProperty) 375b9d36b47SEd Tanous { 376002d39b4SEd Tanous devIdProperty = std::get_if<std::string>(&property.second); 377b9d36b47SEd Tanous continue; 378b9d36b47SEd Tanous } 379b9d36b47SEd Tanous } 380b9d36b47SEd Tanous if (devIdProperty == nullptr || !devIdProperty->empty()) 381f5c9f8bdSJason M. Bills { 382002d39b4SEd Tanous messages::resourceNotFound(asyncResp->res, "PCIeFunction", 383002d39b4SEd Tanous function); 384f5c9f8bdSJason M. Bills return; 385f5c9f8bdSJason M. Bills } 386f5c9f8bdSJason M. Bills 3871476687dSEd Tanous asyncResp->res.jsonValue["@odata.type"] = 3881476687dSEd Tanous "#PCIeFunction.v1_2_0.PCIeFunction"; 3891476687dSEd Tanous asyncResp->res.jsonValue["@odata.id"] = 390168e20c1SEd Tanous "/redfish/v1/Systems/system/PCIeDevices/" + device + 3911476687dSEd Tanous "/PCIeFunctions/" + function; 3921476687dSEd Tanous asyncResp->res.jsonValue["Name"] = "PCIe Function"; 3931476687dSEd Tanous asyncResp->res.jsonValue["Id"] = function; 394002d39b4SEd Tanous asyncResp->res.jsonValue["FunctionId"] = std::stoi(function); 395002d39b4SEd Tanous asyncResp->res.jsonValue["Links"]["PCIeDevice"]["@odata.id"] = 3961476687dSEd Tanous "/redfish/v1/Systems/system/PCIeDevices/" + device; 397f5c9f8bdSJason M. Bills 398b9d36b47SEd Tanous for (const auto& property : pcieDevProperties) 399f5c9f8bdSJason M. Bills { 400b9d36b47SEd Tanous const std::string* strProperty = 401b9d36b47SEd Tanous std::get_if<std::string>(&property.second); 402b9d36b47SEd Tanous if (property.first == functionName + "DeviceId") 403f5c9f8bdSJason M. Bills { 404b9d36b47SEd Tanous asyncResp->res.jsonValue["DeviceId"] = *strProperty; 405f5c9f8bdSJason M. Bills } 406b9d36b47SEd Tanous if (property.first == functionName + "VendorId") 407f5c9f8bdSJason M. Bills { 408b9d36b47SEd Tanous asyncResp->res.jsonValue["VendorId"] = *strProperty; 409f5c9f8bdSJason M. Bills } 410b9d36b47SEd Tanous if (property.first == functionName + "FunctionType") 411f5c9f8bdSJason M. Bills { 412002d39b4SEd Tanous asyncResp->res.jsonValue["FunctionType"] = *strProperty; 413f5c9f8bdSJason M. Bills } 414b9d36b47SEd Tanous if (property.first == functionName + "DeviceClass") 415f5c9f8bdSJason M. Bills { 416002d39b4SEd Tanous asyncResp->res.jsonValue["DeviceClass"] = *strProperty; 417f5c9f8bdSJason M. Bills } 418b9d36b47SEd Tanous if (property.first == functionName + "ClassCode") 419f5c9f8bdSJason M. Bills { 420002d39b4SEd Tanous asyncResp->res.jsonValue["ClassCode"] = *strProperty; 421f5c9f8bdSJason M. Bills } 422b9d36b47SEd Tanous if (property.first == functionName + "RevisionId") 423f5c9f8bdSJason M. Bills { 424002d39b4SEd Tanous asyncResp->res.jsonValue["RevisionId"] = *strProperty; 425f5c9f8bdSJason M. Bills } 426b9d36b47SEd Tanous if (property.first == functionName + "SubsystemId") 427b9d36b47SEd Tanous { 428002d39b4SEd Tanous asyncResp->res.jsonValue["SubsystemId"] = *strProperty; 429b9d36b47SEd Tanous } 430002d39b4SEd Tanous if (property.first == functionName + "SubsystemVendorId") 431f5c9f8bdSJason M. Bills { 432168e20c1SEd Tanous asyncResp->res.jsonValue["SubsystemVendorId"] = 433b9d36b47SEd Tanous *strProperty; 434b9d36b47SEd Tanous } 435f5c9f8bdSJason M. Bills } 436f5c9f8bdSJason M. Bills }; 437f5c9f8bdSJason M. Bills std::string escapedPath = std::string(pciePath) + "/" + device; 438f5c9f8bdSJason M. Bills dbus::utility::escapePathForDbus(escapedPath); 439*d1bde9e5SKrzysztof Grobelny sdbusplus::asio::getAllProperties( 440*d1bde9e5SKrzysztof Grobelny *crow::connections::systemBus, pcieService, escapedPath, 441*d1bde9e5SKrzysztof Grobelny pcieDeviceInterface, std::move(getPCIeDeviceCallback)); 4427e860f15SJohn Edward Broadbent }); 443f5c9f8bdSJason M. Bills } 444f5c9f8bdSJason M. Bills 445f5c9f8bdSJason M. Bills } // namespace redfish 446