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*0ec8b83dSEd Tanous #include "generated/enums/pcie_device.hpp" 20*0ec8b83dSEd Tanous 217e860f15SJohn Edward Broadbent #include <app.hpp> 22f5c9f8bdSJason M. Bills #include <boost/system/linux_error.hpp> 23168e20c1SEd Tanous #include <dbus_utility.hpp> 2445ca1b86SEd Tanous #include <query.hpp> 25ed398213SEd Tanous #include <registries/privilege_registry.hpp> 26d1bde9e5SKrzysztof Grobelny #include <sdbusplus/asio/property.hpp> 27d1bde9e5SKrzysztof Grobelny #include <sdbusplus/unpack_properties.hpp> 28d1bde9e5SKrzysztof Grobelny #include <utils/dbus_utils.hpp> 29f5c9f8bdSJason M. Bills 30f5c9f8bdSJason M. Bills namespace redfish 31f5c9f8bdSJason M. Bills { 32f5c9f8bdSJason M. Bills 33f5c9f8bdSJason M. Bills static constexpr char const* pcieService = "xyz.openbmc_project.PCIe"; 34f5c9f8bdSJason M. Bills static constexpr char const* pciePath = "/xyz/openbmc_project/PCIe"; 35f5c9f8bdSJason M. Bills static constexpr char const* pcieDeviceInterface = 36f5c9f8bdSJason M. Bills "xyz.openbmc_project.PCIe.Device"; 37f5c9f8bdSJason M. Bills 38b5a76932SEd Tanous static inline void 398d1b46d7Szhanghch05 getPCIeDeviceList(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 40adbe192aSJason M. Bills const std::string& name) 41f5c9f8bdSJason M. Bills { 42b9d36b47SEd Tanous auto getPCIeMapCallback = 43b9d36b47SEd Tanous [asyncResp, name](const boost::system::error_code ec, 44b9d36b47SEd Tanous const dbus::utility::MapperGetSubTreePathsResponse& 45b9d36b47SEd Tanous pcieDevicePaths) { 46f5c9f8bdSJason M. Bills if (ec) 47f5c9f8bdSJason M. Bills { 48a2730f01SAndrew Geissler BMCWEB_LOG_DEBUG << "no PCIe device paths found ec: " 49f5c9f8bdSJason M. Bills << ec.message(); 50a2730f01SAndrew Geissler // Not an error, system just doesn't have PCIe info 51f5c9f8bdSJason M. Bills return; 52f5c9f8bdSJason M. Bills } 53adbe192aSJason M. Bills nlohmann::json& pcieDeviceList = asyncResp->res.jsonValue[name]; 54f5c9f8bdSJason M. Bills pcieDeviceList = nlohmann::json::array(); 55f5c9f8bdSJason M. Bills for (const std::string& pcieDevicePath : pcieDevicePaths) 56f5c9f8bdSJason M. Bills { 573174e4dfSEd Tanous size_t devStart = pcieDevicePath.rfind('/'); 58f5c9f8bdSJason M. Bills if (devStart == std::string::npos) 59f5c9f8bdSJason M. Bills { 60f5c9f8bdSJason M. Bills continue; 61f5c9f8bdSJason M. Bills } 62f5c9f8bdSJason M. Bills 63f5c9f8bdSJason M. Bills std::string devName = pcieDevicePath.substr(devStart + 1); 64f5c9f8bdSJason M. Bills if (devName.empty()) 65f5c9f8bdSJason M. Bills { 66f5c9f8bdSJason M. Bills continue; 67f5c9f8bdSJason M. Bills } 681476687dSEd Tanous nlohmann::json::object_t pcieDevice; 691476687dSEd Tanous pcieDevice["@odata.id"] = 701476687dSEd Tanous "/redfish/v1/Systems/system/PCIeDevices/" + devName; 711476687dSEd Tanous pcieDeviceList.push_back(std::move(pcieDevice)); 72f5c9f8bdSJason M. Bills } 73002d39b4SEd Tanous asyncResp->res.jsonValue[name + "@odata.count"] = pcieDeviceList.size(); 74f5c9f8bdSJason M. Bills }; 75f5c9f8bdSJason M. Bills crow::connections::systemBus->async_method_call( 76f5c9f8bdSJason M. Bills std::move(getPCIeMapCallback), "xyz.openbmc_project.ObjectMapper", 77f5c9f8bdSJason M. Bills "/xyz/openbmc_project/object_mapper", 78f5c9f8bdSJason M. Bills "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", 79f5c9f8bdSJason M. Bills std::string(pciePath) + "/", 1, std::array<std::string, 0>()); 80f5c9f8bdSJason M. Bills } 81f5c9f8bdSJason M. Bills 827e860f15SJohn Edward Broadbent inline void requestRoutesSystemPCIeDeviceCollection(App& app) 83adbe192aSJason M. Bills { 84adbe192aSJason M. Bills /** 85adbe192aSJason M. Bills * Functions triggers appropriate requests on DBus 86adbe192aSJason M. Bills */ 8722d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/PCIeDevices/") 88ed398213SEd Tanous .privileges(redfish::privileges::getPCIeDeviceCollection) 897e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 9045ca1b86SEd Tanous [&app](const crow::Request& req, 9122d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 9222d268cbSEd Tanous const std::string& systemName) { 933ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 94adbe192aSJason M. Bills { 9545ca1b86SEd Tanous return; 9645ca1b86SEd Tanous } 9722d268cbSEd Tanous if (systemName != "system") 9822d268cbSEd Tanous { 9922d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 10022d268cbSEd Tanous systemName); 10122d268cbSEd Tanous return; 10222d268cbSEd Tanous } 1031476687dSEd Tanous 1041476687dSEd Tanous asyncResp->res.jsonValue["@odata.type"] = 1051476687dSEd Tanous "#PCIeDeviceCollection.PCIeDeviceCollection"; 1061476687dSEd Tanous asyncResp->res.jsonValue["@odata.id"] = 1071476687dSEd Tanous "/redfish/v1/Systems/system/PCIeDevices"; 1081476687dSEd Tanous asyncResp->res.jsonValue["Name"] = "PCIe Device Collection"; 109002d39b4SEd Tanous asyncResp->res.jsonValue["Description"] = "Collection of PCIe Devices"; 1101476687dSEd Tanous asyncResp->res.jsonValue["Members"] = nlohmann::json::array(); 1111476687dSEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = 0; 112adbe192aSJason M. Bills getPCIeDeviceList(asyncResp, "Members"); 1137e860f15SJohn Edward Broadbent }); 114f5c9f8bdSJason M. Bills } 115f5c9f8bdSJason M. Bills 116*0ec8b83dSEd Tanous inline std::optional<pcie_device::PCIeTypes> 11762cd45afSSpencer Ku redfishPcieGenerationFromDbus(const std::string& generationInUse) 11862cd45afSSpencer Ku { 11962cd45afSSpencer Ku if (generationInUse == 12062cd45afSSpencer Ku "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen1") 12162cd45afSSpencer Ku { 122*0ec8b83dSEd Tanous return pcie_device::PCIeTypes::Gen1; 12362cd45afSSpencer Ku } 12462cd45afSSpencer Ku if (generationInUse == 12562cd45afSSpencer Ku "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen2") 12662cd45afSSpencer Ku { 127*0ec8b83dSEd Tanous return pcie_device::PCIeTypes::Gen2; 12862cd45afSSpencer Ku } 12962cd45afSSpencer Ku if (generationInUse == 13062cd45afSSpencer Ku "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen3") 13162cd45afSSpencer Ku { 132*0ec8b83dSEd Tanous return pcie_device::PCIeTypes::Gen3; 13362cd45afSSpencer Ku } 13462cd45afSSpencer Ku if (generationInUse == 13562cd45afSSpencer Ku "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen4") 13662cd45afSSpencer Ku { 137*0ec8b83dSEd Tanous return pcie_device::PCIeTypes::Gen4; 13862cd45afSSpencer Ku } 13962cd45afSSpencer Ku if (generationInUse == 14062cd45afSSpencer Ku "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen5") 14162cd45afSSpencer Ku { 142*0ec8b83dSEd Tanous return pcie_device::PCIeTypes::Gen5; 14362cd45afSSpencer Ku } 144e825cbc8SEd Tanous if (generationInUse.empty() || 145e825cbc8SEd Tanous generationInUse == 14662cd45afSSpencer Ku "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Unknown") 14762cd45afSSpencer Ku { 148*0ec8b83dSEd Tanous return pcie_device::PCIeTypes::Invalid; 14962cd45afSSpencer Ku } 15062cd45afSSpencer Ku 15162cd45afSSpencer Ku // The value is not unknown or Gen1-5, need return an internal error. 15262cd45afSSpencer Ku return std::nullopt; 15362cd45afSSpencer Ku } 15462cd45afSSpencer Ku 1557e860f15SJohn Edward Broadbent inline void requestRoutesSystemPCIeDevice(App& app) 156f5c9f8bdSJason M. Bills { 15722d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/PCIeDevices/<str>/") 158ed398213SEd Tanous .privileges(redfish::privileges::getPCIeDevice) 159002d39b4SEd Tanous .methods(boost::beast::http::verb::get)( 160002d39b4SEd Tanous [&app](const crow::Request& req, 1617e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 16222d268cbSEd Tanous const std::string& systemName, const std::string& device) { 1633ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 1647e860f15SJohn Edward Broadbent { 16545ca1b86SEd Tanous return; 16645ca1b86SEd Tanous } 16722d268cbSEd Tanous if (systemName != "system") 16822d268cbSEd Tanous { 16922d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 17022d268cbSEd Tanous systemName); 17122d268cbSEd Tanous return; 17222d268cbSEd Tanous } 17322d268cbSEd Tanous 174168e20c1SEd Tanous auto getPCIeDeviceCallback = 17545ca1b86SEd Tanous [asyncResp, device]( 17645ca1b86SEd Tanous const boost::system::error_code ec, 17745ca1b86SEd Tanous const dbus::utility::DBusPropertiesMap& pcieDevProperties) { 178f5c9f8bdSJason M. Bills if (ec) 179f5c9f8bdSJason M. Bills { 180f5c9f8bdSJason M. Bills BMCWEB_LOG_DEBUG 181002d39b4SEd Tanous << "failed to get PCIe Device properties ec: " << ec.value() 182002d39b4SEd Tanous << ": " << ec.message(); 18345ca1b86SEd Tanous if (ec.value() == 18445ca1b86SEd Tanous boost::system::linux_error::bad_request_descriptor) 185f5c9f8bdSJason M. Bills { 186002d39b4SEd Tanous messages::resourceNotFound(asyncResp->res, "PCIeDevice", 187002d39b4SEd Tanous device); 188f5c9f8bdSJason M. Bills } 189f5c9f8bdSJason M. Bills else 190f5c9f8bdSJason M. Bills { 191f5c9f8bdSJason M. Bills messages::internalError(asyncResp->res); 192f5c9f8bdSJason M. Bills } 193f5c9f8bdSJason M. Bills return; 194f5c9f8bdSJason M. Bills } 195f5c9f8bdSJason M. Bills 196d1bde9e5SKrzysztof Grobelny const std::string* manufacturer = nullptr; 197d1bde9e5SKrzysztof Grobelny const std::string* deviceType = nullptr; 198d1bde9e5SKrzysztof Grobelny const std::string* generationInUse = nullptr; 199d1bde9e5SKrzysztof Grobelny 200d1bde9e5SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 201d1bde9e5SKrzysztof Grobelny dbus_utils::UnpackErrorPrinter(), pcieDevProperties, 202d1bde9e5SKrzysztof Grobelny "Manufacturer", manufacturer, "DeviceType", deviceType, 203d1bde9e5SKrzysztof Grobelny "GenerationInUse", generationInUse); 204d1bde9e5SKrzysztof Grobelny 205d1bde9e5SKrzysztof Grobelny if (!success) 206d1bde9e5SKrzysztof Grobelny { 207d1bde9e5SKrzysztof Grobelny messages::internalError(asyncResp->res); 208d1bde9e5SKrzysztof Grobelny return; 209d1bde9e5SKrzysztof Grobelny } 210d1bde9e5SKrzysztof Grobelny 211d1bde9e5SKrzysztof Grobelny if (generationInUse != nullptr) 212d1bde9e5SKrzysztof Grobelny { 213*0ec8b83dSEd Tanous std::optional<pcie_device::PCIeTypes> redfishGenerationInUse = 214d1bde9e5SKrzysztof Grobelny redfishPcieGenerationFromDbus(*generationInUse); 215d1bde9e5SKrzysztof Grobelny if (!redfishGenerationInUse) 216d1bde9e5SKrzysztof Grobelny { 217d1bde9e5SKrzysztof Grobelny messages::internalError(asyncResp->res); 218d1bde9e5SKrzysztof Grobelny return; 219d1bde9e5SKrzysztof Grobelny } 220*0ec8b83dSEd Tanous if (*redfishGenerationInUse != pcie_device::PCIeTypes::Invalid) 221d1bde9e5SKrzysztof Grobelny { 222d1bde9e5SKrzysztof Grobelny asyncResp->res.jsonValue["PCIeInterface"]["PCIeType"] = 223d1bde9e5SKrzysztof Grobelny *redfishGenerationInUse; 224d1bde9e5SKrzysztof Grobelny } 225a9f68bb5STony Lee } 226d1bde9e5SKrzysztof Grobelny 227d1bde9e5SKrzysztof Grobelny if (manufacturer != nullptr) 228d1bde9e5SKrzysztof Grobelny { 229d1bde9e5SKrzysztof Grobelny asyncResp->res.jsonValue["Manufacturer"] = *manufacturer; 230d1bde9e5SKrzysztof Grobelny } 231d1bde9e5SKrzysztof Grobelny 232d1bde9e5SKrzysztof Grobelny if (deviceType != nullptr) 233d1bde9e5SKrzysztof Grobelny { 234d1bde9e5SKrzysztof Grobelny asyncResp->res.jsonValue["DeviceType"] = *deviceType; 235d1bde9e5SKrzysztof Grobelny } 236d1bde9e5SKrzysztof Grobelny 2371476687dSEd Tanous asyncResp->res.jsonValue["@odata.type"] = 2381476687dSEd Tanous "#PCIeDevice.v1_4_0.PCIeDevice"; 2391476687dSEd Tanous asyncResp->res.jsonValue["@odata.id"] = 2401476687dSEd Tanous "/redfish/v1/Systems/system/PCIeDevices/" + device; 2411476687dSEd Tanous asyncResp->res.jsonValue["Name"] = "PCIe Device"; 2421476687dSEd Tanous asyncResp->res.jsonValue["Id"] = device; 2431476687dSEd Tanous 2441476687dSEd Tanous asyncResp->res.jsonValue["PCIeFunctions"]["@odata.id"] = 24545ca1b86SEd Tanous "/redfish/v1/Systems/system/PCIeDevices/" + device + 2461476687dSEd Tanous "/PCIeFunctions"; 247dede6a98SJason M. Bills }; 248dede6a98SJason M. Bills std::string escapedPath = std::string(pciePath) + "/" + device; 249dede6a98SJason M. Bills dbus::utility::escapePathForDbus(escapedPath); 250d1bde9e5SKrzysztof Grobelny sdbusplus::asio::getAllProperties( 251d1bde9e5SKrzysztof Grobelny *crow::connections::systemBus, pcieService, escapedPath, 252d1bde9e5SKrzysztof Grobelny pcieDeviceInterface, std::move(getPCIeDeviceCallback)); 2537e860f15SJohn Edward Broadbent }); 254dede6a98SJason M. Bills } 255dede6a98SJason M. Bills 2567e860f15SJohn Edward Broadbent inline void requestRoutesSystemPCIeFunctionCollection(App& app) 2577e860f15SJohn Edward Broadbent { 258dede6a98SJason M. Bills /** 259dede6a98SJason M. Bills * Functions triggers appropriate requests on DBus 260dede6a98SJason M. Bills */ 2617e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 2627e860f15SJohn Edward Broadbent "/redfish/v1/Systems/system/PCIeDevices/<str>/PCIeFunctions/") 263ed398213SEd Tanous .privileges(redfish::privileges::getPCIeFunctionCollection) 264002d39b4SEd Tanous .methods(boost::beast::http::verb::get)( 265002d39b4SEd Tanous [&app](const crow::Request& req, 2667e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 26745ca1b86SEd Tanous const std::string& device) { 2683ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 269dede6a98SJason M. Bills { 27045ca1b86SEd Tanous return; 27145ca1b86SEd Tanous } 2721476687dSEd Tanous 2731476687dSEd Tanous asyncResp->res.jsonValue["@odata.type"] = 2741476687dSEd Tanous "#PCIeFunctionCollection.PCIeFunctionCollection"; 2751476687dSEd Tanous asyncResp->res.jsonValue["@odata.id"] = 2761476687dSEd Tanous "/redfish/v1/Systems/system/PCIeDevices/" + device + 2771476687dSEd Tanous "/PCIeFunctions"; 2781476687dSEd Tanous asyncResp->res.jsonValue["Name"] = "PCIe Function Collection"; 2791476687dSEd Tanous asyncResp->res.jsonValue["Description"] = 2801476687dSEd Tanous "Collection of PCIe Functions for PCIe Device " + device; 281dede6a98SJason M. Bills 282b9d36b47SEd Tanous auto getPCIeDeviceCallback = 28345ca1b86SEd Tanous [asyncResp, device]( 28445ca1b86SEd Tanous const boost::system::error_code ec, 28545ca1b86SEd Tanous const dbus::utility::DBusPropertiesMap& pcieDevProperties) { 2867e860f15SJohn Edward Broadbent if (ec) 2877e860f15SJohn Edward Broadbent { 2887e860f15SJohn Edward Broadbent BMCWEB_LOG_DEBUG 289002d39b4SEd Tanous << "failed to get PCIe Device properties ec: " << ec.value() 290002d39b4SEd Tanous << ": " << ec.message(); 29145ca1b86SEd Tanous if (ec.value() == 29245ca1b86SEd Tanous boost::system::linux_error::bad_request_descriptor) 2937e860f15SJohn Edward Broadbent { 294002d39b4SEd Tanous messages::resourceNotFound(asyncResp->res, "PCIeDevice", 295002d39b4SEd Tanous device); 2967e860f15SJohn Edward Broadbent } 2977e860f15SJohn Edward Broadbent else 2987e860f15SJohn Edward Broadbent { 2997e860f15SJohn Edward Broadbent messages::internalError(asyncResp->res); 3007e860f15SJohn Edward Broadbent } 3017e860f15SJohn Edward Broadbent return; 3027e860f15SJohn Edward Broadbent } 3037e860f15SJohn Edward Broadbent 3047e860f15SJohn Edward Broadbent nlohmann::json& pcieFunctionList = 3057e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Members"]; 3067e860f15SJohn Edward Broadbent pcieFunctionList = nlohmann::json::array(); 3077e860f15SJohn Edward Broadbent static constexpr const int maxPciFunctionNum = 8; 30845ca1b86SEd Tanous for (int functionNum = 0; functionNum < maxPciFunctionNum; 30945ca1b86SEd Tanous functionNum++) 3107e860f15SJohn Edward Broadbent { 311b9d36b47SEd Tanous // Check if this function exists by looking for a 312b9d36b47SEd Tanous // device ID 3137e860f15SJohn Edward Broadbent std::string devIDProperty = 314002d39b4SEd Tanous "Function" + std::to_string(functionNum) + "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 { 320002d39b4SEd Tanous property = std::get_if<std::string>(&propEntry.second); 321b9d36b47SEd Tanous } 322b9d36b47SEd Tanous } 323fb0ecc3eSNan Zhou if (property == nullptr || property->empty()) 324b9d36b47SEd Tanous { 325e28ce0e6SNan Zhou continue; 326b9d36b47SEd Tanous } 3271476687dSEd Tanous nlohmann::json::object_t pcieFunction; 3281476687dSEd Tanous pcieFunction["@odata.id"] = 3291476687dSEd Tanous "/redfish/v1/Systems/system/PCIeDevices/" + device + 3301476687dSEd Tanous "/PCIeFunctions/" + std::to_string(functionNum); 3311476687dSEd Tanous pcieFunctionList.push_back(std::move(pcieFunction)); 3327e860f15SJohn Edward Broadbent } 333a818d15aSJiaqing Zhao asyncResp->res.jsonValue["Members@odata.count"] = 3347e860f15SJohn Edward Broadbent pcieFunctionList.size(); 3357e860f15SJohn Edward Broadbent }; 3367e860f15SJohn Edward Broadbent std::string escapedPath = std::string(pciePath) + "/" + device; 3377e860f15SJohn Edward Broadbent dbus::utility::escapePathForDbus(escapedPath); 338d1bde9e5SKrzysztof Grobelny sdbusplus::asio::getAllProperties( 339d1bde9e5SKrzysztof Grobelny *crow::connections::systemBus, pcieService, escapedPath, 340d1bde9e5SKrzysztof Grobelny pcieDeviceInterface, std::move(getPCIeDeviceCallback)); 3417e860f15SJohn Edward Broadbent }); 3427e860f15SJohn Edward Broadbent } 3437e860f15SJohn Edward Broadbent 3447e860f15SJohn Edward Broadbent inline void requestRoutesSystemPCIeFunction(App& app) 3457e860f15SJohn Edward Broadbent { 3467e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 3477e860f15SJohn Edward Broadbent app, 3487e860f15SJohn Edward Broadbent "/redfish/v1/Systems/system/PCIeDevices/<str>/PCIeFunctions/<str>/") 349ed398213SEd Tanous .privileges(redfish::privileges::getPCIeFunction) 350002d39b4SEd Tanous .methods(boost::beast::http::verb::get)( 351002d39b4SEd Tanous [&app](const crow::Request& req, 35245ca1b86SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 353002d39b4SEd Tanous const std::string& device, const std::string& function) { 3543ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 35545ca1b86SEd Tanous { 35645ca1b86SEd Tanous return; 35745ca1b86SEd Tanous } 358168e20c1SEd Tanous auto getPCIeDeviceCallback = 359168e20c1SEd Tanous [asyncResp, device, function]( 3607e860f15SJohn Edward Broadbent const boost::system::error_code ec, 361b9d36b47SEd Tanous const dbus::utility::DBusPropertiesMap& pcieDevProperties) { 362dede6a98SJason M. Bills if (ec) 363dede6a98SJason M. Bills { 364dede6a98SJason M. Bills BMCWEB_LOG_DEBUG 365002d39b4SEd Tanous << "failed to get PCIe Device properties ec: " << ec.value() 366002d39b4SEd Tanous << ": " << ec.message(); 367dede6a98SJason M. Bills if (ec.value() == 368dede6a98SJason M. Bills boost::system::linux_error::bad_request_descriptor) 369dede6a98SJason M. Bills { 370002d39b4SEd Tanous messages::resourceNotFound(asyncResp->res, "PCIeDevice", 371002d39b4SEd Tanous device); 372dede6a98SJason M. Bills } 373dede6a98SJason M. Bills else 374dede6a98SJason M. Bills { 375dede6a98SJason M. Bills messages::internalError(asyncResp->res); 376dede6a98SJason M. Bills } 377dede6a98SJason M. Bills return; 378dede6a98SJason M. Bills } 379dede6a98SJason M. Bills 3801476687dSEd Tanous // Check if this function exists by looking for a device 3811476687dSEd Tanous // ID 382b9d36b47SEd Tanous std::string functionName = "Function" + function; 383b9d36b47SEd Tanous std::string devIDProperty = functionName + "DeviceId"; 384b9d36b47SEd Tanous 385b9d36b47SEd Tanous const std::string* devIdProperty = nullptr; 386b9d36b47SEd Tanous for (const auto& property : pcieDevProperties) 387b9d36b47SEd Tanous { 388b9d36b47SEd Tanous if (property.first == devIDProperty) 389b9d36b47SEd Tanous { 390002d39b4SEd Tanous devIdProperty = std::get_if<std::string>(&property.second); 391b9d36b47SEd Tanous continue; 392b9d36b47SEd Tanous } 393b9d36b47SEd Tanous } 394973c1355STony Lee if (devIdProperty == nullptr || devIdProperty->empty()) 395f5c9f8bdSJason M. Bills { 396002d39b4SEd Tanous messages::resourceNotFound(asyncResp->res, "PCIeFunction", 397002d39b4SEd Tanous function); 398f5c9f8bdSJason M. Bills return; 399f5c9f8bdSJason M. Bills } 400f5c9f8bdSJason M. Bills 4011476687dSEd Tanous asyncResp->res.jsonValue["@odata.type"] = 4021476687dSEd Tanous "#PCIeFunction.v1_2_0.PCIeFunction"; 4031476687dSEd Tanous asyncResp->res.jsonValue["@odata.id"] = 404168e20c1SEd Tanous "/redfish/v1/Systems/system/PCIeDevices/" + device + 4051476687dSEd Tanous "/PCIeFunctions/" + function; 4061476687dSEd Tanous asyncResp->res.jsonValue["Name"] = "PCIe Function"; 4071476687dSEd Tanous asyncResp->res.jsonValue["Id"] = function; 408002d39b4SEd Tanous asyncResp->res.jsonValue["FunctionId"] = std::stoi(function); 409002d39b4SEd Tanous asyncResp->res.jsonValue["Links"]["PCIeDevice"]["@odata.id"] = 4101476687dSEd Tanous "/redfish/v1/Systems/system/PCIeDevices/" + device; 411f5c9f8bdSJason M. Bills 412b9d36b47SEd Tanous for (const auto& property : pcieDevProperties) 413f5c9f8bdSJason M. Bills { 414b9d36b47SEd Tanous const std::string* strProperty = 415b9d36b47SEd Tanous std::get_if<std::string>(&property.second); 416b9d36b47SEd Tanous if (property.first == functionName + "DeviceId") 417f5c9f8bdSJason M. Bills { 418b9d36b47SEd Tanous asyncResp->res.jsonValue["DeviceId"] = *strProperty; 419f5c9f8bdSJason M. Bills } 420b9d36b47SEd Tanous if (property.first == functionName + "VendorId") 421f5c9f8bdSJason M. Bills { 422b9d36b47SEd Tanous asyncResp->res.jsonValue["VendorId"] = *strProperty; 423f5c9f8bdSJason M. Bills } 424b9d36b47SEd Tanous if (property.first == functionName + "FunctionType") 425f5c9f8bdSJason M. Bills { 426002d39b4SEd Tanous asyncResp->res.jsonValue["FunctionType"] = *strProperty; 427f5c9f8bdSJason M. Bills } 428b9d36b47SEd Tanous if (property.first == functionName + "DeviceClass") 429f5c9f8bdSJason M. Bills { 430002d39b4SEd Tanous asyncResp->res.jsonValue["DeviceClass"] = *strProperty; 431f5c9f8bdSJason M. Bills } 432b9d36b47SEd Tanous if (property.first == functionName + "ClassCode") 433f5c9f8bdSJason M. Bills { 434002d39b4SEd Tanous asyncResp->res.jsonValue["ClassCode"] = *strProperty; 435f5c9f8bdSJason M. Bills } 436b9d36b47SEd Tanous if (property.first == functionName + "RevisionId") 437f5c9f8bdSJason M. Bills { 438002d39b4SEd Tanous asyncResp->res.jsonValue["RevisionId"] = *strProperty; 439f5c9f8bdSJason M. Bills } 440b9d36b47SEd Tanous if (property.first == functionName + "SubsystemId") 441b9d36b47SEd Tanous { 442002d39b4SEd Tanous asyncResp->res.jsonValue["SubsystemId"] = *strProperty; 443b9d36b47SEd Tanous } 444002d39b4SEd Tanous if (property.first == functionName + "SubsystemVendorId") 445f5c9f8bdSJason M. Bills { 446168e20c1SEd Tanous asyncResp->res.jsonValue["SubsystemVendorId"] = 447b9d36b47SEd Tanous *strProperty; 448b9d36b47SEd Tanous } 449f5c9f8bdSJason M. Bills } 450f5c9f8bdSJason M. Bills }; 451f5c9f8bdSJason M. Bills std::string escapedPath = std::string(pciePath) + "/" + device; 452f5c9f8bdSJason M. Bills dbus::utility::escapePathForDbus(escapedPath); 453d1bde9e5SKrzysztof Grobelny sdbusplus::asio::getAllProperties( 454d1bde9e5SKrzysztof Grobelny *crow::connections::systemBus, pcieService, escapedPath, 455d1bde9e5SKrzysztof Grobelny pcieDeviceInterface, std::move(getPCIeDeviceCallback)); 4567e860f15SJohn Edward Broadbent }); 457f5c9f8bdSJason M. Bills } 458f5c9f8bdSJason M. Bills 459f5c9f8bdSJason M. Bills } // namespace redfish 460