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> 22*45ca1b86SEd 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 } 63f5c9f8bdSJason M. Bills pcieDeviceList.push_back( 64f5c9f8bdSJason M. Bills {{"@odata.id", 65f5c9f8bdSJason M. Bills "/redfish/v1/Systems/system/PCIeDevices/" + devName}}); 66f5c9f8bdSJason M. Bills } 67b9d36b47SEd Tanous asyncResp->res.jsonValue[name + "@odata.count"] = 68b9d36b47SEd Tanous pcieDeviceList.size(); 69f5c9f8bdSJason M. Bills }; 70f5c9f8bdSJason M. Bills crow::connections::systemBus->async_method_call( 71f5c9f8bdSJason M. Bills std::move(getPCIeMapCallback), "xyz.openbmc_project.ObjectMapper", 72f5c9f8bdSJason M. Bills "/xyz/openbmc_project/object_mapper", 73f5c9f8bdSJason M. Bills "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", 74f5c9f8bdSJason M. Bills std::string(pciePath) + "/", 1, std::array<std::string, 0>()); 75f5c9f8bdSJason M. Bills } 76f5c9f8bdSJason M. Bills 777e860f15SJohn Edward Broadbent inline void requestRoutesSystemPCIeDeviceCollection(App& app) 78adbe192aSJason M. Bills { 79adbe192aSJason M. Bills /** 80adbe192aSJason M. Bills * Functions triggers appropriate requests on DBus 81adbe192aSJason M. Bills */ 827e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/PCIeDevices/") 83ed398213SEd Tanous .privileges(redfish::privileges::getPCIeDeviceCollection) 847e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 85*45ca1b86SEd Tanous [&app](const crow::Request& req, 86*45ca1b86SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 87*45ca1b86SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) 88adbe192aSJason M. Bills { 89*45ca1b86SEd Tanous return; 90*45ca1b86SEd Tanous } 91adbe192aSJason M. Bills asyncResp->res.jsonValue = { 927e860f15SJohn Edward Broadbent {"@odata.type", 937e860f15SJohn Edward Broadbent "#PCIeDeviceCollection.PCIeDeviceCollection"}, 94adbe192aSJason M. Bills {"@odata.id", "/redfish/v1/Systems/system/PCIeDevices"}, 95adbe192aSJason M. Bills {"Name", "PCIe Device Collection"}, 96adbe192aSJason M. Bills {"Description", "Collection of PCIe Devices"}, 97adbe192aSJason M. Bills {"Members", nlohmann::json::array()}, 98adbe192aSJason M. Bills {"Members@odata.count", 0}}; 99adbe192aSJason M. Bills getPCIeDeviceList(asyncResp, "Members"); 1007e860f15SJohn Edward Broadbent }); 101f5c9f8bdSJason M. Bills } 102f5c9f8bdSJason M. Bills 10362cd45afSSpencer Ku inline std::optional<std::string> 10462cd45afSSpencer Ku redfishPcieGenerationFromDbus(const std::string& generationInUse) 10562cd45afSSpencer Ku { 10662cd45afSSpencer Ku if (generationInUse == 10762cd45afSSpencer Ku "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen1") 10862cd45afSSpencer Ku { 10962cd45afSSpencer Ku return "Gen1"; 11062cd45afSSpencer Ku } 11162cd45afSSpencer Ku if (generationInUse == 11262cd45afSSpencer Ku "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen2") 11362cd45afSSpencer Ku { 11462cd45afSSpencer Ku return "Gen2"; 11562cd45afSSpencer Ku } 11662cd45afSSpencer Ku if (generationInUse == 11762cd45afSSpencer Ku "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen3") 11862cd45afSSpencer Ku { 11962cd45afSSpencer Ku return "Gen3"; 12062cd45afSSpencer Ku } 12162cd45afSSpencer Ku if (generationInUse == 12262cd45afSSpencer Ku "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen4") 12362cd45afSSpencer Ku { 12462cd45afSSpencer Ku return "Gen4"; 12562cd45afSSpencer Ku } 12662cd45afSSpencer Ku if (generationInUse == 12762cd45afSSpencer Ku "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen5") 12862cd45afSSpencer Ku { 12962cd45afSSpencer Ku return "Gen5"; 13062cd45afSSpencer Ku } 13162cd45afSSpencer Ku if (generationInUse.empty() || 13262cd45afSSpencer Ku generationInUse == 13362cd45afSSpencer Ku "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Unknown") 13462cd45afSSpencer Ku { 13562cd45afSSpencer Ku return ""; 13662cd45afSSpencer Ku } 13762cd45afSSpencer Ku 13862cd45afSSpencer Ku // The value is not unknown or Gen1-5, need return an internal error. 13962cd45afSSpencer Ku return std::nullopt; 14062cd45afSSpencer Ku } 14162cd45afSSpencer Ku 1427e860f15SJohn Edward Broadbent inline void requestRoutesSystemPCIeDevice(App& app) 143f5c9f8bdSJason M. Bills { 1447e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/PCIeDevices/<str>/") 145ed398213SEd Tanous .privileges(redfish::privileges::getPCIeDevice) 146*45ca1b86SEd Tanous .methods( 147*45ca1b86SEd Tanous boost::beast::http::verb:: 148*45ca1b86SEd Tanous get)([&app](const crow::Request& req, 1497e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 150*45ca1b86SEd Tanous const std::string& device) { 151*45ca1b86SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) 1527e860f15SJohn Edward Broadbent { 153*45ca1b86SEd Tanous return; 154*45ca1b86SEd Tanous } 155168e20c1SEd Tanous auto getPCIeDeviceCallback = 156*45ca1b86SEd Tanous [asyncResp, device]( 157*45ca1b86SEd Tanous const boost::system::error_code ec, 158*45ca1b86SEd Tanous const dbus::utility::DBusPropertiesMap& pcieDevProperties) { 159f5c9f8bdSJason M. Bills if (ec) 160f5c9f8bdSJason M. Bills { 161f5c9f8bdSJason M. Bills BMCWEB_LOG_DEBUG 162f5c9f8bdSJason M. Bills << "failed to get PCIe Device properties ec: " 163271584abSEd Tanous << ec.value() << ": " << ec.message(); 164*45ca1b86SEd Tanous if (ec.value() == 165*45ca1b86SEd Tanous boost::system::linux_error::bad_request_descriptor) 166f5c9f8bdSJason M. Bills { 167*45ca1b86SEd Tanous messages::resourceNotFound(asyncResp->res, 168*45ca1b86SEd Tanous "PCIeDevice", device); 169f5c9f8bdSJason M. Bills } 170f5c9f8bdSJason M. Bills else 171f5c9f8bdSJason M. Bills { 172f5c9f8bdSJason M. Bills messages::internalError(asyncResp->res); 173f5c9f8bdSJason M. Bills } 174f5c9f8bdSJason M. Bills return; 175f5c9f8bdSJason M. Bills } 176f5c9f8bdSJason M. Bills 177f5c9f8bdSJason M. Bills asyncResp->res.jsonValue = { 178dede6a98SJason M. Bills {"@odata.type", "#PCIeDevice.v1_4_0.PCIeDevice"}, 179f5c9f8bdSJason M. Bills {"@odata.id", 180*45ca1b86SEd Tanous "/redfish/v1/Systems/system/PCIeDevices/" + device}, 181f5c9f8bdSJason M. Bills {"Name", "PCIe Device"}, 182f5c9f8bdSJason M. Bills {"Id", device}}; 183b9d36b47SEd Tanous asyncResp->res.jsonValue["PCIeFunctions"] = { 184b9d36b47SEd Tanous {"@odata.id", 185*45ca1b86SEd Tanous "/redfish/v1/Systems/system/PCIeDevices/" + device + 186*45ca1b86SEd Tanous "/PCIeFunctions"}}; 187b9d36b47SEd Tanous for (const auto& property : pcieDevProperties) 188f5c9f8bdSJason M. Bills { 189b9d36b47SEd Tanous const std::string* propertyString = 190b9d36b47SEd Tanous std::get_if<std::string>(&property.second); 191b9d36b47SEd Tanous if (property.first == "Manufacturer") 192b9d36b47SEd Tanous { 193b9d36b47SEd Tanous if (propertyString == nullptr) 194b9d36b47SEd Tanous { 195b9d36b47SEd Tanous messages::internalError(asyncResp->res); 196b9d36b47SEd Tanous return; 197b9d36b47SEd Tanous } 198168e20c1SEd Tanous asyncResp->res.jsonValue["Manufacturer"] = 199b9d36b47SEd Tanous *propertyString; 200168e20c1SEd Tanous } 201b9d36b47SEd Tanous if (property.first == "DeviceType") 202168e20c1SEd Tanous { 203b9d36b47SEd Tanous if (propertyString == nullptr) 204b9d36b47SEd Tanous { 205b9d36b47SEd Tanous messages::internalError(asyncResp->res); 206b9d36b47SEd Tanous return; 207168e20c1SEd Tanous } 208b9d36b47SEd Tanous asyncResp->res.jsonValue["DeviceType"] = 209b9d36b47SEd Tanous *propertyString; 210f5c9f8bdSJason M. Bills } 211b9d36b47SEd Tanous if (property.first == "DeviceType") 212f5c9f8bdSJason M. Bills { 213b9d36b47SEd Tanous if (propertyString == nullptr) 214b9d36b47SEd Tanous { 215b9d36b47SEd Tanous messages::internalError(asyncResp->res); 216b9d36b47SEd Tanous return; 217f5c9f8bdSJason M. Bills } 218b9d36b47SEd Tanous asyncResp->res.jsonValue["DeviceType"] = 219b9d36b47SEd Tanous *propertyString; 220b9d36b47SEd Tanous } 221b9d36b47SEd Tanous if (property.first == "GenerationInUse") 22262cd45afSSpencer Ku { 223b9d36b47SEd Tanous if (propertyString == nullptr) 224b9d36b47SEd Tanous { 225b9d36b47SEd Tanous messages::internalError(asyncResp->res); 226b9d36b47SEd Tanous return; 227b9d36b47SEd Tanous } 22862cd45afSSpencer Ku std::optional<std::string> generationInUse = 229*45ca1b86SEd Tanous redfishPcieGenerationFromDbus(*propertyString); 23062cd45afSSpencer Ku if (!generationInUse) 23162cd45afSSpencer Ku { 23262cd45afSSpencer Ku messages::internalError(asyncResp->res); 23362cd45afSSpencer Ku return; 23462cd45afSSpencer Ku } 23526f6976fSEd Tanous if (generationInUse->empty()) 23662cd45afSSpencer Ku { 23762cd45afSSpencer Ku // unknown, no need to handle 23862cd45afSSpencer Ku return; 23962cd45afSSpencer Ku } 240168e20c1SEd Tanous asyncResp->res 241213ffc70SAnjaliintel-21 .jsonValue["PCIeInterface"]["PCIeType"] = 24262cd45afSSpencer Ku *generationInUse; 24362cd45afSSpencer Ku } 244b9d36b47SEd Tanous } 245dede6a98SJason M. Bills }; 246dede6a98SJason M. Bills std::string escapedPath = std::string(pciePath) + "/" + device; 247dede6a98SJason M. Bills dbus::utility::escapePathForDbus(escapedPath); 248dede6a98SJason M. Bills crow::connections::systemBus->async_method_call( 249dede6a98SJason M. Bills std::move(getPCIeDeviceCallback), pcieService, escapedPath, 2507e860f15SJohn Edward Broadbent "org.freedesktop.DBus.Properties", "GetAll", 2517e860f15SJohn Edward Broadbent pcieDeviceInterface); 2527e860f15SJohn Edward Broadbent }); 253dede6a98SJason M. Bills } 254dede6a98SJason M. Bills 2557e860f15SJohn Edward Broadbent inline void requestRoutesSystemPCIeFunctionCollection(App& app) 2567e860f15SJohn Edward Broadbent { 257dede6a98SJason M. Bills /** 258dede6a98SJason M. Bills * Functions triggers appropriate requests on DBus 259dede6a98SJason M. Bills */ 2607e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 2617e860f15SJohn Edward Broadbent "/redfish/v1/Systems/system/PCIeDevices/<str>/PCIeFunctions/") 262ed398213SEd Tanous .privileges(redfish::privileges::getPCIeFunctionCollection) 263*45ca1b86SEd Tanous .methods( 264*45ca1b86SEd Tanous boost::beast::http::verb:: 265*45ca1b86SEd Tanous get)([&app](const crow::Request& req, 2667e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 267*45ca1b86SEd Tanous const std::string& device) { 268*45ca1b86SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) 269dede6a98SJason M. Bills { 270*45ca1b86SEd Tanous return; 271*45ca1b86SEd Tanous } 272dede6a98SJason M. Bills asyncResp->res.jsonValue = { 2737e860f15SJohn Edward Broadbent {"@odata.type", 2747e860f15SJohn Edward Broadbent "#PCIeFunctionCollection.PCIeFunctionCollection"}, 2757e860f15SJohn Edward Broadbent {"@odata.id", "/redfish/v1/Systems/system/PCIeDevices/" + 2767e860f15SJohn Edward Broadbent device + "/PCIeFunctions"}, 277dede6a98SJason M. Bills {"Name", "PCIe Function Collection"}, 278dede6a98SJason M. Bills {"Description", 279dede6a98SJason M. Bills "Collection of PCIe Functions for PCIe Device " + device}}; 280dede6a98SJason M. Bills 281b9d36b47SEd Tanous auto getPCIeDeviceCallback = 282*45ca1b86SEd Tanous [asyncResp, device]( 283*45ca1b86SEd Tanous const boost::system::error_code ec, 284*45ca1b86SEd Tanous const dbus::utility::DBusPropertiesMap& pcieDevProperties) { 2857e860f15SJohn Edward Broadbent if (ec) 2867e860f15SJohn Edward Broadbent { 2877e860f15SJohn Edward Broadbent BMCWEB_LOG_DEBUG 2887e860f15SJohn Edward Broadbent << "failed to get PCIe Device properties ec: " 2897e860f15SJohn Edward Broadbent << ec.value() << ": " << ec.message(); 290*45ca1b86SEd Tanous if (ec.value() == 291*45ca1b86SEd Tanous boost::system::linux_error::bad_request_descriptor) 2927e860f15SJohn Edward Broadbent { 293*45ca1b86SEd Tanous messages::resourceNotFound(asyncResp->res, 294*45ca1b86SEd Tanous "PCIeDevice", device); 2957e860f15SJohn Edward Broadbent } 2967e860f15SJohn Edward Broadbent else 2977e860f15SJohn Edward Broadbent { 2987e860f15SJohn Edward Broadbent messages::internalError(asyncResp->res); 2997e860f15SJohn Edward Broadbent } 3007e860f15SJohn Edward Broadbent return; 3017e860f15SJohn Edward Broadbent } 3027e860f15SJohn Edward Broadbent 3037e860f15SJohn Edward Broadbent nlohmann::json& pcieFunctionList = 3047e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Members"]; 3057e860f15SJohn Edward Broadbent pcieFunctionList = nlohmann::json::array(); 3067e860f15SJohn Edward Broadbent static constexpr const int maxPciFunctionNum = 8; 307*45ca1b86SEd Tanous for (int functionNum = 0; functionNum < maxPciFunctionNum; 308*45ca1b86SEd Tanous functionNum++) 3097e860f15SJohn Edward Broadbent { 310b9d36b47SEd Tanous // Check if this function exists by looking for a 311b9d36b47SEd Tanous // device ID 3127e860f15SJohn Edward Broadbent std::string devIDProperty = 3137e860f15SJohn Edward Broadbent "Function" + std::to_string(functionNum) + 3147e860f15SJohn Edward Broadbent "DeviceId"; 315b9d36b47SEd Tanous const std::string* property = nullptr; 316b9d36b47SEd Tanous for (const auto& propEntry : pcieDevProperties) 3177e860f15SJohn Edward Broadbent { 318b9d36b47SEd Tanous if (propEntry.first == devIDProperty) 319b9d36b47SEd Tanous { 320*45ca1b86SEd Tanous property = 321*45ca1b86SEd Tanous std::get_if<std::string>(&propEntry.second); 322b9d36b47SEd Tanous } 323b9d36b47SEd Tanous } 324b9d36b47SEd Tanous if (property == nullptr || !property->empty()) 325b9d36b47SEd Tanous { 326b9d36b47SEd Tanous return; 327b9d36b47SEd Tanous } 3287e860f15SJohn Edward Broadbent pcieFunctionList.push_back( 3297e860f15SJohn Edward Broadbent {{"@odata.id", 3307e860f15SJohn Edward Broadbent "/redfish/v1/Systems/system/PCIeDevices/" + 3317e860f15SJohn Edward Broadbent device + "/PCIeFunctions/" + 3327e860f15SJohn Edward Broadbent std::to_string(functionNum)}}); 3337e860f15SJohn Edward Broadbent } 334a818d15aSJiaqing Zhao asyncResp->res.jsonValue["Members@odata.count"] = 3357e860f15SJohn Edward Broadbent pcieFunctionList.size(); 3367e860f15SJohn Edward Broadbent }; 3377e860f15SJohn Edward Broadbent std::string escapedPath = std::string(pciePath) + "/" + device; 3387e860f15SJohn Edward Broadbent dbus::utility::escapePathForDbus(escapedPath); 3397e860f15SJohn Edward Broadbent crow::connections::systemBus->async_method_call( 3407e860f15SJohn Edward Broadbent std::move(getPCIeDeviceCallback), pcieService, escapedPath, 3417e860f15SJohn Edward Broadbent "org.freedesktop.DBus.Properties", "GetAll", 3427e860f15SJohn Edward Broadbent pcieDeviceInterface); 3437e860f15SJohn Edward Broadbent }); 3447e860f15SJohn Edward Broadbent } 3457e860f15SJohn Edward Broadbent 3467e860f15SJohn Edward Broadbent inline void requestRoutesSystemPCIeFunction(App& app) 3477e860f15SJohn Edward Broadbent { 3487e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 3497e860f15SJohn Edward Broadbent app, 3507e860f15SJohn Edward Broadbent "/redfish/v1/Systems/system/PCIeDevices/<str>/PCIeFunctions/<str>/") 351ed398213SEd Tanous .privileges(redfish::privileges::getPCIeFunction) 3527e860f15SJohn Edward Broadbent .methods( 353*45ca1b86SEd Tanous boost::beast::http::verb:: 354*45ca1b86SEd Tanous get)([&app](const crow::Request& req, 355*45ca1b86SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 3567e860f15SJohn Edward Broadbent const std::string& device, 3577e860f15SJohn Edward Broadbent const std::string& function) { 358*45ca1b86SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) 359*45ca1b86SEd Tanous { 360*45ca1b86SEd Tanous return; 361*45ca1b86SEd Tanous } 362168e20c1SEd Tanous auto getPCIeDeviceCallback = 363168e20c1SEd Tanous [asyncResp, device, function]( 3647e860f15SJohn Edward Broadbent const boost::system::error_code ec, 365b9d36b47SEd Tanous const dbus::utility::DBusPropertiesMap& pcieDevProperties) { 366dede6a98SJason M. Bills if (ec) 367dede6a98SJason M. Bills { 368dede6a98SJason M. Bills BMCWEB_LOG_DEBUG 369dede6a98SJason M. Bills << "failed to get PCIe Device properties ec: " 370dede6a98SJason M. Bills << ec.value() << ": " << ec.message(); 371dede6a98SJason M. Bills if (ec.value() == 372dede6a98SJason M. Bills boost::system::linux_error::bad_request_descriptor) 373dede6a98SJason M. Bills { 374168e20c1SEd Tanous messages::resourceNotFound(asyncResp->res, 375168e20c1SEd Tanous "PCIeDevice", device); 376dede6a98SJason M. Bills } 377dede6a98SJason M. Bills else 378dede6a98SJason M. Bills { 379dede6a98SJason M. Bills messages::internalError(asyncResp->res); 380dede6a98SJason M. Bills } 381dede6a98SJason M. Bills return; 382dede6a98SJason M. Bills } 383dede6a98SJason M. Bills 384f5c9f8bdSJason M. Bills // Check if this function exists by looking for a device ID 385b9d36b47SEd Tanous std::string functionName = "Function" + function; 386b9d36b47SEd Tanous std::string devIDProperty = functionName + "DeviceId"; 387b9d36b47SEd Tanous 388b9d36b47SEd Tanous const std::string* devIdProperty = nullptr; 389b9d36b47SEd Tanous for (const auto& property : pcieDevProperties) 390b9d36b47SEd Tanous { 391b9d36b47SEd Tanous if (property.first == devIDProperty) 392b9d36b47SEd Tanous { 393b9d36b47SEd Tanous devIdProperty = 394b9d36b47SEd Tanous std::get_if<std::string>(&property.second); 395b9d36b47SEd Tanous continue; 396b9d36b47SEd Tanous } 397b9d36b47SEd Tanous } 398b9d36b47SEd Tanous if (devIdProperty == nullptr || !devIdProperty->empty()) 399f5c9f8bdSJason M. Bills { 400168e20c1SEd Tanous messages::resourceNotFound(asyncResp->res, 401168e20c1SEd Tanous "PCIeFunction", function); 402f5c9f8bdSJason M. Bills return; 403f5c9f8bdSJason M. Bills } 404f5c9f8bdSJason M. Bills 405f5c9f8bdSJason M. Bills asyncResp->res.jsonValue = { 406f5c9f8bdSJason M. Bills {"@odata.type", "#PCIeFunction.v1_2_0.PCIeFunction"}, 407168e20c1SEd Tanous {"@odata.id", 408168e20c1SEd Tanous "/redfish/v1/Systems/system/PCIeDevices/" + device + 409168e20c1SEd Tanous "/PCIeFunctions/" + function}, 410f5c9f8bdSJason M. Bills {"Name", "PCIe Function"}, 411f5c9f8bdSJason M. Bills {"Id", function}, 412f5c9f8bdSJason M. Bills {"FunctionId", std::stoi(function)}, 413f5c9f8bdSJason M. Bills {"Links", 414f5c9f8bdSJason M. Bills {{"PCIeDevice", 415f5c9f8bdSJason M. Bills {{"@odata.id", 4167e860f15SJohn Edward Broadbent "/redfish/v1/Systems/system/PCIeDevices/" + 4177e860f15SJohn Edward Broadbent device}}}}}}; 418f5c9f8bdSJason M. Bills 419b9d36b47SEd Tanous for (const auto& property : pcieDevProperties) 420f5c9f8bdSJason M. Bills { 421b9d36b47SEd Tanous const std::string* strProperty = 422b9d36b47SEd Tanous std::get_if<std::string>(&property.second); 423b9d36b47SEd Tanous if (property.first == functionName + "DeviceId") 424f5c9f8bdSJason M. Bills { 425b9d36b47SEd Tanous asyncResp->res.jsonValue["DeviceId"] = *strProperty; 426f5c9f8bdSJason M. Bills } 427b9d36b47SEd Tanous if (property.first == functionName + "VendorId") 428f5c9f8bdSJason M. Bills { 429b9d36b47SEd Tanous asyncResp->res.jsonValue["VendorId"] = *strProperty; 430f5c9f8bdSJason M. Bills } 431b9d36b47SEd Tanous if (property.first == functionName + "FunctionType") 432f5c9f8bdSJason M. Bills { 433b9d36b47SEd Tanous asyncResp->res.jsonValue["FunctionType"] = 434b9d36b47SEd Tanous *strProperty; 435f5c9f8bdSJason M. Bills } 436b9d36b47SEd Tanous if (property.first == functionName + "DeviceClass") 437f5c9f8bdSJason M. Bills { 438b9d36b47SEd Tanous asyncResp->res.jsonValue["DeviceClass"] = 439b9d36b47SEd Tanous *strProperty; 440f5c9f8bdSJason M. Bills } 441b9d36b47SEd Tanous if (property.first == functionName + "ClassCode") 442f5c9f8bdSJason M. Bills { 443b9d36b47SEd Tanous asyncResp->res.jsonValue["ClassCode"] = 444b9d36b47SEd Tanous *strProperty; 445f5c9f8bdSJason M. Bills } 446b9d36b47SEd Tanous if (property.first == functionName + "RevisionId") 447f5c9f8bdSJason M. Bills { 448b9d36b47SEd Tanous asyncResp->res.jsonValue["RevisionId"] = 449b9d36b47SEd Tanous *strProperty; 450f5c9f8bdSJason M. Bills } 451b9d36b47SEd Tanous if (property.first == functionName + "SubsystemId") 452b9d36b47SEd Tanous { 453b9d36b47SEd Tanous asyncResp->res.jsonValue["SubsystemId"] = 454b9d36b47SEd Tanous *strProperty; 455b9d36b47SEd Tanous } 456b9d36b47SEd Tanous if (property.first == 457b9d36b47SEd Tanous functionName + "SubsystemVendorId") 458f5c9f8bdSJason M. Bills { 459168e20c1SEd Tanous asyncResp->res.jsonValue["SubsystemVendorId"] = 460b9d36b47SEd Tanous *strProperty; 461b9d36b47SEd Tanous } 462f5c9f8bdSJason M. Bills } 463f5c9f8bdSJason M. Bills }; 464f5c9f8bdSJason M. Bills std::string escapedPath = std::string(pciePath) + "/" + device; 465f5c9f8bdSJason M. Bills dbus::utility::escapePathForDbus(escapedPath); 466f5c9f8bdSJason M. Bills crow::connections::systemBus->async_method_call( 467f5c9f8bdSJason M. Bills std::move(getPCIeDeviceCallback), pcieService, escapedPath, 4687e860f15SJohn Edward Broadbent "org.freedesktop.DBus.Properties", "GetAll", 4697e860f15SJohn Edward Broadbent pcieDeviceInterface); 4707e860f15SJohn Edward Broadbent }); 471f5c9f8bdSJason M. Bills } 472f5c9f8bdSJason M. Bills 473f5c9f8bdSJason M. Bills } // namespace redfish 474