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> 22ed398213SEd Tanous #include <registries/privilege_registry.hpp> 23f5c9f8bdSJason M. Bills 24f5c9f8bdSJason M. Bills namespace redfish 25f5c9f8bdSJason M. Bills { 26f5c9f8bdSJason M. Bills 27f5c9f8bdSJason M. Bills static constexpr char const* pcieService = "xyz.openbmc_project.PCIe"; 28f5c9f8bdSJason M. Bills static constexpr char const* pciePath = "/xyz/openbmc_project/PCIe"; 29f5c9f8bdSJason M. Bills static constexpr char const* pcieDeviceInterface = 30f5c9f8bdSJason M. Bills "xyz.openbmc_project.PCIe.Device"; 31f5c9f8bdSJason M. Bills 32b5a76932SEd Tanous static inline void 338d1b46d7Szhanghch05 getPCIeDeviceList(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 34adbe192aSJason M. Bills const std::string& name) 35f5c9f8bdSJason M. Bills { 36*b9d36b47SEd Tanous auto getPCIeMapCallback = 37*b9d36b47SEd Tanous [asyncResp, name](const boost::system::error_code ec, 38*b9d36b47SEd Tanous const dbus::utility::MapperGetSubTreePathsResponse& 39*b9d36b47SEd Tanous pcieDevicePaths) { 40f5c9f8bdSJason M. Bills if (ec) 41f5c9f8bdSJason M. Bills { 42a2730f01SAndrew Geissler BMCWEB_LOG_DEBUG << "no PCIe device paths found ec: " 43f5c9f8bdSJason M. Bills << ec.message(); 44a2730f01SAndrew Geissler // Not an error, system just doesn't have PCIe info 45f5c9f8bdSJason M. Bills return; 46f5c9f8bdSJason M. Bills } 47adbe192aSJason M. Bills nlohmann::json& pcieDeviceList = asyncResp->res.jsonValue[name]; 48f5c9f8bdSJason M. Bills pcieDeviceList = nlohmann::json::array(); 49f5c9f8bdSJason M. Bills for (const std::string& pcieDevicePath : pcieDevicePaths) 50f5c9f8bdSJason M. Bills { 513174e4dfSEd Tanous size_t devStart = pcieDevicePath.rfind('/'); 52f5c9f8bdSJason M. Bills if (devStart == std::string::npos) 53f5c9f8bdSJason M. Bills { 54f5c9f8bdSJason M. Bills continue; 55f5c9f8bdSJason M. Bills } 56f5c9f8bdSJason M. Bills 57f5c9f8bdSJason M. Bills std::string devName = pcieDevicePath.substr(devStart + 1); 58f5c9f8bdSJason M. Bills if (devName.empty()) 59f5c9f8bdSJason M. Bills { 60f5c9f8bdSJason M. Bills continue; 61f5c9f8bdSJason M. Bills } 62f5c9f8bdSJason M. Bills pcieDeviceList.push_back( 63f5c9f8bdSJason M. Bills {{"@odata.id", 64f5c9f8bdSJason M. Bills "/redfish/v1/Systems/system/PCIeDevices/" + devName}}); 65f5c9f8bdSJason M. Bills } 66*b9d36b47SEd Tanous asyncResp->res.jsonValue[name + "@odata.count"] = 67*b9d36b47SEd Tanous pcieDeviceList.size(); 68f5c9f8bdSJason M. Bills }; 69f5c9f8bdSJason M. Bills crow::connections::systemBus->async_method_call( 70f5c9f8bdSJason M. Bills std::move(getPCIeMapCallback), "xyz.openbmc_project.ObjectMapper", 71f5c9f8bdSJason M. Bills "/xyz/openbmc_project/object_mapper", 72f5c9f8bdSJason M. Bills "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", 73f5c9f8bdSJason M. Bills std::string(pciePath) + "/", 1, std::array<std::string, 0>()); 74f5c9f8bdSJason M. Bills } 75f5c9f8bdSJason M. Bills 767e860f15SJohn Edward Broadbent inline void requestRoutesSystemPCIeDeviceCollection(App& app) 77adbe192aSJason M. Bills { 78adbe192aSJason M. Bills /** 79adbe192aSJason M. Bills * Functions triggers appropriate requests on DBus 80adbe192aSJason M. Bills */ 817e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/PCIeDevices/") 82ed398213SEd Tanous .privileges(redfish::privileges::getPCIeDeviceCollection) 837e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 847e860f15SJohn Edward Broadbent [](const crow::Request&, 857e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 867e860f15SJohn Edward Broadbent 87adbe192aSJason M. Bills { 88adbe192aSJason M. Bills asyncResp->res.jsonValue = { 897e860f15SJohn Edward Broadbent {"@odata.type", 907e860f15SJohn Edward Broadbent "#PCIeDeviceCollection.PCIeDeviceCollection"}, 91adbe192aSJason M. Bills {"@odata.id", "/redfish/v1/Systems/system/PCIeDevices"}, 92adbe192aSJason M. Bills {"Name", "PCIe Device Collection"}, 93adbe192aSJason M. Bills {"Description", "Collection of PCIe Devices"}, 94adbe192aSJason M. Bills {"Members", nlohmann::json::array()}, 95adbe192aSJason M. Bills {"Members@odata.count", 0}}; 96adbe192aSJason M. Bills getPCIeDeviceList(asyncResp, "Members"); 977e860f15SJohn Edward Broadbent }); 98f5c9f8bdSJason M. Bills } 99f5c9f8bdSJason M. Bills 10062cd45afSSpencer Ku inline std::optional<std::string> 10162cd45afSSpencer Ku redfishPcieGenerationFromDbus(const std::string& generationInUse) 10262cd45afSSpencer Ku { 10362cd45afSSpencer Ku if (generationInUse == 10462cd45afSSpencer Ku "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen1") 10562cd45afSSpencer Ku { 10662cd45afSSpencer Ku return "Gen1"; 10762cd45afSSpencer Ku } 10862cd45afSSpencer Ku if (generationInUse == 10962cd45afSSpencer Ku "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen2") 11062cd45afSSpencer Ku { 11162cd45afSSpencer Ku return "Gen2"; 11262cd45afSSpencer Ku } 11362cd45afSSpencer Ku if (generationInUse == 11462cd45afSSpencer Ku "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen3") 11562cd45afSSpencer Ku { 11662cd45afSSpencer Ku return "Gen3"; 11762cd45afSSpencer Ku } 11862cd45afSSpencer Ku if (generationInUse == 11962cd45afSSpencer Ku "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen4") 12062cd45afSSpencer Ku { 12162cd45afSSpencer Ku return "Gen4"; 12262cd45afSSpencer Ku } 12362cd45afSSpencer Ku if (generationInUse == 12462cd45afSSpencer Ku "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen5") 12562cd45afSSpencer Ku { 12662cd45afSSpencer Ku return "Gen5"; 12762cd45afSSpencer Ku } 12862cd45afSSpencer Ku if (generationInUse.empty() || 12962cd45afSSpencer Ku generationInUse == 13062cd45afSSpencer Ku "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Unknown") 13162cd45afSSpencer Ku { 13262cd45afSSpencer Ku return ""; 13362cd45afSSpencer Ku } 13462cd45afSSpencer Ku 13562cd45afSSpencer Ku // The value is not unknown or Gen1-5, need return an internal error. 13662cd45afSSpencer Ku return std::nullopt; 13762cd45afSSpencer Ku } 13862cd45afSSpencer Ku 1397e860f15SJohn Edward Broadbent inline void requestRoutesSystemPCIeDevice(App& app) 140f5c9f8bdSJason M. Bills { 1417e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/PCIeDevices/<str>/") 142ed398213SEd Tanous .privileges(redfish::privileges::getPCIeDevice) 1437e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 1447e860f15SJohn Edward Broadbent [](const crow::Request&, 1457e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1467e860f15SJohn Edward Broadbent const std::string& device) 147f5c9f8bdSJason M. Bills 1487e860f15SJohn Edward Broadbent { 149168e20c1SEd Tanous auto getPCIeDeviceCallback = 150*b9d36b47SEd Tanous [asyncResp, device](const boost::system::error_code ec, 151*b9d36b47SEd Tanous const dbus::utility::DBusPropertiesMap& 1521214b7e7SGunnar Mills pcieDevProperties) { 153f5c9f8bdSJason M. Bills if (ec) 154f5c9f8bdSJason M. Bills { 155f5c9f8bdSJason M. Bills BMCWEB_LOG_DEBUG 156f5c9f8bdSJason M. Bills << "failed to get PCIe Device properties ec: " 157271584abSEd Tanous << ec.value() << ": " << ec.message(); 158168e20c1SEd Tanous if (ec.value() == boost::system::linux_error:: 159168e20c1SEd Tanous bad_request_descriptor) 160f5c9f8bdSJason M. Bills { 161168e20c1SEd Tanous messages::resourceNotFound( 162168e20c1SEd Tanous asyncResp->res, "PCIeDevice", device); 163f5c9f8bdSJason M. Bills } 164f5c9f8bdSJason M. Bills else 165f5c9f8bdSJason M. Bills { 166f5c9f8bdSJason M. Bills messages::internalError(asyncResp->res); 167f5c9f8bdSJason M. Bills } 168f5c9f8bdSJason M. Bills return; 169f5c9f8bdSJason M. Bills } 170f5c9f8bdSJason M. Bills 171f5c9f8bdSJason M. Bills asyncResp->res.jsonValue = { 172dede6a98SJason M. Bills {"@odata.type", "#PCIeDevice.v1_4_0.PCIeDevice"}, 173f5c9f8bdSJason M. Bills {"@odata.id", 174168e20c1SEd Tanous "/redfish/v1/Systems/system/PCIeDevices/" + 175168e20c1SEd Tanous device}, 176f5c9f8bdSJason M. Bills {"Name", "PCIe Device"}, 177f5c9f8bdSJason M. Bills {"Id", device}}; 178*b9d36b47SEd Tanous asyncResp->res.jsonValue["PCIeFunctions"] = { 179*b9d36b47SEd Tanous {"@odata.id", 180*b9d36b47SEd Tanous "/redfish/v1/Systems/system/PCIeDevices/" + 181*b9d36b47SEd Tanous device + "/PCIeFunctions"}}; 182*b9d36b47SEd Tanous for (const auto& property : pcieDevProperties) 183f5c9f8bdSJason M. Bills { 184*b9d36b47SEd Tanous const std::string* propertyString = 185*b9d36b47SEd Tanous std::get_if<std::string>(&property.second); 186*b9d36b47SEd Tanous if (property.first == "Manufacturer") 187*b9d36b47SEd Tanous { 188*b9d36b47SEd Tanous if (propertyString == nullptr) 189*b9d36b47SEd Tanous { 190*b9d36b47SEd Tanous messages::internalError(asyncResp->res); 191*b9d36b47SEd Tanous return; 192*b9d36b47SEd Tanous } 193168e20c1SEd Tanous asyncResp->res.jsonValue["Manufacturer"] = 194*b9d36b47SEd Tanous *propertyString; 195168e20c1SEd Tanous } 196*b9d36b47SEd Tanous if (property.first == "DeviceType") 197168e20c1SEd Tanous { 198*b9d36b47SEd Tanous if (propertyString == nullptr) 199*b9d36b47SEd Tanous { 200*b9d36b47SEd Tanous messages::internalError(asyncResp->res); 201*b9d36b47SEd Tanous return; 202168e20c1SEd Tanous } 203*b9d36b47SEd Tanous asyncResp->res.jsonValue["DeviceType"] = 204*b9d36b47SEd Tanous *propertyString; 205f5c9f8bdSJason M. Bills } 206*b9d36b47SEd Tanous if (property.first == "DeviceType") 207f5c9f8bdSJason M. Bills { 208*b9d36b47SEd Tanous if (propertyString == nullptr) 209*b9d36b47SEd Tanous { 210*b9d36b47SEd Tanous messages::internalError(asyncResp->res); 211*b9d36b47SEd Tanous return; 212f5c9f8bdSJason M. Bills } 213*b9d36b47SEd Tanous asyncResp->res.jsonValue["DeviceType"] = 214*b9d36b47SEd Tanous *propertyString; 215*b9d36b47SEd Tanous } 216*b9d36b47SEd Tanous if (property.first == "GenerationInUse") 21762cd45afSSpencer Ku { 218*b9d36b47SEd Tanous if (propertyString == nullptr) 219*b9d36b47SEd Tanous { 220*b9d36b47SEd Tanous messages::internalError(asyncResp->res); 221*b9d36b47SEd Tanous return; 222*b9d36b47SEd Tanous } 22362cd45afSSpencer Ku std::optional<std::string> generationInUse = 224*b9d36b47SEd Tanous redfishPcieGenerationFromDbus( 225*b9d36b47SEd Tanous *propertyString); 22662cd45afSSpencer Ku if (!generationInUse) 22762cd45afSSpencer Ku { 22862cd45afSSpencer Ku messages::internalError(asyncResp->res); 22962cd45afSSpencer Ku return; 23062cd45afSSpencer Ku } 23126f6976fSEd Tanous if (generationInUse->empty()) 23262cd45afSSpencer Ku { 23362cd45afSSpencer Ku // unknown, no need to handle 23462cd45afSSpencer Ku return; 23562cd45afSSpencer Ku } 236168e20c1SEd Tanous asyncResp->res 237213ffc70SAnjaliintel-21 .jsonValue["PCIeInterface"]["PCIeType"] = 23862cd45afSSpencer Ku *generationInUse; 23962cd45afSSpencer Ku } 240*b9d36b47SEd Tanous } 241dede6a98SJason M. Bills }; 242dede6a98SJason M. Bills std::string escapedPath = std::string(pciePath) + "/" + device; 243dede6a98SJason M. Bills dbus::utility::escapePathForDbus(escapedPath); 244dede6a98SJason M. Bills crow::connections::systemBus->async_method_call( 245dede6a98SJason M. Bills std::move(getPCIeDeviceCallback), pcieService, escapedPath, 2467e860f15SJohn Edward Broadbent "org.freedesktop.DBus.Properties", "GetAll", 2477e860f15SJohn Edward Broadbent pcieDeviceInterface); 2487e860f15SJohn Edward Broadbent }); 249dede6a98SJason M. Bills } 250dede6a98SJason M. Bills 2517e860f15SJohn Edward Broadbent inline void requestRoutesSystemPCIeFunctionCollection(App& app) 2527e860f15SJohn Edward Broadbent { 253dede6a98SJason M. Bills /** 254dede6a98SJason M. Bills * Functions triggers appropriate requests on DBus 255dede6a98SJason M. Bills */ 2567e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 2577e860f15SJohn Edward Broadbent "/redfish/v1/Systems/system/PCIeDevices/<str>/PCIeFunctions/") 258ed398213SEd Tanous .privileges(redfish::privileges::getPCIeFunctionCollection) 2597e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 2607e860f15SJohn Edward Broadbent [](const crow::Request&, 2617e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2627e860f15SJohn Edward Broadbent const std::string& device) 2637e860f15SJohn Edward Broadbent 264dede6a98SJason M. Bills { 265dede6a98SJason M. Bills asyncResp->res.jsonValue = { 2667e860f15SJohn Edward Broadbent {"@odata.type", 2677e860f15SJohn Edward Broadbent "#PCIeFunctionCollection.PCIeFunctionCollection"}, 2687e860f15SJohn Edward Broadbent {"@odata.id", "/redfish/v1/Systems/system/PCIeDevices/" + 2697e860f15SJohn Edward Broadbent device + "/PCIeFunctions"}, 270dede6a98SJason M. Bills {"Name", "PCIe Function Collection"}, 271dede6a98SJason M. Bills {"Description", 272dede6a98SJason M. Bills "Collection of PCIe Functions for PCIe Device " + device}}; 273dede6a98SJason M. Bills 274*b9d36b47SEd Tanous auto getPCIeDeviceCallback = 275*b9d36b47SEd Tanous [asyncResp, device](const boost::system::error_code ec, 276*b9d36b47SEd Tanous const dbus::utility::DBusPropertiesMap& 2777e860f15SJohn Edward Broadbent pcieDevProperties) { 2787e860f15SJohn Edward Broadbent if (ec) 2797e860f15SJohn Edward Broadbent { 2807e860f15SJohn Edward Broadbent BMCWEB_LOG_DEBUG 2817e860f15SJohn Edward Broadbent << "failed to get PCIe Device properties ec: " 2827e860f15SJohn Edward Broadbent << ec.value() << ": " << ec.message(); 283*b9d36b47SEd Tanous if (ec.value() == boost::system::linux_error:: 284*b9d36b47SEd Tanous bad_request_descriptor) 2857e860f15SJohn Edward Broadbent { 286*b9d36b47SEd Tanous messages::resourceNotFound( 287*b9d36b47SEd Tanous asyncResp->res, "PCIeDevice", device); 2887e860f15SJohn Edward Broadbent } 2897e860f15SJohn Edward Broadbent else 2907e860f15SJohn Edward Broadbent { 2917e860f15SJohn Edward Broadbent messages::internalError(asyncResp->res); 2927e860f15SJohn Edward Broadbent } 2937e860f15SJohn Edward Broadbent return; 2947e860f15SJohn Edward Broadbent } 2957e860f15SJohn Edward Broadbent 2967e860f15SJohn Edward Broadbent nlohmann::json& pcieFunctionList = 2977e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Members"]; 2987e860f15SJohn Edward Broadbent pcieFunctionList = nlohmann::json::array(); 2997e860f15SJohn Edward Broadbent static constexpr const int maxPciFunctionNum = 8; 300*b9d36b47SEd Tanous for (int functionNum = 0; 301*b9d36b47SEd Tanous functionNum < maxPciFunctionNum; functionNum++) 3027e860f15SJohn Edward Broadbent { 303*b9d36b47SEd Tanous // Check if this function exists by looking for a 304*b9d36b47SEd Tanous // device ID 3057e860f15SJohn Edward Broadbent std::string devIDProperty = 3067e860f15SJohn Edward Broadbent "Function" + std::to_string(functionNum) + 3077e860f15SJohn Edward Broadbent "DeviceId"; 308*b9d36b47SEd Tanous const std::string* property = nullptr; 309*b9d36b47SEd Tanous for (const auto& propEntry : pcieDevProperties) 3107e860f15SJohn Edward Broadbent { 311*b9d36b47SEd Tanous if (propEntry.first == devIDProperty) 312*b9d36b47SEd Tanous { 313*b9d36b47SEd Tanous property = std::get_if<std::string>( 314*b9d36b47SEd Tanous &propEntry.second); 315*b9d36b47SEd Tanous } 316*b9d36b47SEd Tanous } 317*b9d36b47SEd Tanous if (property == nullptr || !property->empty()) 318*b9d36b47SEd Tanous { 319*b9d36b47SEd Tanous return; 320*b9d36b47SEd Tanous } 3217e860f15SJohn Edward Broadbent pcieFunctionList.push_back( 3227e860f15SJohn Edward Broadbent {{"@odata.id", 3237e860f15SJohn Edward Broadbent "/redfish/v1/Systems/system/PCIeDevices/" + 3247e860f15SJohn Edward Broadbent device + "/PCIeFunctions/" + 3257e860f15SJohn Edward Broadbent std::to_string(functionNum)}}); 3267e860f15SJohn Edward Broadbent } 327a818d15aSJiaqing Zhao asyncResp->res.jsonValue["Members@odata.count"] = 3287e860f15SJohn Edward Broadbent pcieFunctionList.size(); 3297e860f15SJohn Edward Broadbent }; 3307e860f15SJohn Edward Broadbent std::string escapedPath = std::string(pciePath) + "/" + device; 3317e860f15SJohn Edward Broadbent dbus::utility::escapePathForDbus(escapedPath); 3327e860f15SJohn Edward Broadbent crow::connections::systemBus->async_method_call( 3337e860f15SJohn Edward Broadbent std::move(getPCIeDeviceCallback), pcieService, escapedPath, 3347e860f15SJohn Edward Broadbent "org.freedesktop.DBus.Properties", "GetAll", 3357e860f15SJohn Edward Broadbent pcieDeviceInterface); 3367e860f15SJohn Edward Broadbent }); 3377e860f15SJohn Edward Broadbent } 3387e860f15SJohn Edward Broadbent 3397e860f15SJohn Edward Broadbent inline void requestRoutesSystemPCIeFunction(App& app) 3407e860f15SJohn Edward Broadbent { 3417e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 3427e860f15SJohn Edward Broadbent app, 3437e860f15SJohn Edward Broadbent "/redfish/v1/Systems/system/PCIeDevices/<str>/PCIeFunctions/<str>/") 344ed398213SEd Tanous .privileges(redfish::privileges::getPCIeFunction) 3457e860f15SJohn Edward Broadbent .methods( 3467e860f15SJohn Edward Broadbent boost::beast::http::verb::get)([](const crow::Request&, 3477e860f15SJohn Edward Broadbent const std::shared_ptr< 3487e860f15SJohn Edward Broadbent bmcweb::AsyncResp>& asyncResp, 3497e860f15SJohn Edward Broadbent const std::string& device, 3507e860f15SJohn Edward Broadbent const std::string& function) { 351168e20c1SEd Tanous auto getPCIeDeviceCallback = 352168e20c1SEd Tanous [asyncResp, device, function]( 3537e860f15SJohn Edward Broadbent const boost::system::error_code ec, 354*b9d36b47SEd Tanous const dbus::utility::DBusPropertiesMap& pcieDevProperties) { 355dede6a98SJason M. Bills if (ec) 356dede6a98SJason M. Bills { 357dede6a98SJason M. Bills BMCWEB_LOG_DEBUG 358dede6a98SJason M. Bills << "failed to get PCIe Device properties ec: " 359dede6a98SJason M. Bills << ec.value() << ": " << ec.message(); 360dede6a98SJason M. Bills if (ec.value() == 361dede6a98SJason M. Bills boost::system::linux_error::bad_request_descriptor) 362dede6a98SJason M. Bills { 363168e20c1SEd Tanous messages::resourceNotFound(asyncResp->res, 364168e20c1SEd Tanous "PCIeDevice", device); 365dede6a98SJason M. Bills } 366dede6a98SJason M. Bills else 367dede6a98SJason M. Bills { 368dede6a98SJason M. Bills messages::internalError(asyncResp->res); 369dede6a98SJason M. Bills } 370dede6a98SJason M. Bills return; 371dede6a98SJason M. Bills } 372dede6a98SJason M. Bills 373f5c9f8bdSJason M. Bills // Check if this function exists by looking for a device ID 374*b9d36b47SEd Tanous std::string functionName = "Function" + function; 375*b9d36b47SEd Tanous std::string devIDProperty = functionName + "DeviceId"; 376*b9d36b47SEd Tanous 377*b9d36b47SEd Tanous const std::string* devIdProperty = nullptr; 378*b9d36b47SEd Tanous for (const auto& property : pcieDevProperties) 379*b9d36b47SEd Tanous { 380*b9d36b47SEd Tanous if (property.first == devIDProperty) 381*b9d36b47SEd Tanous { 382*b9d36b47SEd Tanous devIdProperty = 383*b9d36b47SEd Tanous std::get_if<std::string>(&property.second); 384*b9d36b47SEd Tanous continue; 385*b9d36b47SEd Tanous } 386*b9d36b47SEd Tanous } 387*b9d36b47SEd Tanous if (devIdProperty == nullptr || !devIdProperty->empty()) 388f5c9f8bdSJason M. Bills { 389168e20c1SEd Tanous messages::resourceNotFound(asyncResp->res, 390168e20c1SEd Tanous "PCIeFunction", function); 391f5c9f8bdSJason M. Bills return; 392f5c9f8bdSJason M. Bills } 393f5c9f8bdSJason M. Bills 394f5c9f8bdSJason M. Bills asyncResp->res.jsonValue = { 395f5c9f8bdSJason M. Bills {"@odata.type", "#PCIeFunction.v1_2_0.PCIeFunction"}, 396168e20c1SEd Tanous {"@odata.id", 397168e20c1SEd Tanous "/redfish/v1/Systems/system/PCIeDevices/" + device + 398168e20c1SEd Tanous "/PCIeFunctions/" + function}, 399f5c9f8bdSJason M. Bills {"Name", "PCIe Function"}, 400f5c9f8bdSJason M. Bills {"Id", function}, 401f5c9f8bdSJason M. Bills {"FunctionId", std::stoi(function)}, 402f5c9f8bdSJason M. Bills {"Links", 403f5c9f8bdSJason M. Bills {{"PCIeDevice", 404f5c9f8bdSJason M. Bills {{"@odata.id", 4057e860f15SJohn Edward Broadbent "/redfish/v1/Systems/system/PCIeDevices/" + 4067e860f15SJohn Edward Broadbent device}}}}}}; 407f5c9f8bdSJason M. Bills 408*b9d36b47SEd Tanous for (const auto& property : pcieDevProperties) 409f5c9f8bdSJason M. Bills { 410*b9d36b47SEd Tanous const std::string* strProperty = 411*b9d36b47SEd Tanous std::get_if<std::string>(&property.second); 412*b9d36b47SEd Tanous if (property.first == functionName + "DeviceId") 413f5c9f8bdSJason M. Bills { 414*b9d36b47SEd Tanous asyncResp->res.jsonValue["DeviceId"] = *strProperty; 415f5c9f8bdSJason M. Bills } 416*b9d36b47SEd Tanous if (property.first == functionName + "VendorId") 417f5c9f8bdSJason M. Bills { 418*b9d36b47SEd Tanous asyncResp->res.jsonValue["VendorId"] = *strProperty; 419f5c9f8bdSJason M. Bills } 420*b9d36b47SEd Tanous if (property.first == functionName + "FunctionType") 421f5c9f8bdSJason M. Bills { 422*b9d36b47SEd Tanous asyncResp->res.jsonValue["FunctionType"] = 423*b9d36b47SEd Tanous *strProperty; 424f5c9f8bdSJason M. Bills } 425*b9d36b47SEd Tanous if (property.first == functionName + "DeviceClass") 426f5c9f8bdSJason M. Bills { 427*b9d36b47SEd Tanous asyncResp->res.jsonValue["DeviceClass"] = 428*b9d36b47SEd Tanous *strProperty; 429f5c9f8bdSJason M. Bills } 430*b9d36b47SEd Tanous if (property.first == functionName + "ClassCode") 431f5c9f8bdSJason M. Bills { 432*b9d36b47SEd Tanous asyncResp->res.jsonValue["ClassCode"] = 433*b9d36b47SEd Tanous *strProperty; 434f5c9f8bdSJason M. Bills } 435*b9d36b47SEd Tanous if (property.first == functionName + "RevisionId") 436f5c9f8bdSJason M. Bills { 437*b9d36b47SEd Tanous asyncResp->res.jsonValue["RevisionId"] = 438*b9d36b47SEd Tanous *strProperty; 439f5c9f8bdSJason M. Bills } 440*b9d36b47SEd Tanous if (property.first == functionName + "SubsystemId") 441*b9d36b47SEd Tanous { 442*b9d36b47SEd Tanous asyncResp->res.jsonValue["SubsystemId"] = 443*b9d36b47SEd Tanous *strProperty; 444*b9d36b47SEd Tanous } 445*b9d36b47SEd Tanous if (property.first == 446*b9d36b47SEd Tanous functionName + "SubsystemVendorId") 447f5c9f8bdSJason M. Bills { 448168e20c1SEd Tanous asyncResp->res.jsonValue["SubsystemVendorId"] = 449*b9d36b47SEd Tanous *strProperty; 450*b9d36b47SEd Tanous } 451f5c9f8bdSJason M. Bills } 452f5c9f8bdSJason M. Bills }; 453f5c9f8bdSJason M. Bills std::string escapedPath = std::string(pciePath) + "/" + device; 454f5c9f8bdSJason M. Bills dbus::utility::escapePathForDbus(escapedPath); 455f5c9f8bdSJason M. Bills crow::connections::systemBus->async_method_call( 456f5c9f8bdSJason M. Bills std::move(getPCIeDeviceCallback), pcieService, escapedPath, 4577e860f15SJohn Edward Broadbent "org.freedesktop.DBus.Properties", "GetAll", 4587e860f15SJohn Edward Broadbent pcieDeviceInterface); 4597e860f15SJohn Edward Broadbent }); 460f5c9f8bdSJason M. Bills } 461f5c9f8bdSJason M. Bills 462f5c9f8bdSJason M. Bills } // namespace redfish 463