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> 24f5c9f8bdSJason M. Bills 25f5c9f8bdSJason M. Bills namespace redfish 26f5c9f8bdSJason M. Bills { 27f5c9f8bdSJason M. Bills 28f5c9f8bdSJason M. Bills static constexpr char const* pcieService = "xyz.openbmc_project.PCIe"; 29f5c9f8bdSJason M. Bills static constexpr char const* pciePath = "/xyz/openbmc_project/PCIe"; 30f5c9f8bdSJason M. Bills static constexpr char const* pcieDeviceInterface = 31f5c9f8bdSJason M. Bills "xyz.openbmc_project.PCIe.Device"; 32f5c9f8bdSJason M. Bills 33b5a76932SEd Tanous static inline void 348d1b46d7Szhanghch05 getPCIeDeviceList(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 35adbe192aSJason M. Bills const std::string& name) 36f5c9f8bdSJason M. Bills { 37b9d36b47SEd Tanous auto getPCIeMapCallback = 38b9d36b47SEd Tanous [asyncResp, name](const boost::system::error_code ec, 39b9d36b47SEd Tanous const dbus::utility::MapperGetSubTreePathsResponse& 40b9d36b47SEd Tanous pcieDevicePaths) { 41f5c9f8bdSJason M. Bills if (ec) 42f5c9f8bdSJason M. Bills { 43a2730f01SAndrew Geissler BMCWEB_LOG_DEBUG << "no PCIe device paths found ec: " 44f5c9f8bdSJason M. Bills << ec.message(); 45a2730f01SAndrew Geissler // Not an error, system just doesn't have PCIe info 46f5c9f8bdSJason M. Bills return; 47f5c9f8bdSJason M. Bills } 48adbe192aSJason M. Bills nlohmann::json& pcieDeviceList = asyncResp->res.jsonValue[name]; 49f5c9f8bdSJason M. Bills pcieDeviceList = nlohmann::json::array(); 50f5c9f8bdSJason M. Bills for (const std::string& pcieDevicePath : pcieDevicePaths) 51f5c9f8bdSJason M. Bills { 523174e4dfSEd Tanous size_t devStart = pcieDevicePath.rfind('/'); 53f5c9f8bdSJason M. Bills if (devStart == std::string::npos) 54f5c9f8bdSJason M. Bills { 55f5c9f8bdSJason M. Bills continue; 56f5c9f8bdSJason M. Bills } 57f5c9f8bdSJason M. Bills 58f5c9f8bdSJason M. Bills std::string devName = pcieDevicePath.substr(devStart + 1); 59f5c9f8bdSJason M. Bills if (devName.empty()) 60f5c9f8bdSJason M. Bills { 61f5c9f8bdSJason M. Bills continue; 62f5c9f8bdSJason M. Bills } 63*1476687dSEd Tanous nlohmann::json::object_t pcieDevice; 64*1476687dSEd Tanous pcieDevice["@odata.id"] = 65*1476687dSEd Tanous "/redfish/v1/Systems/system/PCIeDevices/" + devName; 66*1476687dSEd Tanous pcieDeviceList.push_back(std::move(pcieDevice)); 67f5c9f8bdSJason M. Bills } 68b9d36b47SEd Tanous asyncResp->res.jsonValue[name + "@odata.count"] = 69b9d36b47SEd Tanous pcieDeviceList.size(); 70f5c9f8bdSJason M. Bills }; 71f5c9f8bdSJason M. Bills crow::connections::systemBus->async_method_call( 72f5c9f8bdSJason M. Bills std::move(getPCIeMapCallback), "xyz.openbmc_project.ObjectMapper", 73f5c9f8bdSJason M. Bills "/xyz/openbmc_project/object_mapper", 74f5c9f8bdSJason M. Bills "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", 75f5c9f8bdSJason M. Bills std::string(pciePath) + "/", 1, std::array<std::string, 0>()); 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 */ 837e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/PCIeDevices/") 84ed398213SEd Tanous .privileges(redfish::privileges::getPCIeDeviceCollection) 857e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 8645ca1b86SEd Tanous [&app](const crow::Request& req, 8745ca1b86SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 8845ca1b86SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) 89adbe192aSJason M. Bills { 9045ca1b86SEd Tanous return; 9145ca1b86SEd Tanous } 92*1476687dSEd Tanous 93*1476687dSEd Tanous asyncResp->res.jsonValue["@odata.type"] = 94*1476687dSEd Tanous "#PCIeDeviceCollection.PCIeDeviceCollection"; 95*1476687dSEd Tanous asyncResp->res.jsonValue["@odata.id"] = 96*1476687dSEd Tanous "/redfish/v1/Systems/system/PCIeDevices"; 97*1476687dSEd Tanous asyncResp->res.jsonValue["Name"] = "PCIe Device Collection"; 98*1476687dSEd Tanous asyncResp->res.jsonValue["Description"] = 99*1476687dSEd Tanous "Collection of PCIe Devices"; 100*1476687dSEd Tanous asyncResp->res.jsonValue["Members"] = nlohmann::json::array(); 101*1476687dSEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = 0; 102adbe192aSJason M. Bills getPCIeDeviceList(asyncResp, "Members"); 1037e860f15SJohn Edward Broadbent }); 104f5c9f8bdSJason M. Bills } 105f5c9f8bdSJason M. Bills 10662cd45afSSpencer Ku inline std::optional<std::string> 10762cd45afSSpencer Ku redfishPcieGenerationFromDbus(const std::string& generationInUse) 10862cd45afSSpencer Ku { 10962cd45afSSpencer Ku if (generationInUse == 11062cd45afSSpencer Ku "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen1") 11162cd45afSSpencer Ku { 11262cd45afSSpencer Ku return "Gen1"; 11362cd45afSSpencer Ku } 11462cd45afSSpencer Ku if (generationInUse == 11562cd45afSSpencer Ku "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen2") 11662cd45afSSpencer Ku { 11762cd45afSSpencer Ku return "Gen2"; 11862cd45afSSpencer Ku } 11962cd45afSSpencer Ku if (generationInUse == 12062cd45afSSpencer Ku "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen3") 12162cd45afSSpencer Ku { 12262cd45afSSpencer Ku return "Gen3"; 12362cd45afSSpencer Ku } 12462cd45afSSpencer Ku if (generationInUse == 12562cd45afSSpencer Ku "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen4") 12662cd45afSSpencer Ku { 12762cd45afSSpencer Ku return "Gen4"; 12862cd45afSSpencer Ku } 12962cd45afSSpencer Ku if (generationInUse == 13062cd45afSSpencer Ku "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen5") 13162cd45afSSpencer Ku { 13262cd45afSSpencer Ku return "Gen5"; 13362cd45afSSpencer Ku } 13462cd45afSSpencer Ku if (generationInUse.empty() || 13562cd45afSSpencer Ku generationInUse == 13662cd45afSSpencer Ku "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Unknown") 13762cd45afSSpencer Ku { 13862cd45afSSpencer Ku return ""; 13962cd45afSSpencer Ku } 14062cd45afSSpencer Ku 14162cd45afSSpencer Ku // The value is not unknown or Gen1-5, need return an internal error. 14262cd45afSSpencer Ku return std::nullopt; 14362cd45afSSpencer Ku } 14462cd45afSSpencer Ku 1457e860f15SJohn Edward Broadbent inline void requestRoutesSystemPCIeDevice(App& app) 146f5c9f8bdSJason M. Bills { 1477e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/PCIeDevices/<str>/") 148ed398213SEd Tanous .privileges(redfish::privileges::getPCIeDevice) 14945ca1b86SEd Tanous .methods( 15045ca1b86SEd Tanous boost::beast::http::verb:: 15145ca1b86SEd Tanous get)([&app](const crow::Request& req, 1527e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 15345ca1b86SEd Tanous const std::string& device) { 15445ca1b86SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) 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 165f5c9f8bdSJason M. Bills << "failed to get PCIe Device properties ec: " 166271584abSEd Tanous << ec.value() << ": " << ec.message(); 16745ca1b86SEd Tanous if (ec.value() == 16845ca1b86SEd Tanous boost::system::linux_error::bad_request_descriptor) 169f5c9f8bdSJason M. Bills { 17045ca1b86SEd Tanous messages::resourceNotFound(asyncResp->res, 17145ca1b86SEd Tanous "PCIeDevice", 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*1476687dSEd Tanous asyncResp->res.jsonValue["@odata.type"] = 181*1476687dSEd Tanous "#PCIeDevice.v1_4_0.PCIeDevice"; 182*1476687dSEd Tanous asyncResp->res.jsonValue["@odata.id"] = 183*1476687dSEd Tanous "/redfish/v1/Systems/system/PCIeDevices/" + device; 184*1476687dSEd Tanous asyncResp->res.jsonValue["Name"] = "PCIe Device"; 185*1476687dSEd Tanous asyncResp->res.jsonValue["Id"] = device; 186*1476687dSEd Tanous 187*1476687dSEd Tanous asyncResp->res.jsonValue["PCIeFunctions"]["@odata.id"] = 18845ca1b86SEd Tanous "/redfish/v1/Systems/system/PCIeDevices/" + device + 189*1476687dSEd Tanous "/PCIeFunctions"; 190b9d36b47SEd Tanous for (const auto& property : pcieDevProperties) 191f5c9f8bdSJason M. Bills { 192b9d36b47SEd Tanous const std::string* propertyString = 193b9d36b47SEd Tanous std::get_if<std::string>(&property.second); 194b9d36b47SEd Tanous if (property.first == "Manufacturer") 195b9d36b47SEd Tanous { 196b9d36b47SEd Tanous if (propertyString == nullptr) 197b9d36b47SEd Tanous { 198b9d36b47SEd Tanous messages::internalError(asyncResp->res); 199b9d36b47SEd Tanous return; 200b9d36b47SEd Tanous } 201168e20c1SEd Tanous asyncResp->res.jsonValue["Manufacturer"] = 202b9d36b47SEd Tanous *propertyString; 203168e20c1SEd Tanous } 204b9d36b47SEd Tanous if (property.first == "DeviceType") 205168e20c1SEd Tanous { 206b9d36b47SEd Tanous if (propertyString == nullptr) 207b9d36b47SEd Tanous { 208b9d36b47SEd Tanous messages::internalError(asyncResp->res); 209b9d36b47SEd Tanous return; 210168e20c1SEd Tanous } 211b9d36b47SEd Tanous asyncResp->res.jsonValue["DeviceType"] = 212b9d36b47SEd Tanous *propertyString; 213f5c9f8bdSJason M. Bills } 214b9d36b47SEd Tanous if (property.first == "GenerationInUse") 21562cd45afSSpencer Ku { 216b9d36b47SEd Tanous if (propertyString == nullptr) 217b9d36b47SEd Tanous { 218b9d36b47SEd Tanous messages::internalError(asyncResp->res); 219b9d36b47SEd Tanous return; 220b9d36b47SEd Tanous } 22162cd45afSSpencer Ku std::optional<std::string> generationInUse = 22245ca1b86SEd Tanous redfishPcieGenerationFromDbus(*propertyString); 22362cd45afSSpencer Ku if (!generationInUse) 22462cd45afSSpencer Ku { 22562cd45afSSpencer Ku messages::internalError(asyncResp->res); 22662cd45afSSpencer Ku return; 22762cd45afSSpencer Ku } 22826f6976fSEd Tanous if (generationInUse->empty()) 22962cd45afSSpencer Ku { 23062cd45afSSpencer Ku // unknown, no need to handle 23162cd45afSSpencer Ku return; 23262cd45afSSpencer Ku } 233168e20c1SEd Tanous asyncResp->res 234213ffc70SAnjaliintel-21 .jsonValue["PCIeInterface"]["PCIeType"] = 23562cd45afSSpencer Ku *generationInUse; 23662cd45afSSpencer Ku } 237b9d36b47SEd Tanous } 238dede6a98SJason M. Bills }; 239dede6a98SJason M. Bills std::string escapedPath = std::string(pciePath) + "/" + device; 240dede6a98SJason M. Bills dbus::utility::escapePathForDbus(escapedPath); 241dede6a98SJason M. Bills crow::connections::systemBus->async_method_call( 242dede6a98SJason M. Bills std::move(getPCIeDeviceCallback), pcieService, escapedPath, 2437e860f15SJohn Edward Broadbent "org.freedesktop.DBus.Properties", "GetAll", 2447e860f15SJohn Edward Broadbent pcieDeviceInterface); 2457e860f15SJohn Edward Broadbent }); 246dede6a98SJason M. Bills } 247dede6a98SJason M. Bills 2487e860f15SJohn Edward Broadbent inline void requestRoutesSystemPCIeFunctionCollection(App& app) 2497e860f15SJohn Edward Broadbent { 250dede6a98SJason M. Bills /** 251dede6a98SJason M. Bills * Functions triggers appropriate requests on DBus 252dede6a98SJason M. Bills */ 2537e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 2547e860f15SJohn Edward Broadbent "/redfish/v1/Systems/system/PCIeDevices/<str>/PCIeFunctions/") 255ed398213SEd Tanous .privileges(redfish::privileges::getPCIeFunctionCollection) 25645ca1b86SEd Tanous .methods( 25745ca1b86SEd Tanous boost::beast::http::verb:: 25845ca1b86SEd Tanous get)([&app](const crow::Request& req, 2597e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 26045ca1b86SEd Tanous const std::string& device) { 26145ca1b86SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) 262dede6a98SJason M. Bills { 26345ca1b86SEd Tanous return; 26445ca1b86SEd Tanous } 265*1476687dSEd Tanous 266*1476687dSEd Tanous asyncResp->res.jsonValue["@odata.type"] = 267*1476687dSEd Tanous "#PCIeFunctionCollection.PCIeFunctionCollection"; 268*1476687dSEd Tanous asyncResp->res.jsonValue["@odata.id"] = 269*1476687dSEd Tanous "/redfish/v1/Systems/system/PCIeDevices/" + device + 270*1476687dSEd Tanous "/PCIeFunctions"; 271*1476687dSEd Tanous asyncResp->res.jsonValue["Name"] = "PCIe Function Collection"; 272*1476687dSEd Tanous asyncResp->res.jsonValue["Description"] = 273*1476687dSEd Tanous "Collection of PCIe Functions for PCIe Device " + device; 274dede6a98SJason M. Bills 275b9d36b47SEd Tanous auto getPCIeDeviceCallback = 27645ca1b86SEd Tanous [asyncResp, device]( 27745ca1b86SEd Tanous const boost::system::error_code ec, 27845ca1b86SEd Tanous const dbus::utility::DBusPropertiesMap& pcieDevProperties) { 2797e860f15SJohn Edward Broadbent if (ec) 2807e860f15SJohn Edward Broadbent { 2817e860f15SJohn Edward Broadbent BMCWEB_LOG_DEBUG 2827e860f15SJohn Edward Broadbent << "failed to get PCIe Device properties ec: " 2837e860f15SJohn Edward Broadbent << ec.value() << ": " << ec.message(); 28445ca1b86SEd Tanous if (ec.value() == 28545ca1b86SEd Tanous boost::system::linux_error::bad_request_descriptor) 2867e860f15SJohn Edward Broadbent { 28745ca1b86SEd Tanous messages::resourceNotFound(asyncResp->res, 28845ca1b86SEd Tanous "PCIeDevice", device); 2897e860f15SJohn Edward Broadbent } 2907e860f15SJohn Edward Broadbent else 2917e860f15SJohn Edward Broadbent { 2927e860f15SJohn Edward Broadbent messages::internalError(asyncResp->res); 2937e860f15SJohn Edward Broadbent } 2947e860f15SJohn Edward Broadbent return; 2957e860f15SJohn Edward Broadbent } 2967e860f15SJohn Edward Broadbent 2977e860f15SJohn Edward Broadbent nlohmann::json& pcieFunctionList = 2987e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Members"]; 2997e860f15SJohn Edward Broadbent pcieFunctionList = nlohmann::json::array(); 3007e860f15SJohn Edward Broadbent static constexpr const int maxPciFunctionNum = 8; 30145ca1b86SEd Tanous for (int functionNum = 0; functionNum < maxPciFunctionNum; 30245ca1b86SEd Tanous functionNum++) 3037e860f15SJohn Edward Broadbent { 304b9d36b47SEd Tanous // Check if this function exists by looking for a 305b9d36b47SEd Tanous // device ID 3067e860f15SJohn Edward Broadbent std::string devIDProperty = 3077e860f15SJohn Edward Broadbent "Function" + std::to_string(functionNum) + 3087e860f15SJohn Edward Broadbent "DeviceId"; 309b9d36b47SEd Tanous const std::string* property = nullptr; 310b9d36b47SEd Tanous for (const auto& propEntry : pcieDevProperties) 3117e860f15SJohn Edward Broadbent { 312b9d36b47SEd Tanous if (propEntry.first == devIDProperty) 313b9d36b47SEd Tanous { 31445ca1b86SEd Tanous property = 31545ca1b86SEd Tanous std::get_if<std::string>(&propEntry.second); 316b9d36b47SEd Tanous } 317b9d36b47SEd Tanous } 318b9d36b47SEd Tanous if (property == nullptr || !property->empty()) 319b9d36b47SEd Tanous { 320b9d36b47SEd Tanous return; 321b9d36b47SEd Tanous } 322*1476687dSEd Tanous nlohmann::json::object_t pcieFunction; 323*1476687dSEd Tanous pcieFunction["@odata.id"] = 324*1476687dSEd Tanous "/redfish/v1/Systems/system/PCIeDevices/" + device + 325*1476687dSEd Tanous "/PCIeFunctions/" + std::to_string(functionNum); 326*1476687dSEd Tanous pcieFunctionList.push_back(std::move(pcieFunction)); 3277e860f15SJohn Edward Broadbent } 328a818d15aSJiaqing Zhao asyncResp->res.jsonValue["Members@odata.count"] = 3297e860f15SJohn Edward Broadbent pcieFunctionList.size(); 3307e860f15SJohn Edward Broadbent }; 3317e860f15SJohn Edward Broadbent std::string escapedPath = std::string(pciePath) + "/" + device; 3327e860f15SJohn Edward Broadbent dbus::utility::escapePathForDbus(escapedPath); 3337e860f15SJohn Edward Broadbent crow::connections::systemBus->async_method_call( 3347e860f15SJohn Edward Broadbent std::move(getPCIeDeviceCallback), pcieService, escapedPath, 3357e860f15SJohn Edward Broadbent "org.freedesktop.DBus.Properties", "GetAll", 3367e860f15SJohn Edward Broadbent pcieDeviceInterface); 3377e860f15SJohn Edward Broadbent }); 3387e860f15SJohn Edward Broadbent } 3397e860f15SJohn Edward Broadbent 3407e860f15SJohn Edward Broadbent inline void requestRoutesSystemPCIeFunction(App& app) 3417e860f15SJohn Edward Broadbent { 3427e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 3437e860f15SJohn Edward Broadbent app, 3447e860f15SJohn Edward Broadbent "/redfish/v1/Systems/system/PCIeDevices/<str>/PCIeFunctions/<str>/") 345ed398213SEd Tanous .privileges(redfish::privileges::getPCIeFunction) 3467e860f15SJohn Edward Broadbent .methods( 34745ca1b86SEd Tanous boost::beast::http::verb:: 34845ca1b86SEd Tanous get)([&app](const crow::Request& req, 34945ca1b86SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 3507e860f15SJohn Edward Broadbent const std::string& device, 3517e860f15SJohn Edward Broadbent const std::string& function) { 35245ca1b86SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) 35345ca1b86SEd Tanous { 35445ca1b86SEd Tanous return; 35545ca1b86SEd Tanous } 356168e20c1SEd Tanous auto getPCIeDeviceCallback = 357168e20c1SEd Tanous [asyncResp, device, function]( 3587e860f15SJohn Edward Broadbent const boost::system::error_code ec, 359b9d36b47SEd Tanous const dbus::utility::DBusPropertiesMap& pcieDevProperties) { 360dede6a98SJason M. Bills if (ec) 361dede6a98SJason M. Bills { 362dede6a98SJason M. Bills BMCWEB_LOG_DEBUG 363dede6a98SJason M. Bills << "failed to get PCIe Device properties ec: " 364dede6a98SJason M. Bills << ec.value() << ": " << ec.message(); 365dede6a98SJason M. Bills if (ec.value() == 366dede6a98SJason M. Bills boost::system::linux_error::bad_request_descriptor) 367dede6a98SJason M. Bills { 368168e20c1SEd Tanous messages::resourceNotFound(asyncResp->res, 369168e20c1SEd Tanous "PCIeDevice", device); 370dede6a98SJason M. Bills } 371dede6a98SJason M. Bills else 372dede6a98SJason M. Bills { 373dede6a98SJason M. Bills messages::internalError(asyncResp->res); 374dede6a98SJason M. Bills } 375dede6a98SJason M. Bills return; 376dede6a98SJason M. Bills } 377dede6a98SJason M. Bills 378*1476687dSEd Tanous // Check if this function exists by looking for a device 379*1476687dSEd Tanous // ID 380b9d36b47SEd Tanous std::string functionName = "Function" + function; 381b9d36b47SEd Tanous std::string devIDProperty = functionName + "DeviceId"; 382b9d36b47SEd Tanous 383b9d36b47SEd Tanous const std::string* devIdProperty = nullptr; 384b9d36b47SEd Tanous for (const auto& property : pcieDevProperties) 385b9d36b47SEd Tanous { 386b9d36b47SEd Tanous if (property.first == devIDProperty) 387b9d36b47SEd Tanous { 388b9d36b47SEd Tanous devIdProperty = 389b9d36b47SEd Tanous std::get_if<std::string>(&property.second); 390b9d36b47SEd Tanous continue; 391b9d36b47SEd Tanous } 392b9d36b47SEd Tanous } 393b9d36b47SEd Tanous if (devIdProperty == nullptr || !devIdProperty->empty()) 394f5c9f8bdSJason M. Bills { 395168e20c1SEd Tanous messages::resourceNotFound(asyncResp->res, 396168e20c1SEd Tanous "PCIeFunction", function); 397f5c9f8bdSJason M. Bills return; 398f5c9f8bdSJason M. Bills } 399f5c9f8bdSJason M. Bills 400*1476687dSEd Tanous asyncResp->res.jsonValue["@odata.type"] = 401*1476687dSEd Tanous "#PCIeFunction.v1_2_0.PCIeFunction"; 402*1476687dSEd Tanous asyncResp->res.jsonValue["@odata.id"] = 403168e20c1SEd Tanous "/redfish/v1/Systems/system/PCIeDevices/" + device + 404*1476687dSEd Tanous "/PCIeFunctions/" + function; 405*1476687dSEd Tanous asyncResp->res.jsonValue["Name"] = "PCIe Function"; 406*1476687dSEd Tanous asyncResp->res.jsonValue["Id"] = function; 407*1476687dSEd Tanous asyncResp->res.jsonValue["FunctionId"] = 408*1476687dSEd Tanous std::stoi(function); 409*1476687dSEd Tanous asyncResp->res 410*1476687dSEd Tanous .jsonValue["Links"]["PCIeDevice"]["@odata.id"] = 411*1476687dSEd Tanous "/redfish/v1/Systems/system/PCIeDevices/" + device; 412f5c9f8bdSJason M. Bills 413b9d36b47SEd Tanous for (const auto& property : pcieDevProperties) 414f5c9f8bdSJason M. Bills { 415b9d36b47SEd Tanous const std::string* strProperty = 416b9d36b47SEd Tanous std::get_if<std::string>(&property.second); 417b9d36b47SEd Tanous if (property.first == functionName + "DeviceId") 418f5c9f8bdSJason M. Bills { 419b9d36b47SEd Tanous asyncResp->res.jsonValue["DeviceId"] = *strProperty; 420f5c9f8bdSJason M. Bills } 421b9d36b47SEd Tanous if (property.first == functionName + "VendorId") 422f5c9f8bdSJason M. Bills { 423b9d36b47SEd Tanous asyncResp->res.jsonValue["VendorId"] = *strProperty; 424f5c9f8bdSJason M. Bills } 425b9d36b47SEd Tanous if (property.first == functionName + "FunctionType") 426f5c9f8bdSJason M. Bills { 427b9d36b47SEd Tanous asyncResp->res.jsonValue["FunctionType"] = 428b9d36b47SEd Tanous *strProperty; 429f5c9f8bdSJason M. Bills } 430b9d36b47SEd Tanous if (property.first == functionName + "DeviceClass") 431f5c9f8bdSJason M. Bills { 432b9d36b47SEd Tanous asyncResp->res.jsonValue["DeviceClass"] = 433b9d36b47SEd Tanous *strProperty; 434f5c9f8bdSJason M. Bills } 435b9d36b47SEd Tanous if (property.first == functionName + "ClassCode") 436f5c9f8bdSJason M. Bills { 437b9d36b47SEd Tanous asyncResp->res.jsonValue["ClassCode"] = 438b9d36b47SEd Tanous *strProperty; 439f5c9f8bdSJason M. Bills } 440b9d36b47SEd Tanous if (property.first == functionName + "RevisionId") 441f5c9f8bdSJason M. Bills { 442b9d36b47SEd Tanous asyncResp->res.jsonValue["RevisionId"] = 443b9d36b47SEd Tanous *strProperty; 444f5c9f8bdSJason M. Bills } 445b9d36b47SEd Tanous if (property.first == functionName + "SubsystemId") 446b9d36b47SEd Tanous { 447b9d36b47SEd Tanous asyncResp->res.jsonValue["SubsystemId"] = 448b9d36b47SEd Tanous *strProperty; 449b9d36b47SEd Tanous } 450b9d36b47SEd Tanous if (property.first == 451b9d36b47SEd Tanous functionName + "SubsystemVendorId") 452f5c9f8bdSJason M. Bills { 453168e20c1SEd Tanous asyncResp->res.jsonValue["SubsystemVendorId"] = 454b9d36b47SEd Tanous *strProperty; 455b9d36b47SEd Tanous } 456f5c9f8bdSJason M. Bills } 457f5c9f8bdSJason M. Bills }; 458f5c9f8bdSJason M. Bills std::string escapedPath = std::string(pciePath) + "/" + device; 459f5c9f8bdSJason M. Bills dbus::utility::escapePathForDbus(escapedPath); 460f5c9f8bdSJason M. Bills crow::connections::systemBus->async_method_call( 461f5c9f8bdSJason M. Bills std::move(getPCIeDeviceCallback), pcieService, escapedPath, 4627e860f15SJohn Edward Broadbent "org.freedesktop.DBus.Properties", "GetAll", 4637e860f15SJohn Edward Broadbent pcieDeviceInterface); 4647e860f15SJohn Edward Broadbent }); 465f5c9f8bdSJason M. Bills } 466f5c9f8bdSJason M. Bills 467f5c9f8bdSJason M. Bills } // namespace redfish 468