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 19*7a1dbc48SGeorge Liu #include "dbus_utility.hpp" 200ec8b83dSEd Tanous #include "generated/enums/pcie_device.hpp" 210ec8b83dSEd Tanous 227e860f15SJohn Edward Broadbent #include <app.hpp> 23f5c9f8bdSJason M. Bills #include <boost/system/linux_error.hpp> 24168e20c1SEd Tanous #include <dbus_utility.hpp> 2545ca1b86SEd Tanous #include <query.hpp> 26ed398213SEd Tanous #include <registries/privilege_registry.hpp> 27d1bde9e5SKrzysztof Grobelny #include <sdbusplus/asio/property.hpp> 28d1bde9e5SKrzysztof Grobelny #include <sdbusplus/unpack_properties.hpp> 29d1bde9e5SKrzysztof Grobelny #include <utils/dbus_utils.hpp> 30f5c9f8bdSJason M. Bills 31f5c9f8bdSJason M. Bills namespace redfish 32f5c9f8bdSJason M. Bills { 33f5c9f8bdSJason M. Bills 34f5c9f8bdSJason M. Bills static constexpr char const* pcieService = "xyz.openbmc_project.PCIe"; 35f5c9f8bdSJason M. Bills static constexpr char const* pciePath = "/xyz/openbmc_project/PCIe"; 36f5c9f8bdSJason M. Bills static constexpr char const* pcieDeviceInterface = 37f5c9f8bdSJason M. Bills "xyz.openbmc_project.PCIe.Device"; 38f5c9f8bdSJason M. Bills 39b5a76932SEd Tanous static inline void 408d1b46d7Szhanghch05 getPCIeDeviceList(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 41adbe192aSJason M. Bills const std::string& name) 42f5c9f8bdSJason M. Bills { 43*7a1dbc48SGeorge Liu dbus::utility::getSubTreePaths( 44*7a1dbc48SGeorge Liu pciePath, 1, {}, 45*7a1dbc48SGeorge Liu [asyncResp, name](const boost::system::error_code& ec, 46b9d36b47SEd Tanous const dbus::utility::MapperGetSubTreePathsResponse& 47b9d36b47SEd Tanous pcieDevicePaths) { 48f5c9f8bdSJason M. Bills if (ec) 49f5c9f8bdSJason M. Bills { 50a2730f01SAndrew Geissler BMCWEB_LOG_DEBUG << "no PCIe device paths found ec: " 51f5c9f8bdSJason M. Bills << ec.message(); 52a2730f01SAndrew Geissler // Not an error, system just doesn't have PCIe info 53f5c9f8bdSJason M. Bills return; 54f5c9f8bdSJason M. Bills } 55adbe192aSJason M. Bills nlohmann::json& pcieDeviceList = asyncResp->res.jsonValue[name]; 56f5c9f8bdSJason M. Bills pcieDeviceList = nlohmann::json::array(); 57f5c9f8bdSJason M. Bills for (const std::string& pcieDevicePath : pcieDevicePaths) 58f5c9f8bdSJason M. Bills { 593174e4dfSEd Tanous size_t devStart = pcieDevicePath.rfind('/'); 60f5c9f8bdSJason M. Bills if (devStart == std::string::npos) 61f5c9f8bdSJason M. Bills { 62f5c9f8bdSJason M. Bills continue; 63f5c9f8bdSJason M. Bills } 64f5c9f8bdSJason M. Bills 65f5c9f8bdSJason M. Bills std::string devName = pcieDevicePath.substr(devStart + 1); 66f5c9f8bdSJason M. Bills if (devName.empty()) 67f5c9f8bdSJason M. Bills { 68f5c9f8bdSJason M. Bills continue; 69f5c9f8bdSJason M. Bills } 701476687dSEd Tanous nlohmann::json::object_t pcieDevice; 711476687dSEd Tanous pcieDevice["@odata.id"] = 721476687dSEd Tanous "/redfish/v1/Systems/system/PCIeDevices/" + devName; 731476687dSEd Tanous pcieDeviceList.push_back(std::move(pcieDevice)); 74f5c9f8bdSJason M. Bills } 75002d39b4SEd Tanous asyncResp->res.jsonValue[name + "@odata.count"] = pcieDeviceList.size(); 76*7a1dbc48SGeorge Liu }); 77f5c9f8bdSJason M. Bills } 78f5c9f8bdSJason M. Bills 797e860f15SJohn Edward Broadbent inline void requestRoutesSystemPCIeDeviceCollection(App& app) 80adbe192aSJason M. Bills { 81adbe192aSJason M. Bills /** 82adbe192aSJason M. Bills * Functions triggers appropriate requests on DBus 83adbe192aSJason M. Bills */ 8422d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/PCIeDevices/") 85ed398213SEd Tanous .privileges(redfish::privileges::getPCIeDeviceCollection) 867e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 8745ca1b86SEd Tanous [&app](const crow::Request& req, 8822d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 8922d268cbSEd Tanous const std::string& systemName) { 903ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 91adbe192aSJason M. Bills { 9245ca1b86SEd Tanous return; 9345ca1b86SEd Tanous } 9422d268cbSEd Tanous if (systemName != "system") 9522d268cbSEd Tanous { 9622d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 9722d268cbSEd Tanous systemName); 9822d268cbSEd Tanous return; 9922d268cbSEd Tanous } 1001476687dSEd Tanous 1011476687dSEd Tanous asyncResp->res.jsonValue["@odata.type"] = 1021476687dSEd Tanous "#PCIeDeviceCollection.PCIeDeviceCollection"; 1031476687dSEd Tanous asyncResp->res.jsonValue["@odata.id"] = 1041476687dSEd Tanous "/redfish/v1/Systems/system/PCIeDevices"; 1051476687dSEd Tanous asyncResp->res.jsonValue["Name"] = "PCIe Device Collection"; 106002d39b4SEd Tanous asyncResp->res.jsonValue["Description"] = "Collection of PCIe Devices"; 1071476687dSEd Tanous asyncResp->res.jsonValue["Members"] = nlohmann::json::array(); 1081476687dSEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = 0; 109adbe192aSJason M. Bills getPCIeDeviceList(asyncResp, "Members"); 1107e860f15SJohn Edward Broadbent }); 111f5c9f8bdSJason M. Bills } 112f5c9f8bdSJason M. Bills 1130ec8b83dSEd Tanous inline std::optional<pcie_device::PCIeTypes> 11462cd45afSSpencer Ku redfishPcieGenerationFromDbus(const std::string& generationInUse) 11562cd45afSSpencer Ku { 11662cd45afSSpencer Ku if (generationInUse == 11762cd45afSSpencer Ku "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen1") 11862cd45afSSpencer Ku { 1190ec8b83dSEd Tanous return pcie_device::PCIeTypes::Gen1; 12062cd45afSSpencer Ku } 12162cd45afSSpencer Ku if (generationInUse == 12262cd45afSSpencer Ku "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen2") 12362cd45afSSpencer Ku { 1240ec8b83dSEd Tanous return pcie_device::PCIeTypes::Gen2; 12562cd45afSSpencer Ku } 12662cd45afSSpencer Ku if (generationInUse == 12762cd45afSSpencer Ku "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen3") 12862cd45afSSpencer Ku { 1290ec8b83dSEd Tanous return pcie_device::PCIeTypes::Gen3; 13062cd45afSSpencer Ku } 13162cd45afSSpencer Ku if (generationInUse == 13262cd45afSSpencer Ku "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen4") 13362cd45afSSpencer Ku { 1340ec8b83dSEd Tanous return pcie_device::PCIeTypes::Gen4; 13562cd45afSSpencer Ku } 13662cd45afSSpencer Ku if (generationInUse == 13762cd45afSSpencer Ku "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen5") 13862cd45afSSpencer Ku { 1390ec8b83dSEd Tanous return pcie_device::PCIeTypes::Gen5; 14062cd45afSSpencer Ku } 141e825cbc8SEd Tanous if (generationInUse.empty() || 142e825cbc8SEd Tanous generationInUse == 14362cd45afSSpencer Ku "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Unknown") 14462cd45afSSpencer Ku { 1450ec8b83dSEd Tanous return pcie_device::PCIeTypes::Invalid; 14662cd45afSSpencer Ku } 14762cd45afSSpencer Ku 14862cd45afSSpencer Ku // The value is not unknown or Gen1-5, need return an internal error. 14962cd45afSSpencer Ku return std::nullopt; 15062cd45afSSpencer Ku } 15162cd45afSSpencer Ku 1527e860f15SJohn Edward Broadbent inline void requestRoutesSystemPCIeDevice(App& app) 153f5c9f8bdSJason M. Bills { 15422d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/PCIeDevices/<str>/") 155ed398213SEd Tanous .privileges(redfish::privileges::getPCIeDevice) 156002d39b4SEd Tanous .methods(boost::beast::http::verb::get)( 157002d39b4SEd Tanous [&app](const crow::Request& req, 1587e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 15922d268cbSEd Tanous const std::string& systemName, const std::string& device) { 1603ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 1617e860f15SJohn Edward Broadbent { 16245ca1b86SEd Tanous return; 16345ca1b86SEd Tanous } 16422d268cbSEd Tanous if (systemName != "system") 16522d268cbSEd Tanous { 16622d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 16722d268cbSEd Tanous systemName); 16822d268cbSEd Tanous return; 16922d268cbSEd Tanous } 17022d268cbSEd Tanous 171168e20c1SEd Tanous auto getPCIeDeviceCallback = 17245ca1b86SEd Tanous [asyncResp, device]( 17345ca1b86SEd Tanous const boost::system::error_code ec, 17445ca1b86SEd Tanous const dbus::utility::DBusPropertiesMap& pcieDevProperties) { 175f5c9f8bdSJason M. Bills if (ec) 176f5c9f8bdSJason M. Bills { 177f5c9f8bdSJason M. Bills BMCWEB_LOG_DEBUG 178002d39b4SEd Tanous << "failed to get PCIe Device properties ec: " << ec.value() 179002d39b4SEd Tanous << ": " << ec.message(); 18045ca1b86SEd Tanous if (ec.value() == 18145ca1b86SEd Tanous boost::system::linux_error::bad_request_descriptor) 182f5c9f8bdSJason M. Bills { 183002d39b4SEd Tanous messages::resourceNotFound(asyncResp->res, "PCIeDevice", 184002d39b4SEd Tanous device); 185f5c9f8bdSJason M. Bills } 186f5c9f8bdSJason M. Bills else 187f5c9f8bdSJason M. Bills { 188f5c9f8bdSJason M. Bills messages::internalError(asyncResp->res); 189f5c9f8bdSJason M. Bills } 190f5c9f8bdSJason M. Bills return; 191f5c9f8bdSJason M. Bills } 192f5c9f8bdSJason M. Bills 193d1bde9e5SKrzysztof Grobelny const std::string* manufacturer = nullptr; 194d1bde9e5SKrzysztof Grobelny const std::string* deviceType = nullptr; 195d1bde9e5SKrzysztof Grobelny const std::string* generationInUse = nullptr; 196d1bde9e5SKrzysztof Grobelny 197d1bde9e5SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 198d1bde9e5SKrzysztof Grobelny dbus_utils::UnpackErrorPrinter(), pcieDevProperties, 199d1bde9e5SKrzysztof Grobelny "Manufacturer", manufacturer, "DeviceType", deviceType, 200d1bde9e5SKrzysztof Grobelny "GenerationInUse", generationInUse); 201d1bde9e5SKrzysztof Grobelny 202d1bde9e5SKrzysztof Grobelny if (!success) 203d1bde9e5SKrzysztof Grobelny { 204d1bde9e5SKrzysztof Grobelny messages::internalError(asyncResp->res); 205d1bde9e5SKrzysztof Grobelny return; 206d1bde9e5SKrzysztof Grobelny } 207d1bde9e5SKrzysztof Grobelny 208d1bde9e5SKrzysztof Grobelny if (generationInUse != nullptr) 209d1bde9e5SKrzysztof Grobelny { 2100ec8b83dSEd Tanous std::optional<pcie_device::PCIeTypes> redfishGenerationInUse = 211d1bde9e5SKrzysztof Grobelny redfishPcieGenerationFromDbus(*generationInUse); 212d1bde9e5SKrzysztof Grobelny if (!redfishGenerationInUse) 213d1bde9e5SKrzysztof Grobelny { 214d1bde9e5SKrzysztof Grobelny messages::internalError(asyncResp->res); 215d1bde9e5SKrzysztof Grobelny return; 216d1bde9e5SKrzysztof Grobelny } 2170ec8b83dSEd Tanous if (*redfishGenerationInUse != pcie_device::PCIeTypes::Invalid) 218d1bde9e5SKrzysztof Grobelny { 219d1bde9e5SKrzysztof Grobelny asyncResp->res.jsonValue["PCIeInterface"]["PCIeType"] = 220d1bde9e5SKrzysztof Grobelny *redfishGenerationInUse; 221d1bde9e5SKrzysztof Grobelny } 222a9f68bb5STony Lee } 223d1bde9e5SKrzysztof Grobelny 224d1bde9e5SKrzysztof Grobelny if (manufacturer != nullptr) 225d1bde9e5SKrzysztof Grobelny { 226d1bde9e5SKrzysztof Grobelny asyncResp->res.jsonValue["Manufacturer"] = *manufacturer; 227d1bde9e5SKrzysztof Grobelny } 228d1bde9e5SKrzysztof Grobelny 229d1bde9e5SKrzysztof Grobelny if (deviceType != nullptr) 230d1bde9e5SKrzysztof Grobelny { 231d1bde9e5SKrzysztof Grobelny asyncResp->res.jsonValue["DeviceType"] = *deviceType; 232d1bde9e5SKrzysztof Grobelny } 233d1bde9e5SKrzysztof Grobelny 2341476687dSEd Tanous asyncResp->res.jsonValue["@odata.type"] = 2351476687dSEd Tanous "#PCIeDevice.v1_4_0.PCIeDevice"; 2361476687dSEd Tanous asyncResp->res.jsonValue["@odata.id"] = 2371476687dSEd Tanous "/redfish/v1/Systems/system/PCIeDevices/" + device; 2381476687dSEd Tanous asyncResp->res.jsonValue["Name"] = "PCIe Device"; 2391476687dSEd Tanous asyncResp->res.jsonValue["Id"] = device; 2401476687dSEd Tanous 2411476687dSEd Tanous asyncResp->res.jsonValue["PCIeFunctions"]["@odata.id"] = 24245ca1b86SEd Tanous "/redfish/v1/Systems/system/PCIeDevices/" + device + 2431476687dSEd Tanous "/PCIeFunctions"; 244dede6a98SJason M. Bills }; 245dede6a98SJason M. Bills std::string escapedPath = std::string(pciePath) + "/" + device; 246dede6a98SJason M. Bills dbus::utility::escapePathForDbus(escapedPath); 247d1bde9e5SKrzysztof Grobelny sdbusplus::asio::getAllProperties( 248d1bde9e5SKrzysztof Grobelny *crow::connections::systemBus, pcieService, escapedPath, 249d1bde9e5SKrzysztof Grobelny pcieDeviceInterface, std::move(getPCIeDeviceCallback)); 2507e860f15SJohn Edward Broadbent }); 251dede6a98SJason M. Bills } 252dede6a98SJason M. Bills 2537e860f15SJohn Edward Broadbent inline void requestRoutesSystemPCIeFunctionCollection(App& app) 2547e860f15SJohn Edward Broadbent { 255dede6a98SJason M. Bills /** 256dede6a98SJason M. Bills * Functions triggers appropriate requests on DBus 257dede6a98SJason M. Bills */ 2587e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 2597e860f15SJohn Edward Broadbent "/redfish/v1/Systems/system/PCIeDevices/<str>/PCIeFunctions/") 260ed398213SEd Tanous .privileges(redfish::privileges::getPCIeFunctionCollection) 261002d39b4SEd Tanous .methods(boost::beast::http::verb::get)( 262002d39b4SEd Tanous [&app](const crow::Request& req, 2637e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 26445ca1b86SEd Tanous const std::string& device) { 2653ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 266dede6a98SJason M. Bills { 26745ca1b86SEd Tanous return; 26845ca1b86SEd Tanous } 2691476687dSEd Tanous 2701476687dSEd Tanous asyncResp->res.jsonValue["@odata.type"] = 2711476687dSEd Tanous "#PCIeFunctionCollection.PCIeFunctionCollection"; 2721476687dSEd Tanous asyncResp->res.jsonValue["@odata.id"] = 2731476687dSEd Tanous "/redfish/v1/Systems/system/PCIeDevices/" + device + 2741476687dSEd Tanous "/PCIeFunctions"; 2751476687dSEd Tanous asyncResp->res.jsonValue["Name"] = "PCIe Function Collection"; 2761476687dSEd Tanous asyncResp->res.jsonValue["Description"] = 2771476687dSEd Tanous "Collection of PCIe Functions for PCIe Device " + device; 278dede6a98SJason M. Bills 279b9d36b47SEd Tanous auto getPCIeDeviceCallback = 28045ca1b86SEd Tanous [asyncResp, device]( 28145ca1b86SEd Tanous const boost::system::error_code ec, 28245ca1b86SEd Tanous const dbus::utility::DBusPropertiesMap& pcieDevProperties) { 2837e860f15SJohn Edward Broadbent if (ec) 2847e860f15SJohn Edward Broadbent { 2857e860f15SJohn Edward Broadbent BMCWEB_LOG_DEBUG 286002d39b4SEd Tanous << "failed to get PCIe Device properties ec: " << ec.value() 287002d39b4SEd Tanous << ": " << ec.message(); 28845ca1b86SEd Tanous if (ec.value() == 28945ca1b86SEd Tanous boost::system::linux_error::bad_request_descriptor) 2907e860f15SJohn Edward Broadbent { 291002d39b4SEd Tanous messages::resourceNotFound(asyncResp->res, "PCIeDevice", 292002d39b4SEd Tanous device); 2937e860f15SJohn Edward Broadbent } 2947e860f15SJohn Edward Broadbent else 2957e860f15SJohn Edward Broadbent { 2967e860f15SJohn Edward Broadbent messages::internalError(asyncResp->res); 2977e860f15SJohn Edward Broadbent } 2987e860f15SJohn Edward Broadbent return; 2997e860f15SJohn Edward Broadbent } 3007e860f15SJohn Edward Broadbent 3017e860f15SJohn Edward Broadbent nlohmann::json& pcieFunctionList = 3027e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Members"]; 3037e860f15SJohn Edward Broadbent pcieFunctionList = nlohmann::json::array(); 3047e860f15SJohn Edward Broadbent static constexpr const int maxPciFunctionNum = 8; 30545ca1b86SEd Tanous for (int functionNum = 0; functionNum < maxPciFunctionNum; 30645ca1b86SEd Tanous functionNum++) 3077e860f15SJohn Edward Broadbent { 308b9d36b47SEd Tanous // Check if this function exists by looking for a 309b9d36b47SEd Tanous // device ID 3107e860f15SJohn Edward Broadbent std::string devIDProperty = 311002d39b4SEd Tanous "Function" + std::to_string(functionNum) + "DeviceId"; 312b9d36b47SEd Tanous const std::string* property = nullptr; 313b9d36b47SEd Tanous for (const auto& propEntry : pcieDevProperties) 3147e860f15SJohn Edward Broadbent { 315b9d36b47SEd Tanous if (propEntry.first == devIDProperty) 316b9d36b47SEd Tanous { 317002d39b4SEd Tanous property = std::get_if<std::string>(&propEntry.second); 318b9d36b47SEd Tanous } 319b9d36b47SEd Tanous } 320fb0ecc3eSNan Zhou if (property == nullptr || property->empty()) 321b9d36b47SEd Tanous { 322e28ce0e6SNan Zhou continue; 323b9d36b47SEd Tanous } 3241476687dSEd Tanous nlohmann::json::object_t pcieFunction; 3251476687dSEd Tanous pcieFunction["@odata.id"] = 3261476687dSEd Tanous "/redfish/v1/Systems/system/PCIeDevices/" + device + 3271476687dSEd Tanous "/PCIeFunctions/" + std::to_string(functionNum); 3281476687dSEd Tanous pcieFunctionList.push_back(std::move(pcieFunction)); 3297e860f15SJohn Edward Broadbent } 330a818d15aSJiaqing Zhao asyncResp->res.jsonValue["Members@odata.count"] = 3317e860f15SJohn Edward Broadbent pcieFunctionList.size(); 3327e860f15SJohn Edward Broadbent }; 3337e860f15SJohn Edward Broadbent std::string escapedPath = std::string(pciePath) + "/" + device; 3347e860f15SJohn Edward Broadbent dbus::utility::escapePathForDbus(escapedPath); 335d1bde9e5SKrzysztof Grobelny sdbusplus::asio::getAllProperties( 336d1bde9e5SKrzysztof Grobelny *crow::connections::systemBus, pcieService, escapedPath, 337d1bde9e5SKrzysztof Grobelny pcieDeviceInterface, std::move(getPCIeDeviceCallback)); 3387e860f15SJohn Edward Broadbent }); 3397e860f15SJohn Edward Broadbent } 3407e860f15SJohn Edward Broadbent 3417e860f15SJohn Edward Broadbent inline void requestRoutesSystemPCIeFunction(App& app) 3427e860f15SJohn Edward Broadbent { 3437e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 3447e860f15SJohn Edward Broadbent app, 3457e860f15SJohn Edward Broadbent "/redfish/v1/Systems/system/PCIeDevices/<str>/PCIeFunctions/<str>/") 346ed398213SEd Tanous .privileges(redfish::privileges::getPCIeFunction) 347002d39b4SEd Tanous .methods(boost::beast::http::verb::get)( 348002d39b4SEd Tanous [&app](const crow::Request& req, 34945ca1b86SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 350002d39b4SEd Tanous const std::string& device, const std::string& function) { 3513ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 35245ca1b86SEd Tanous { 35345ca1b86SEd Tanous return; 35445ca1b86SEd Tanous } 355168e20c1SEd Tanous auto getPCIeDeviceCallback = 356168e20c1SEd Tanous [asyncResp, device, function]( 3577e860f15SJohn Edward Broadbent const boost::system::error_code ec, 358b9d36b47SEd Tanous const dbus::utility::DBusPropertiesMap& pcieDevProperties) { 359dede6a98SJason M. Bills if (ec) 360dede6a98SJason M. Bills { 361dede6a98SJason M. Bills BMCWEB_LOG_DEBUG 362002d39b4SEd Tanous << "failed to get PCIe Device properties ec: " << ec.value() 363002d39b4SEd Tanous << ": " << ec.message(); 364dede6a98SJason M. Bills if (ec.value() == 365dede6a98SJason M. Bills boost::system::linux_error::bad_request_descriptor) 366dede6a98SJason M. Bills { 367002d39b4SEd Tanous messages::resourceNotFound(asyncResp->res, "PCIeDevice", 368002d39b4SEd Tanous device); 369dede6a98SJason M. Bills } 370dede6a98SJason M. Bills else 371dede6a98SJason M. Bills { 372dede6a98SJason M. Bills messages::internalError(asyncResp->res); 373dede6a98SJason M. Bills } 374dede6a98SJason M. Bills return; 375dede6a98SJason M. Bills } 376dede6a98SJason M. Bills 3771476687dSEd Tanous // Check if this function exists by looking for a device 3781476687dSEd Tanous // ID 379b9d36b47SEd Tanous std::string functionName = "Function" + function; 380b9d36b47SEd Tanous std::string devIDProperty = functionName + "DeviceId"; 381b9d36b47SEd Tanous 382b9d36b47SEd Tanous const std::string* devIdProperty = nullptr; 383b9d36b47SEd Tanous for (const auto& property : pcieDevProperties) 384b9d36b47SEd Tanous { 385b9d36b47SEd Tanous if (property.first == devIDProperty) 386b9d36b47SEd Tanous { 387002d39b4SEd Tanous devIdProperty = std::get_if<std::string>(&property.second); 388b9d36b47SEd Tanous continue; 389b9d36b47SEd Tanous } 390b9d36b47SEd Tanous } 391973c1355STony Lee if (devIdProperty == nullptr || devIdProperty->empty()) 392f5c9f8bdSJason M. Bills { 393002d39b4SEd Tanous messages::resourceNotFound(asyncResp->res, "PCIeFunction", 394002d39b4SEd Tanous function); 395f5c9f8bdSJason M. Bills return; 396f5c9f8bdSJason M. Bills } 397f5c9f8bdSJason M. Bills 3981476687dSEd Tanous asyncResp->res.jsonValue["@odata.type"] = 3991476687dSEd Tanous "#PCIeFunction.v1_2_0.PCIeFunction"; 4001476687dSEd Tanous asyncResp->res.jsonValue["@odata.id"] = 401168e20c1SEd Tanous "/redfish/v1/Systems/system/PCIeDevices/" + device + 4021476687dSEd Tanous "/PCIeFunctions/" + function; 4031476687dSEd Tanous asyncResp->res.jsonValue["Name"] = "PCIe Function"; 4041476687dSEd Tanous asyncResp->res.jsonValue["Id"] = function; 405002d39b4SEd Tanous asyncResp->res.jsonValue["FunctionId"] = std::stoi(function); 406002d39b4SEd Tanous asyncResp->res.jsonValue["Links"]["PCIeDevice"]["@odata.id"] = 4071476687dSEd Tanous "/redfish/v1/Systems/system/PCIeDevices/" + device; 408f5c9f8bdSJason M. Bills 409b9d36b47SEd Tanous for (const auto& property : pcieDevProperties) 410f5c9f8bdSJason M. Bills { 411b9d36b47SEd Tanous const std::string* strProperty = 412b9d36b47SEd Tanous std::get_if<std::string>(&property.second); 413b9d36b47SEd Tanous if (property.first == functionName + "DeviceId") 414f5c9f8bdSJason M. Bills { 415b9d36b47SEd Tanous asyncResp->res.jsonValue["DeviceId"] = *strProperty; 416f5c9f8bdSJason M. Bills } 417b9d36b47SEd Tanous if (property.first == functionName + "VendorId") 418f5c9f8bdSJason M. Bills { 419b9d36b47SEd Tanous asyncResp->res.jsonValue["VendorId"] = *strProperty; 420f5c9f8bdSJason M. Bills } 421b9d36b47SEd Tanous if (property.first == functionName + "FunctionType") 422f5c9f8bdSJason M. Bills { 423002d39b4SEd Tanous asyncResp->res.jsonValue["FunctionType"] = *strProperty; 424f5c9f8bdSJason M. Bills } 425b9d36b47SEd Tanous if (property.first == functionName + "DeviceClass") 426f5c9f8bdSJason M. Bills { 427002d39b4SEd Tanous asyncResp->res.jsonValue["DeviceClass"] = *strProperty; 428f5c9f8bdSJason M. Bills } 429b9d36b47SEd Tanous if (property.first == functionName + "ClassCode") 430f5c9f8bdSJason M. Bills { 431002d39b4SEd Tanous asyncResp->res.jsonValue["ClassCode"] = *strProperty; 432f5c9f8bdSJason M. Bills } 433b9d36b47SEd Tanous if (property.first == functionName + "RevisionId") 434f5c9f8bdSJason M. Bills { 435002d39b4SEd Tanous asyncResp->res.jsonValue["RevisionId"] = *strProperty; 436f5c9f8bdSJason M. Bills } 437b9d36b47SEd Tanous if (property.first == functionName + "SubsystemId") 438b9d36b47SEd Tanous { 439002d39b4SEd Tanous asyncResp->res.jsonValue["SubsystemId"] = *strProperty; 440b9d36b47SEd Tanous } 441002d39b4SEd Tanous if (property.first == functionName + "SubsystemVendorId") 442f5c9f8bdSJason M. Bills { 443168e20c1SEd Tanous asyncResp->res.jsonValue["SubsystemVendorId"] = 444b9d36b47SEd Tanous *strProperty; 445b9d36b47SEd Tanous } 446f5c9f8bdSJason M. Bills } 447f5c9f8bdSJason M. Bills }; 448f5c9f8bdSJason M. Bills std::string escapedPath = std::string(pciePath) + "/" + device; 449f5c9f8bdSJason M. Bills dbus::utility::escapePathForDbus(escapedPath); 450d1bde9e5SKrzysztof Grobelny sdbusplus::asio::getAllProperties( 451d1bde9e5SKrzysztof Grobelny *crow::connections::systemBus, pcieService, escapedPath, 452d1bde9e5SKrzysztof Grobelny pcieDeviceInterface, std::move(getPCIeDeviceCallback)); 4537e860f15SJohn Edward Broadbent }); 454f5c9f8bdSJason M. Bills } 455f5c9f8bdSJason M. Bills 456f5c9f8bdSJason M. Bills } // namespace redfish 457