1ac6a4445SGunnar Mills /* 2ac6a4445SGunnar Mills // Copyright (c) 2018 Intel Corporation 3ac6a4445SGunnar Mills // 4ac6a4445SGunnar Mills // Licensed under the Apache License, Version 2.0 (the "License"); 5ac6a4445SGunnar Mills // you may not use this file except in compliance with the License. 6ac6a4445SGunnar Mills // You may obtain a copy of the License at 7ac6a4445SGunnar Mills // 8ac6a4445SGunnar Mills // http://www.apache.org/licenses/LICENSE-2.0 9ac6a4445SGunnar Mills // 10ac6a4445SGunnar Mills // Unless required by applicable law or agreed to in writing, software 11ac6a4445SGunnar Mills // distributed under the License is distributed on an "AS IS" BASIS, 12ac6a4445SGunnar Mills // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ac6a4445SGunnar Mills // See the License for the specific language governing permissions and 14ac6a4445SGunnar Mills // limitations under the License. 15ac6a4445SGunnar Mills */ 16ac6a4445SGunnar Mills #pragma once 17ac6a4445SGunnar Mills 183ccb3adbSEd Tanous #include "app.hpp" 191e1e598dSJonathan Doman #include "dbus_singleton.hpp" 207a1dbc48SGeorge Liu #include "dbus_utility.hpp" 211e1e598dSJonathan Doman #include "error_messages.hpp" 22dfbf7de5SChris Cain #include "generated/enums/processor.hpp" 23ac6a4445SGunnar Mills #include "health.hpp" 243ccb3adbSEd Tanous #include "query.hpp" 253ccb3adbSEd Tanous #include "registries/privilege_registry.hpp" 263ccb3adbSEd Tanous #include "utils/collection.hpp" 273ccb3adbSEd Tanous #include "utils/dbus_utils.hpp" 283ccb3adbSEd Tanous #include "utils/json_utils.hpp" 29ac6a4445SGunnar Mills 30ac6a4445SGunnar Mills #include <boost/container/flat_map.hpp> 31e99073f5SGeorge Liu #include <boost/system/error_code.hpp> 32ef4c65b7SEd Tanous #include <boost/url/format.hpp> 331e1e598dSJonathan Doman #include <sdbusplus/asio/property.hpp> 34dba0c291SJonathan Doman #include <sdbusplus/message/native_types.hpp> 35351053f2SKrzysztof Grobelny #include <sdbusplus/unpack_properties.hpp> 36dba0c291SJonathan Doman #include <sdbusplus/utility/dedup_variant.hpp> 37ac6a4445SGunnar Mills 387a1dbc48SGeorge Liu #include <array> 39b9d679d1SMichael Shen #include <limits> 403544d2a7SEd Tanous #include <ranges> 41*3c569218SEd Tanous #include <string> 427a1dbc48SGeorge Liu #include <string_view> 437a1dbc48SGeorge Liu 44ac6a4445SGunnar Mills namespace redfish 45ac6a4445SGunnar Mills { 46ac6a4445SGunnar Mills 47c951448aSJonathan Doman // Interfaces which imply a D-Bus object represents a Processor 487a1dbc48SGeorge Liu constexpr std::array<std::string_view, 2> processorInterfaces = { 49c951448aSJonathan Doman "xyz.openbmc_project.Inventory.Item.Cpu", 50c951448aSJonathan Doman "xyz.openbmc_project.Inventory.Item.Accelerator"}; 512bab9831SJonathan Doman 5271b82f26SSharad Yadav /** 5371b82f26SSharad Yadav * @brief Fill out uuid info of a processor by 5471b82f26SSharad Yadav * requesting data from the given D-Bus object. 5571b82f26SSharad Yadav * 56ac106bf6SEd Tanous * @param[in,out] asyncResp Async HTTP response. 5771b82f26SSharad Yadav * @param[in] service D-Bus service to query. 5871b82f26SSharad Yadav * @param[in] objPath D-Bus object to query. 5971b82f26SSharad Yadav */ 60ac106bf6SEd Tanous inline void getProcessorUUID(std::shared_ptr<bmcweb::AsyncResp> asyncResp, 6171b82f26SSharad Yadav const std::string& service, 6271b82f26SSharad Yadav const std::string& objPath) 6371b82f26SSharad Yadav { 6462598e31SEd Tanous BMCWEB_LOG_DEBUG("Get Processor UUID"); 651e1e598dSJonathan Doman sdbusplus::asio::getProperty<std::string>( 661e1e598dSJonathan Doman *crow::connections::systemBus, service, objPath, 671e1e598dSJonathan Doman "xyz.openbmc_project.Common.UUID", "UUID", 68ac106bf6SEd Tanous [objPath, asyncResp{std::move(asyncResp)}]( 69ac106bf6SEd Tanous const boost::system::error_code& ec, const std::string& property) { 7071b82f26SSharad Yadav if (ec) 7171b82f26SSharad Yadav { 7262598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error"); 73ac106bf6SEd Tanous messages::internalError(asyncResp->res); 7471b82f26SSharad Yadav return; 7571b82f26SSharad Yadav } 76ac106bf6SEd Tanous asyncResp->res.jsonValue["UUID"] = property; 771e1e598dSJonathan Doman }); 7871b82f26SSharad Yadav } 7971b82f26SSharad Yadav 80711ac7a9SEd Tanous inline void getCpuDataByInterface( 81ac106bf6SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 8280f79a40SMichael Shen const dbus::utility::DBusInterfacesMap& cpuInterfacesProperties) 83ac6a4445SGunnar Mills { 8462598e31SEd Tanous BMCWEB_LOG_DEBUG("Get CPU resources by interface."); 85ac6a4445SGunnar Mills 86a1649ec6SChicago Duan // Set the default value of state 87ac106bf6SEd Tanous asyncResp->res.jsonValue["Status"]["State"] = "Enabled"; 88ac106bf6SEd Tanous asyncResp->res.jsonValue["Status"]["Health"] = "OK"; 89ac6a4445SGunnar Mills 90ac6a4445SGunnar Mills for (const auto& interface : cpuInterfacesProperties) 91ac6a4445SGunnar Mills { 92ac6a4445SGunnar Mills for (const auto& property : interface.second) 93ac6a4445SGunnar Mills { 94a1649ec6SChicago Duan if (property.first == "Present") 95ac6a4445SGunnar Mills { 96a1649ec6SChicago Duan const bool* cpuPresent = std::get_if<bool>(&property.second); 97a1649ec6SChicago Duan if (cpuPresent == nullptr) 98ac6a4445SGunnar Mills { 99ac6a4445SGunnar Mills // Important property not in desired type 100ac106bf6SEd Tanous messages::internalError(asyncResp->res); 101ac6a4445SGunnar Mills return; 102ac6a4445SGunnar Mills } 103e05aec50SEd Tanous if (!*cpuPresent) 104ac6a4445SGunnar Mills { 105a1649ec6SChicago Duan // Slot is not populated 106ac106bf6SEd Tanous asyncResp->res.jsonValue["Status"]["State"] = "Absent"; 107a1649ec6SChicago Duan } 108a1649ec6SChicago Duan } 109a1649ec6SChicago Duan else if (property.first == "Functional") 110a1649ec6SChicago Duan { 111a1649ec6SChicago Duan const bool* cpuFunctional = std::get_if<bool>(&property.second); 112a1649ec6SChicago Duan if (cpuFunctional == nullptr) 113a1649ec6SChicago Duan { 114ac106bf6SEd Tanous messages::internalError(asyncResp->res); 115ac6a4445SGunnar Mills return; 116ac6a4445SGunnar Mills } 117e05aec50SEd Tanous if (!*cpuFunctional) 118a1649ec6SChicago Duan { 119ac106bf6SEd Tanous asyncResp->res.jsonValue["Status"]["Health"] = "Critical"; 120a1649ec6SChicago Duan } 121a1649ec6SChicago Duan } 122a1649ec6SChicago Duan else if (property.first == "CoreCount") 123a1649ec6SChicago Duan { 124a1649ec6SChicago Duan const uint16_t* coresCount = 125a1649ec6SChicago Duan std::get_if<uint16_t>(&property.second); 126a1649ec6SChicago Duan if (coresCount == nullptr) 127a1649ec6SChicago Duan { 128ac106bf6SEd Tanous messages::internalError(asyncResp->res); 129a1649ec6SChicago Duan return; 130a1649ec6SChicago Duan } 131ac106bf6SEd Tanous asyncResp->res.jsonValue["TotalCores"] = *coresCount; 132ac6a4445SGunnar Mills } 133dc3fa667SJonathan Doman else if (property.first == "MaxSpeedInMhz") 134dc3fa667SJonathan Doman { 135dc3fa667SJonathan Doman const uint32_t* value = std::get_if<uint32_t>(&property.second); 136dc3fa667SJonathan Doman if (value != nullptr) 137dc3fa667SJonathan Doman { 138ac106bf6SEd Tanous asyncResp->res.jsonValue["MaxSpeedMHz"] = *value; 139dc3fa667SJonathan Doman } 140dc3fa667SJonathan Doman } 141ac6a4445SGunnar Mills else if (property.first == "Socket") 142ac6a4445SGunnar Mills { 143ac6a4445SGunnar Mills const std::string* value = 144ac6a4445SGunnar Mills std::get_if<std::string>(&property.second); 145ac6a4445SGunnar Mills if (value != nullptr) 146ac6a4445SGunnar Mills { 147ac106bf6SEd Tanous asyncResp->res.jsonValue["Socket"] = *value; 148ac6a4445SGunnar Mills } 149ac6a4445SGunnar Mills } 150ac6a4445SGunnar Mills else if (property.first == "ThreadCount") 151ac6a4445SGunnar Mills { 152dc3fa667SJonathan Doman const uint16_t* value = std::get_if<uint16_t>(&property.second); 153ac6a4445SGunnar Mills if (value != nullptr) 154ac6a4445SGunnar Mills { 155ac106bf6SEd Tanous asyncResp->res.jsonValue["TotalThreads"] = *value; 156ac6a4445SGunnar Mills } 157ac6a4445SGunnar Mills } 1581930fbd4SBrandon Kim else if (property.first == "EffectiveFamily") 159ac6a4445SGunnar Mills { 1601930fbd4SBrandon Kim const uint16_t* value = std::get_if<uint16_t>(&property.second); 1616169de2cSBrad Bishop if (value != nullptr && *value != 2) 162ac6a4445SGunnar Mills { 163ac106bf6SEd Tanous asyncResp->res.jsonValue["ProcessorId"]["EffectiveFamily"] = 164866e4862SEd Tanous "0x" + intToHexString(*value, 4); 165ac6a4445SGunnar Mills } 166ac6a4445SGunnar Mills } 1671930fbd4SBrandon Kim else if (property.first == "EffectiveModel") 1681930fbd4SBrandon Kim { 1691930fbd4SBrandon Kim const uint16_t* value = std::get_if<uint16_t>(&property.second); 1701930fbd4SBrandon Kim if (value == nullptr) 1711930fbd4SBrandon Kim { 172ac106bf6SEd Tanous messages::internalError(asyncResp->res); 1731930fbd4SBrandon Kim return; 1741930fbd4SBrandon Kim } 1756169de2cSBrad Bishop if (*value != 0) 1766169de2cSBrad Bishop { 177ac106bf6SEd Tanous asyncResp->res.jsonValue["ProcessorId"]["EffectiveModel"] = 178866e4862SEd Tanous "0x" + intToHexString(*value, 4); 1791930fbd4SBrandon Kim } 1806169de2cSBrad Bishop } 181ac6a4445SGunnar Mills else if (property.first == "Id") 182ac6a4445SGunnar Mills { 183ac6a4445SGunnar Mills const uint64_t* value = std::get_if<uint64_t>(&property.second); 184ac6a4445SGunnar Mills if (value != nullptr && *value != 0) 185ac6a4445SGunnar Mills { 186ac106bf6SEd Tanous asyncResp->res 187ac6a4445SGunnar Mills .jsonValue["ProcessorId"]["IdentificationRegisters"] = 188866e4862SEd Tanous "0x" + intToHexString(*value, 16); 189ac6a4445SGunnar Mills } 190ac6a4445SGunnar Mills } 1911930fbd4SBrandon Kim else if (property.first == "Microcode") 1921930fbd4SBrandon Kim { 1931930fbd4SBrandon Kim const uint32_t* value = std::get_if<uint32_t>(&property.second); 1941930fbd4SBrandon Kim if (value == nullptr) 1951930fbd4SBrandon Kim { 196ac106bf6SEd Tanous messages::internalError(asyncResp->res); 1971930fbd4SBrandon Kim return; 1981930fbd4SBrandon Kim } 1996169de2cSBrad Bishop if (*value != 0) 2006169de2cSBrad Bishop { 201ac106bf6SEd Tanous asyncResp->res.jsonValue["ProcessorId"]["MicrocodeInfo"] = 202866e4862SEd Tanous "0x" + intToHexString(*value, 8); 2031930fbd4SBrandon Kim } 2046169de2cSBrad Bishop } 2051930fbd4SBrandon Kim else if (property.first == "Step") 2061930fbd4SBrandon Kim { 2071930fbd4SBrandon Kim const uint16_t* value = std::get_if<uint16_t>(&property.second); 2081930fbd4SBrandon Kim if (value == nullptr) 2091930fbd4SBrandon Kim { 210ac106bf6SEd Tanous messages::internalError(asyncResp->res); 2111930fbd4SBrandon Kim return; 2121930fbd4SBrandon Kim } 213b9d679d1SMichael Shen if (*value != std::numeric_limits<uint16_t>::max()) 2146169de2cSBrad Bishop { 215ac106bf6SEd Tanous asyncResp->res.jsonValue["ProcessorId"]["Step"] = 216866e4862SEd Tanous "0x" + intToHexString(*value, 4); 2171930fbd4SBrandon Kim } 218ac6a4445SGunnar Mills } 219ac6a4445SGunnar Mills } 220ac6a4445SGunnar Mills } 2216169de2cSBrad Bishop } 222ac6a4445SGunnar Mills 223ac106bf6SEd Tanous inline void getCpuDataByService(std::shared_ptr<bmcweb::AsyncResp> asyncResp, 224ac6a4445SGunnar Mills const std::string& cpuId, 225ac6a4445SGunnar Mills const std::string& service, 226ac6a4445SGunnar Mills const std::string& objPath) 227ac6a4445SGunnar Mills { 22862598e31SEd Tanous BMCWEB_LOG_DEBUG("Get available system cpu resources by service."); 229ac6a4445SGunnar Mills 2305eb468daSGeorge Liu sdbusplus::message::object_path path("/xyz/openbmc_project/inventory"); 2315eb468daSGeorge Liu dbus::utility::getManagedObjects( 2325eb468daSGeorge Liu service, path, 233ac106bf6SEd Tanous [cpuId, service, objPath, asyncResp{std::move(asyncResp)}]( 2345e7e2dc5SEd Tanous const boost::system::error_code& ec, 235ac6a4445SGunnar Mills const dbus::utility::ManagedObjectType& dbusData) { 236ac6a4445SGunnar Mills if (ec) 237ac6a4445SGunnar Mills { 23862598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error"); 239ac106bf6SEd Tanous messages::internalError(asyncResp->res); 240ac6a4445SGunnar Mills return; 241ac6a4445SGunnar Mills } 242ac106bf6SEd Tanous asyncResp->res.jsonValue["Id"] = cpuId; 243ac106bf6SEd Tanous asyncResp->res.jsonValue["Name"] = "Processor"; 244ac106bf6SEd Tanous asyncResp->res.jsonValue["ProcessorType"] = "CPU"; 245ac6a4445SGunnar Mills 246ac6a4445SGunnar Mills bool slotPresent = false; 247ac6a4445SGunnar Mills std::string corePath = objPath + "/core"; 248ac6a4445SGunnar Mills size_t totalCores = 0; 249ac6a4445SGunnar Mills for (const auto& object : dbusData) 250ac6a4445SGunnar Mills { 251ac6a4445SGunnar Mills if (object.first.str == objPath) 252ac6a4445SGunnar Mills { 253ac106bf6SEd Tanous getCpuDataByInterface(asyncResp, object.second); 254ac6a4445SGunnar Mills } 25511ba3979SEd Tanous else if (object.first.str.starts_with(corePath)) 256ac6a4445SGunnar Mills { 257ac6a4445SGunnar Mills for (const auto& interface : object.second) 258ac6a4445SGunnar Mills { 259002d39b4SEd Tanous if (interface.first == "xyz.openbmc_project.Inventory.Item") 260ac6a4445SGunnar Mills { 261ac6a4445SGunnar Mills for (const auto& property : interface.second) 262ac6a4445SGunnar Mills { 263ac6a4445SGunnar Mills if (property.first == "Present") 264ac6a4445SGunnar Mills { 265ac6a4445SGunnar Mills const bool* present = 266ac6a4445SGunnar Mills std::get_if<bool>(&property.second); 267ac6a4445SGunnar Mills if (present != nullptr) 268ac6a4445SGunnar Mills { 269e05aec50SEd Tanous if (*present) 270ac6a4445SGunnar Mills { 271ac6a4445SGunnar Mills slotPresent = true; 272ac6a4445SGunnar Mills totalCores++; 273ac6a4445SGunnar Mills } 274ac6a4445SGunnar Mills } 275ac6a4445SGunnar Mills } 276ac6a4445SGunnar Mills } 277ac6a4445SGunnar Mills } 278ac6a4445SGunnar Mills } 279ac6a4445SGunnar Mills } 280ac6a4445SGunnar Mills } 281ac6a4445SGunnar Mills // In getCpuDataByInterface(), state and health are set 282ac6a4445SGunnar Mills // based on the present and functional status. If core 283ac6a4445SGunnar Mills // count is zero, then it has a higher precedence. 284ac6a4445SGunnar Mills if (slotPresent) 285ac6a4445SGunnar Mills { 286ac6a4445SGunnar Mills if (totalCores == 0) 287ac6a4445SGunnar Mills { 288ac6a4445SGunnar Mills // Slot is not populated, set status end return 289ac106bf6SEd Tanous asyncResp->res.jsonValue["Status"]["State"] = "Absent"; 290ac106bf6SEd Tanous asyncResp->res.jsonValue["Status"]["Health"] = "OK"; 291ac6a4445SGunnar Mills } 292ac106bf6SEd Tanous asyncResp->res.jsonValue["TotalCores"] = totalCores; 293ac6a4445SGunnar Mills } 294ac6a4445SGunnar Mills return; 2955eb468daSGeorge Liu }); 296ac6a4445SGunnar Mills } 297ac6a4445SGunnar Mills 298dfbf7de5SChris Cain /** 299dfbf7de5SChris Cain * @brief Translates throttle cause DBUS property to redfish. 300dfbf7de5SChris Cain * 301dfbf7de5SChris Cain * @param[in] dbusSource The throttle cause from DBUS 302dfbf7de5SChris Cain * 303dfbf7de5SChris Cain * @return Returns as a string, the throttle cause in Redfish terms. If 304dfbf7de5SChris Cain * translation cannot be done, returns "Unknown" throttle reason. 305dfbf7de5SChris Cain */ 306dfbf7de5SChris Cain inline processor::ThrottleCause 307dfbf7de5SChris Cain dbusToRfThrottleCause(const std::string& dbusSource) 308dfbf7de5SChris Cain { 309dfbf7de5SChris Cain if (dbusSource == 310dfbf7de5SChris Cain "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.ClockLimit") 311dfbf7de5SChris Cain { 312dfbf7de5SChris Cain return processor::ThrottleCause::ClockLimit; 313dfbf7de5SChris Cain } 314dfbf7de5SChris Cain if (dbusSource == 315dfbf7de5SChris Cain "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.ManagementDetectedFault") 316dfbf7de5SChris Cain { 317dfbf7de5SChris Cain return processor::ThrottleCause::ManagementDetectedFault; 318dfbf7de5SChris Cain } 319dfbf7de5SChris Cain if (dbusSource == 320dfbf7de5SChris Cain "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.PowerLimit") 321dfbf7de5SChris Cain { 322dfbf7de5SChris Cain return processor::ThrottleCause::PowerLimit; 323dfbf7de5SChris Cain } 324dfbf7de5SChris Cain if (dbusSource == 325dfbf7de5SChris Cain "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.ThermalLimit") 326dfbf7de5SChris Cain { 327dfbf7de5SChris Cain return processor::ThrottleCause::ThermalLimit; 328dfbf7de5SChris Cain } 329dfbf7de5SChris Cain if (dbusSource == 330dfbf7de5SChris Cain "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.Unknown") 331dfbf7de5SChris Cain { 332dfbf7de5SChris Cain return processor::ThrottleCause::Unknown; 333dfbf7de5SChris Cain } 334dfbf7de5SChris Cain return processor::ThrottleCause::Invalid; 335dfbf7de5SChris Cain } 336dfbf7de5SChris Cain 337dfbf7de5SChris Cain inline void 338ac106bf6SEd Tanous readThrottleProperties(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 339dfbf7de5SChris Cain const boost::system::error_code& ec, 340dfbf7de5SChris Cain const dbus::utility::DBusPropertiesMap& properties) 341dfbf7de5SChris Cain { 342dfbf7de5SChris Cain if (ec) 343dfbf7de5SChris Cain { 34462598e31SEd Tanous BMCWEB_LOG_ERROR("Processor Throttle getAllProperties error {}", ec); 345ac106bf6SEd Tanous messages::internalError(asyncResp->res); 346dfbf7de5SChris Cain return; 347dfbf7de5SChris Cain } 348dfbf7de5SChris Cain 349dfbf7de5SChris Cain const bool* status = nullptr; 350dfbf7de5SChris Cain const std::vector<std::string>* causes = nullptr; 351dfbf7de5SChris Cain 352dfbf7de5SChris Cain if (!sdbusplus::unpackPropertiesNoThrow(dbus_utils::UnpackErrorPrinter(), 353dfbf7de5SChris Cain properties, "Throttled", status, 354dfbf7de5SChris Cain "ThrottleCauses", causes)) 355dfbf7de5SChris Cain { 356ac106bf6SEd Tanous messages::internalError(asyncResp->res); 357dfbf7de5SChris Cain return; 358dfbf7de5SChris Cain } 359dfbf7de5SChris Cain 360ac106bf6SEd Tanous asyncResp->res.jsonValue["Throttled"] = *status; 361dfbf7de5SChris Cain nlohmann::json::array_t rCauses; 362dfbf7de5SChris Cain for (const std::string& cause : *causes) 363dfbf7de5SChris Cain { 364dfbf7de5SChris Cain processor::ThrottleCause rfCause = dbusToRfThrottleCause(cause); 365dfbf7de5SChris Cain if (rfCause == processor::ThrottleCause::Invalid) 366dfbf7de5SChris Cain { 367ac106bf6SEd Tanous messages::internalError(asyncResp->res); 368dfbf7de5SChris Cain return; 369dfbf7de5SChris Cain } 370dfbf7de5SChris Cain 371dfbf7de5SChris Cain rCauses.emplace_back(rfCause); 372dfbf7de5SChris Cain } 373ac106bf6SEd Tanous asyncResp->res.jsonValue["ThrottleCauses"] = std::move(rCauses); 374dfbf7de5SChris Cain } 375dfbf7de5SChris Cain 376dfbf7de5SChris Cain inline void 377ac106bf6SEd Tanous getThrottleProperties(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 378dfbf7de5SChris Cain const std::string& service, 379dfbf7de5SChris Cain const std::string& objectPath) 380dfbf7de5SChris Cain { 38162598e31SEd Tanous BMCWEB_LOG_DEBUG("Get processor throttle resources"); 382dfbf7de5SChris Cain 383dfbf7de5SChris Cain sdbusplus::asio::getAllProperties( 384dfbf7de5SChris Cain *crow::connections::systemBus, service, objectPath, 385dfbf7de5SChris Cain "xyz.openbmc_project.Control.Power.Throttle", 386ac106bf6SEd Tanous [asyncResp](const boost::system::error_code& ec, 387dfbf7de5SChris Cain const dbus::utility::DBusPropertiesMap& properties) { 388ac106bf6SEd Tanous readThrottleProperties(asyncResp, ec, properties); 389dfbf7de5SChris Cain }); 390dfbf7de5SChris Cain } 391dfbf7de5SChris Cain 392ac106bf6SEd Tanous inline void getCpuAssetData(std::shared_ptr<bmcweb::AsyncResp> asyncResp, 393ac6a4445SGunnar Mills const std::string& service, 394ac6a4445SGunnar Mills const std::string& objPath) 395ac6a4445SGunnar Mills { 39662598e31SEd Tanous BMCWEB_LOG_DEBUG("Get Cpu Asset Data"); 397351053f2SKrzysztof Grobelny sdbusplus::asio::getAllProperties( 398351053f2SKrzysztof Grobelny *crow::connections::systemBus, service, objPath, 399351053f2SKrzysztof Grobelny "xyz.openbmc_project.Inventory.Decorator.Asset", 400ac106bf6SEd Tanous [objPath, asyncResp{std::move(asyncResp)}]( 4015e7e2dc5SEd Tanous const boost::system::error_code& ec, 402351053f2SKrzysztof Grobelny const dbus::utility::DBusPropertiesMap& properties) { 403ac6a4445SGunnar Mills if (ec) 404ac6a4445SGunnar Mills { 40562598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error"); 406ac106bf6SEd Tanous messages::internalError(asyncResp->res); 407ac6a4445SGunnar Mills return; 408ac6a4445SGunnar Mills } 409ac6a4445SGunnar Mills 410351053f2SKrzysztof Grobelny const std::string* serialNumber = nullptr; 411351053f2SKrzysztof Grobelny const std::string* model = nullptr; 412351053f2SKrzysztof Grobelny const std::string* manufacturer = nullptr; 413351053f2SKrzysztof Grobelny const std::string* partNumber = nullptr; 414351053f2SKrzysztof Grobelny const std::string* sparePartNumber = nullptr; 415351053f2SKrzysztof Grobelny 416351053f2SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 417351053f2SKrzysztof Grobelny dbus_utils::UnpackErrorPrinter(), properties, "SerialNumber", 418351053f2SKrzysztof Grobelny serialNumber, "Model", model, "Manufacturer", manufacturer, 419351053f2SKrzysztof Grobelny "PartNumber", partNumber, "SparePartNumber", sparePartNumber); 420351053f2SKrzysztof Grobelny 421351053f2SKrzysztof Grobelny if (!success) 422ac6a4445SGunnar Mills { 423ac106bf6SEd Tanous messages::internalError(asyncResp->res); 424351053f2SKrzysztof Grobelny return; 425ac6a4445SGunnar Mills } 426351053f2SKrzysztof Grobelny 427351053f2SKrzysztof Grobelny if (serialNumber != nullptr && !serialNumber->empty()) 428ac6a4445SGunnar Mills { 429ac106bf6SEd Tanous asyncResp->res.jsonValue["SerialNumber"] = *serialNumber; 430351053f2SKrzysztof Grobelny } 431351053f2SKrzysztof Grobelny 432351053f2SKrzysztof Grobelny if ((model != nullptr) && !model->empty()) 433ac6a4445SGunnar Mills { 434ac106bf6SEd Tanous asyncResp->res.jsonValue["Model"] = *model; 435ac6a4445SGunnar Mills } 436ac6a4445SGunnar Mills 437351053f2SKrzysztof Grobelny if (manufacturer != nullptr) 438ac6a4445SGunnar Mills { 439ac106bf6SEd Tanous asyncResp->res.jsonValue["Manufacturer"] = *manufacturer; 440ac6a4445SGunnar Mills 441ac6a4445SGunnar Mills // Otherwise would be unexpected. 442351053f2SKrzysztof Grobelny if (manufacturer->find("Intel") != std::string::npos) 443ac6a4445SGunnar Mills { 444ac106bf6SEd Tanous asyncResp->res.jsonValue["ProcessorArchitecture"] = "x86"; 445ac106bf6SEd Tanous asyncResp->res.jsonValue["InstructionSet"] = "x86-64"; 446ac6a4445SGunnar Mills } 447351053f2SKrzysztof Grobelny else if (manufacturer->find("IBM") != std::string::npos) 448ac6a4445SGunnar Mills { 449ac106bf6SEd Tanous asyncResp->res.jsonValue["ProcessorArchitecture"] = "Power"; 450ac106bf6SEd Tanous asyncResp->res.jsonValue["InstructionSet"] = "PowerISA"; 451ac6a4445SGunnar Mills } 452ac6a4445SGunnar Mills } 453cba4f448SSunnySrivastava1984 454351053f2SKrzysztof Grobelny if (partNumber != nullptr) 455cba4f448SSunnySrivastava1984 { 456ac106bf6SEd Tanous asyncResp->res.jsonValue["PartNumber"] = *partNumber; 457cba4f448SSunnySrivastava1984 } 458cba4f448SSunnySrivastava1984 4596169de2cSBrad Bishop if (sparePartNumber != nullptr && !sparePartNumber->empty()) 460cba4f448SSunnySrivastava1984 { 461ac106bf6SEd Tanous asyncResp->res.jsonValue["SparePartNumber"] = *sparePartNumber; 462cba4f448SSunnySrivastava1984 } 463351053f2SKrzysztof Grobelny }); 464ac6a4445SGunnar Mills } 465ac6a4445SGunnar Mills 466ac106bf6SEd Tanous inline void getCpuRevisionData(std::shared_ptr<bmcweb::AsyncResp> asyncResp, 467ac6a4445SGunnar Mills const std::string& service, 468ac6a4445SGunnar Mills const std::string& objPath) 469ac6a4445SGunnar Mills { 47062598e31SEd Tanous BMCWEB_LOG_DEBUG("Get Cpu Revision Data"); 471351053f2SKrzysztof Grobelny sdbusplus::asio::getAllProperties( 472351053f2SKrzysztof Grobelny *crow::connections::systemBus, service, objPath, 473351053f2SKrzysztof Grobelny "xyz.openbmc_project.Inventory.Decorator.Revision", 474ac106bf6SEd Tanous [objPath, asyncResp{std::move(asyncResp)}]( 4755e7e2dc5SEd Tanous const boost::system::error_code& ec, 476351053f2SKrzysztof Grobelny const dbus::utility::DBusPropertiesMap& properties) { 477ac6a4445SGunnar Mills if (ec) 478ac6a4445SGunnar Mills { 47962598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error"); 480ac106bf6SEd Tanous messages::internalError(asyncResp->res); 481ac6a4445SGunnar Mills return; 482ac6a4445SGunnar Mills } 483ac6a4445SGunnar Mills 484351053f2SKrzysztof Grobelny const std::string* version = nullptr; 485351053f2SKrzysztof Grobelny 486351053f2SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 487351053f2SKrzysztof Grobelny dbus_utils::UnpackErrorPrinter(), properties, "Version", version); 488351053f2SKrzysztof Grobelny 489351053f2SKrzysztof Grobelny if (!success) 490ac6a4445SGunnar Mills { 491ac106bf6SEd Tanous messages::internalError(asyncResp->res); 492351053f2SKrzysztof Grobelny return; 493351053f2SKrzysztof Grobelny } 494351053f2SKrzysztof Grobelny 495351053f2SKrzysztof Grobelny if (version != nullptr) 496ac6a4445SGunnar Mills { 497ac106bf6SEd Tanous asyncResp->res.jsonValue["Version"] = *version; 498ac6a4445SGunnar Mills } 499351053f2SKrzysztof Grobelny }); 500ac6a4445SGunnar Mills } 501ac6a4445SGunnar Mills 5028d1b46d7Szhanghch05 inline void getAcceleratorDataByService( 503ac106bf6SEd Tanous std::shared_ptr<bmcweb::AsyncResp> asyncResp, const std::string& acclrtrId, 5048d1b46d7Szhanghch05 const std::string& service, const std::string& objPath) 505ac6a4445SGunnar Mills { 50662598e31SEd Tanous BMCWEB_LOG_DEBUG("Get available system Accelerator resources by service."); 507351053f2SKrzysztof Grobelny sdbusplus::asio::getAllProperties( 508351053f2SKrzysztof Grobelny *crow::connections::systemBus, service, objPath, "", 509ac106bf6SEd Tanous [acclrtrId, asyncResp{std::move(asyncResp)}]( 5105e7e2dc5SEd Tanous const boost::system::error_code& ec, 511351053f2SKrzysztof Grobelny const dbus::utility::DBusPropertiesMap& properties) { 512ac6a4445SGunnar Mills if (ec) 513ac6a4445SGunnar Mills { 51462598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error"); 515ac106bf6SEd Tanous messages::internalError(asyncResp->res); 516ac6a4445SGunnar Mills return; 517ac6a4445SGunnar Mills } 518ac6a4445SGunnar Mills 519351053f2SKrzysztof Grobelny const bool* functional = nullptr; 520351053f2SKrzysztof Grobelny const bool* present = nullptr; 521351053f2SKrzysztof Grobelny 522351053f2SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 523351053f2SKrzysztof Grobelny dbus_utils::UnpackErrorPrinter(), properties, "Functional", 524351053f2SKrzysztof Grobelny functional, "Present", present); 525351053f2SKrzysztof Grobelny 526351053f2SKrzysztof Grobelny if (!success) 527ac6a4445SGunnar Mills { 528ac106bf6SEd Tanous messages::internalError(asyncResp->res); 529351053f2SKrzysztof Grobelny return; 530ac6a4445SGunnar Mills } 531ac6a4445SGunnar Mills 532ac6a4445SGunnar Mills std::string state = "Enabled"; 533ac6a4445SGunnar Mills std::string health = "OK"; 534ac6a4445SGunnar Mills 535351053f2SKrzysztof Grobelny if (present != nullptr && !*present) 536ac6a4445SGunnar Mills { 537ac6a4445SGunnar Mills state = "Absent"; 538ac6a4445SGunnar Mills } 539ac6a4445SGunnar Mills 540351053f2SKrzysztof Grobelny if (functional != nullptr && !*functional) 541ac6a4445SGunnar Mills { 542ac6a4445SGunnar Mills if (state == "Enabled") 543ac6a4445SGunnar Mills { 544ac6a4445SGunnar Mills health = "Critical"; 545ac6a4445SGunnar Mills } 546ac6a4445SGunnar Mills } 547ac6a4445SGunnar Mills 548ac106bf6SEd Tanous asyncResp->res.jsonValue["Id"] = acclrtrId; 549ac106bf6SEd Tanous asyncResp->res.jsonValue["Name"] = "Processor"; 550ac106bf6SEd Tanous asyncResp->res.jsonValue["Status"]["State"] = state; 551ac106bf6SEd Tanous asyncResp->res.jsonValue["Status"]["Health"] = health; 552ac106bf6SEd Tanous asyncResp->res.jsonValue["ProcessorType"] = "Accelerator"; 553351053f2SKrzysztof Grobelny }); 554ac6a4445SGunnar Mills } 555ac6a4445SGunnar Mills 556dba0c291SJonathan Doman // OperatingConfig D-Bus Types 557dba0c291SJonathan Doman using TurboProfileProperty = std::vector<std::tuple<uint32_t, size_t>>; 558dba0c291SJonathan Doman using BaseSpeedPrioritySettingsProperty = 559dba0c291SJonathan Doman std::vector<std::tuple<uint32_t, std::vector<uint32_t>>>; 560dba0c291SJonathan Doman // uint32_t and size_t may or may not be the same type, requiring a dedup'd 561dba0c291SJonathan Doman // variant 562dba0c291SJonathan Doman 563dba0c291SJonathan Doman /** 564dba0c291SJonathan Doman * Fill out the HighSpeedCoreIDs in a Processor resource from the given 565dba0c291SJonathan Doman * OperatingConfig D-Bus property. 566dba0c291SJonathan Doman * 567ac106bf6SEd Tanous * @param[in,out] asyncResp Async HTTP response. 568dba0c291SJonathan Doman * @param[in] baseSpeedSettings Full list of base speed priority groups, 569dba0c291SJonathan Doman * to use to determine the list of high 570dba0c291SJonathan Doman * speed cores. 571dba0c291SJonathan Doman */ 572dba0c291SJonathan Doman inline void highSpeedCoreIdsHandler( 573ac106bf6SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 574dba0c291SJonathan Doman const BaseSpeedPrioritySettingsProperty& baseSpeedSettings) 575dba0c291SJonathan Doman { 576dba0c291SJonathan Doman // The D-Bus property does not indicate which bucket is the "high 577dba0c291SJonathan Doman // priority" group, so let's discern that by looking for the one with 578dba0c291SJonathan Doman // highest base frequency. 579dba0c291SJonathan Doman auto highPriorityGroup = baseSpeedSettings.cend(); 580dba0c291SJonathan Doman uint32_t highestBaseSpeed = 0; 581dba0c291SJonathan Doman for (auto it = baseSpeedSettings.cbegin(); it != baseSpeedSettings.cend(); 582dba0c291SJonathan Doman ++it) 583dba0c291SJonathan Doman { 584dba0c291SJonathan Doman const uint32_t baseFreq = std::get<uint32_t>(*it); 585dba0c291SJonathan Doman if (baseFreq > highestBaseSpeed) 586dba0c291SJonathan Doman { 587dba0c291SJonathan Doman highestBaseSpeed = baseFreq; 588dba0c291SJonathan Doman highPriorityGroup = it; 589dba0c291SJonathan Doman } 590dba0c291SJonathan Doman } 591dba0c291SJonathan Doman 592ac106bf6SEd Tanous nlohmann::json& jsonCoreIds = asyncResp->res.jsonValue["HighSpeedCoreIDs"]; 593dba0c291SJonathan Doman jsonCoreIds = nlohmann::json::array(); 594dba0c291SJonathan Doman 595dba0c291SJonathan Doman // There may not be any entries in the D-Bus property, so only populate 596dba0c291SJonathan Doman // if there was actually something there. 597dba0c291SJonathan Doman if (highPriorityGroup != baseSpeedSettings.cend()) 598dba0c291SJonathan Doman { 599dba0c291SJonathan Doman jsonCoreIds = std::get<std::vector<uint32_t>>(*highPriorityGroup); 600dba0c291SJonathan Doman } 601dba0c291SJonathan Doman } 602dba0c291SJonathan Doman 603dba0c291SJonathan Doman /** 604dba0c291SJonathan Doman * Fill out OperatingConfig related items in a Processor resource by requesting 605dba0c291SJonathan Doman * data from the given D-Bus object. 606dba0c291SJonathan Doman * 607ac106bf6SEd Tanous * @param[in,out] asyncResp Async HTTP response. 608dba0c291SJonathan Doman * @param[in] cpuId CPU D-Bus name. 609dba0c291SJonathan Doman * @param[in] service D-Bus service to query. 610dba0c291SJonathan Doman * @param[in] objPath D-Bus object to query. 611dba0c291SJonathan Doman */ 612ac106bf6SEd Tanous inline void 613ac106bf6SEd Tanous getCpuConfigData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 614ac106bf6SEd Tanous const std::string& cpuId, const std::string& service, 615dba0c291SJonathan Doman const std::string& objPath) 616dba0c291SJonathan Doman { 61762598e31SEd Tanous BMCWEB_LOG_INFO("Getting CPU operating configs for {}", cpuId); 618dba0c291SJonathan Doman 619dba0c291SJonathan Doman // First, GetAll CurrentOperatingConfig properties on the object 620351053f2SKrzysztof Grobelny sdbusplus::asio::getAllProperties( 621351053f2SKrzysztof Grobelny *crow::connections::systemBus, service, objPath, 622351053f2SKrzysztof Grobelny "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig", 623ac106bf6SEd Tanous [asyncResp, cpuId, 6245e7e2dc5SEd Tanous service](const boost::system::error_code& ec, 625351053f2SKrzysztof Grobelny const dbus::utility::DBusPropertiesMap& properties) { 626dba0c291SJonathan Doman if (ec) 627dba0c291SJonathan Doman { 62862598e31SEd Tanous BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec, ec.message()); 629ac106bf6SEd Tanous messages::internalError(asyncResp->res); 630dba0c291SJonathan Doman return; 631dba0c291SJonathan Doman } 632dba0c291SJonathan Doman 633ac106bf6SEd Tanous nlohmann::json& json = asyncResp->res.jsonValue; 634dba0c291SJonathan Doman 635351053f2SKrzysztof Grobelny const sdbusplus::message::object_path* appliedConfig = nullptr; 636351053f2SKrzysztof Grobelny const bool* baseSpeedPriorityEnabled = nullptr; 637351053f2SKrzysztof Grobelny 638351053f2SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 639351053f2SKrzysztof Grobelny dbus_utils::UnpackErrorPrinter(), properties, "AppliedConfig", 640351053f2SKrzysztof Grobelny appliedConfig, "BaseSpeedPriorityEnabled", 641351053f2SKrzysztof Grobelny baseSpeedPriorityEnabled); 642351053f2SKrzysztof Grobelny 643351053f2SKrzysztof Grobelny if (!success) 644dba0c291SJonathan Doman { 645ac106bf6SEd Tanous messages::internalError(asyncResp->res); 646351053f2SKrzysztof Grobelny return; 647dba0c291SJonathan Doman } 648dba0c291SJonathan Doman 649351053f2SKrzysztof Grobelny if (appliedConfig != nullptr) 650351053f2SKrzysztof Grobelny { 651351053f2SKrzysztof Grobelny const std::string& dbusPath = appliedConfig->str; 6521476687dSEd Tanous nlohmann::json::object_t operatingConfig; 653ef4c65b7SEd Tanous operatingConfig["@odata.id"] = boost::urls::format( 654ef4c65b7SEd Tanous "/redfish/v1/Systems/system/Processors/{}/OperatingConfigs", 655ef4c65b7SEd Tanous cpuId); 6561476687dSEd Tanous json["OperatingConfigs"] = std::move(operatingConfig); 657dba0c291SJonathan Doman 658dba0c291SJonathan Doman // Reuse the D-Bus config object name for the Redfish 659dba0c291SJonathan Doman // URI 660dba0c291SJonathan Doman size_t baseNamePos = dbusPath.rfind('/'); 661dba0c291SJonathan Doman if (baseNamePos == std::string::npos || 662dba0c291SJonathan Doman baseNamePos == (dbusPath.size() - 1)) 663dba0c291SJonathan Doman { 664dba0c291SJonathan Doman // If the AppliedConfig was somehow not a valid path, 665dba0c291SJonathan Doman // skip adding any more properties, since everything 666dba0c291SJonathan Doman // else is tied to this applied config. 667ac106bf6SEd Tanous messages::internalError(asyncResp->res); 668351053f2SKrzysztof Grobelny return; 669dba0c291SJonathan Doman } 6701476687dSEd Tanous nlohmann::json::object_t appliedOperatingConfig; 671ef4c65b7SEd Tanous appliedOperatingConfig["@odata.id"] = boost::urls::format( 672ef4c65b7SEd Tanous "/redfish/v1/Systems/system/Processors/{}/OperatingConfigs/{}", 673ef4c65b7SEd Tanous cpuId, dbusPath.substr(baseNamePos + 1)); 674351053f2SKrzysztof Grobelny json["AppliedOperatingConfig"] = std::move(appliedOperatingConfig); 675dba0c291SJonathan Doman 676dba0c291SJonathan Doman // Once we found the current applied config, queue another 677dba0c291SJonathan Doman // request to read the base freq core ids out of that 678dba0c291SJonathan Doman // config. 679002d39b4SEd Tanous sdbusplus::asio::getProperty<BaseSpeedPrioritySettingsProperty>( 6801e1e598dSJonathan Doman *crow::connections::systemBus, service, dbusPath, 6811e1e598dSJonathan Doman "xyz.openbmc_project.Inventory.Item.Cpu." 6821e1e598dSJonathan Doman "OperatingConfig", 6831e1e598dSJonathan Doman "BaseSpeedPrioritySettings", 684ac106bf6SEd Tanous [asyncResp]( 6855e7e2dc5SEd Tanous const boost::system::error_code& ec2, 686351053f2SKrzysztof Grobelny const BaseSpeedPrioritySettingsProperty& baseSpeedList) { 6878a592810SEd Tanous if (ec2) 688dba0c291SJonathan Doman { 68962598e31SEd Tanous BMCWEB_LOG_WARNING("D-Bus Property Get error: {}", ec2); 690ac106bf6SEd Tanous messages::internalError(asyncResp->res); 691dba0c291SJonathan Doman return; 692dba0c291SJonathan Doman } 6931e1e598dSJonathan Doman 694ac106bf6SEd Tanous highSpeedCoreIdsHandler(asyncResp, baseSpeedList); 6951e1e598dSJonathan Doman }); 696dba0c291SJonathan Doman } 697351053f2SKrzysztof Grobelny 698351053f2SKrzysztof Grobelny if (baseSpeedPriorityEnabled != nullptr) 699dba0c291SJonathan Doman { 700dba0c291SJonathan Doman json["BaseSpeedPriorityState"] = 701351053f2SKrzysztof Grobelny *baseSpeedPriorityEnabled ? "Enabled" : "Disabled"; 702dba0c291SJonathan Doman } 703351053f2SKrzysztof Grobelny }); 704dba0c291SJonathan Doman } 705dba0c291SJonathan Doman 706cba4f448SSunnySrivastava1984 /** 707cba4f448SSunnySrivastava1984 * @brief Fill out location info of a processor by 708cba4f448SSunnySrivastava1984 * requesting data from the given D-Bus object. 709cba4f448SSunnySrivastava1984 * 710ac106bf6SEd Tanous * @param[in,out] asyncResp Async HTTP response. 711cba4f448SSunnySrivastava1984 * @param[in] service D-Bus service to query. 712cba4f448SSunnySrivastava1984 * @param[in] objPath D-Bus object to query. 713cba4f448SSunnySrivastava1984 */ 714ac106bf6SEd Tanous inline void getCpuLocationCode(std::shared_ptr<bmcweb::AsyncResp> asyncResp, 715cba4f448SSunnySrivastava1984 const std::string& service, 716cba4f448SSunnySrivastava1984 const std::string& objPath) 717cba4f448SSunnySrivastava1984 { 71862598e31SEd Tanous BMCWEB_LOG_DEBUG("Get Cpu Location Data"); 7191e1e598dSJonathan Doman sdbusplus::asio::getProperty<std::string>( 7201e1e598dSJonathan Doman *crow::connections::systemBus, service, objPath, 7211e1e598dSJonathan Doman "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode", 722ac106bf6SEd Tanous [objPath, asyncResp{std::move(asyncResp)}]( 723ac106bf6SEd Tanous const boost::system::error_code& ec, const std::string& property) { 724cba4f448SSunnySrivastava1984 if (ec) 725cba4f448SSunnySrivastava1984 { 72662598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error"); 727ac106bf6SEd Tanous messages::internalError(asyncResp->res); 728cba4f448SSunnySrivastava1984 return; 729cba4f448SSunnySrivastava1984 } 730cba4f448SSunnySrivastava1984 731ac106bf6SEd Tanous asyncResp->res.jsonValue["Location"]["PartLocation"]["ServiceLabel"] = 7321e1e598dSJonathan Doman property; 7331e1e598dSJonathan Doman }); 734cba4f448SSunnySrivastava1984 } 735cba4f448SSunnySrivastava1984 736c951448aSJonathan Doman /** 73749e429caSJonathan Doman * Populate the unique identifier in a Processor resource by requesting data 73849e429caSJonathan Doman * from the given D-Bus object. 73949e429caSJonathan Doman * 740ac106bf6SEd Tanous * @param[in,out] asyncResp Async HTTP response. 74149e429caSJonathan Doman * @param[in] service D-Bus service to query. 74249e429caSJonathan Doman * @param[in] objPath D-Bus object to query. 74349e429caSJonathan Doman */ 744ac106bf6SEd Tanous inline void getCpuUniqueId(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 74549e429caSJonathan Doman const std::string& service, 74649e429caSJonathan Doman const std::string& objectPath) 74749e429caSJonathan Doman { 74862598e31SEd Tanous BMCWEB_LOG_DEBUG("Get CPU UniqueIdentifier"); 7491e1e598dSJonathan Doman sdbusplus::asio::getProperty<std::string>( 7501e1e598dSJonathan Doman *crow::connections::systemBus, service, objectPath, 7511e1e598dSJonathan Doman "xyz.openbmc_project.Inventory.Decorator.UniqueIdentifier", 7521e1e598dSJonathan Doman "UniqueIdentifier", 753ac106bf6SEd Tanous [asyncResp](const boost::system::error_code& ec, 754ac106bf6SEd Tanous const std::string& id) { 7551e1e598dSJonathan Doman if (ec) 75649e429caSJonathan Doman { 75762598e31SEd Tanous BMCWEB_LOG_ERROR("Failed to read cpu unique id: {}", ec); 758ac106bf6SEd Tanous messages::internalError(asyncResp->res); 75949e429caSJonathan Doman return; 76049e429caSJonathan Doman } 761ac106bf6SEd Tanous asyncResp->res 762ac106bf6SEd Tanous .jsonValue["ProcessorId"]["ProtectedIdentificationNumber"] = id; 7631e1e598dSJonathan Doman }); 76449e429caSJonathan Doman } 76549e429caSJonathan Doman 76649e429caSJonathan Doman /** 767c951448aSJonathan Doman * Find the D-Bus object representing the requested Processor, and call the 768c951448aSJonathan Doman * handler with the results. If matching object is not found, add 404 error to 769c951448aSJonathan Doman * response and don't call the handler. 770c951448aSJonathan Doman * 771c951448aSJonathan Doman * @param[in,out] resp Async HTTP response. 772c951448aSJonathan Doman * @param[in] processorId Redfish Processor Id. 773c951448aSJonathan Doman * @param[in] handler Callback to continue processing request upon 774c951448aSJonathan Doman * successfully finding object. 775c951448aSJonathan Doman */ 776c951448aSJonathan Doman template <typename Handler> 7778d1b46d7Szhanghch05 inline void getProcessorObject(const std::shared_ptr<bmcweb::AsyncResp>& resp, 778c951448aSJonathan Doman const std::string& processorId, 779c951448aSJonathan Doman Handler&& handler) 780ac6a4445SGunnar Mills { 78162598e31SEd Tanous BMCWEB_LOG_DEBUG("Get available system processor resources."); 782ac6a4445SGunnar Mills 783c951448aSJonathan Doman // GetSubTree on all interfaces which provide info about a Processor 784dfbf7de5SChris Cain constexpr std::array<std::string_view, 9> interfaces = { 785e99073f5SGeorge Liu "xyz.openbmc_project.Common.UUID", 786e99073f5SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.Asset", 787e99073f5SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.Revision", 788e99073f5SGeorge Liu "xyz.openbmc_project.Inventory.Item.Cpu", 789e99073f5SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.LocationCode", 790e99073f5SGeorge Liu "xyz.openbmc_project.Inventory.Item.Accelerator", 791e99073f5SGeorge Liu "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig", 792dfbf7de5SChris Cain "xyz.openbmc_project.Inventory.Decorator.UniqueIdentifier", 793dfbf7de5SChris Cain "xyz.openbmc_project.Control.Power.Throttle"}; 794e99073f5SGeorge Liu dbus::utility::getSubTree( 795e99073f5SGeorge Liu "/xyz/openbmc_project/inventory", 0, interfaces, 796c951448aSJonathan Doman [resp, processorId, handler = std::forward<Handler>(handler)]( 797e99073f5SGeorge Liu const boost::system::error_code& ec, 798e99073f5SGeorge Liu const dbus::utility::MapperGetSubTreeResponse& subtree) { 799ac6a4445SGunnar Mills if (ec) 800ac6a4445SGunnar Mills { 80162598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error: {}", ec); 802c951448aSJonathan Doman messages::internalError(resp->res); 803ac6a4445SGunnar Mills return; 804ac6a4445SGunnar Mills } 8052bab9831SJonathan Doman for (const auto& [objectPath, serviceMap] : subtree) 806ac6a4445SGunnar Mills { 8072bab9831SJonathan Doman // Ignore any objects which don't end with our desired cpu name 80811ba3979SEd Tanous if (!objectPath.ends_with(processorId)) 809ac6a4445SGunnar Mills { 8102bab9831SJonathan Doman continue; 811ac6a4445SGunnar Mills } 8122bab9831SJonathan Doman 813c951448aSJonathan Doman bool found = false; 814c951448aSJonathan Doman // Filter out objects that don't have the CPU-specific 815c951448aSJonathan Doman // interfaces to make sure we can return 404 on non-CPUs 816c951448aSJonathan Doman // (e.g. /redfish/../Processors/dimm0) 8172bab9831SJonathan Doman for (const auto& [serviceName, interfaceList] : serviceMap) 818ac6a4445SGunnar Mills { 8193544d2a7SEd Tanous if (std::ranges::find_first_of(interfaceList, 8203544d2a7SEd Tanous processorInterfaces) != 8213544d2a7SEd Tanous std::end(interfaceList)) 8222bab9831SJonathan Doman { 823c951448aSJonathan Doman found = true; 824c951448aSJonathan Doman break; 825c951448aSJonathan Doman } 826c951448aSJonathan Doman } 827c951448aSJonathan Doman 828c951448aSJonathan Doman if (!found) 8292bab9831SJonathan Doman { 830c951448aSJonathan Doman continue; 831ac6a4445SGunnar Mills } 832c951448aSJonathan Doman 833c951448aSJonathan Doman // Process the first object which does match our cpu name and 834c951448aSJonathan Doman // required interfaces, and potentially ignore any other 835c951448aSJonathan Doman // matching objects. Assume all interfaces we want to process 836c951448aSJonathan Doman // must be on the same object path. 837c951448aSJonathan Doman 8388a592810SEd Tanous handler(objectPath, serviceMap); 839ac6a4445SGunnar Mills return; 840ac6a4445SGunnar Mills } 841c951448aSJonathan Doman messages::resourceNotFound(resp->res, "Processor", processorId); 842e99073f5SGeorge Liu }); 843ac6a4445SGunnar Mills } 844ac6a4445SGunnar Mills 845ac106bf6SEd Tanous inline void 846ac106bf6SEd Tanous getProcessorData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 847c951448aSJonathan Doman const std::string& processorId, 848c951448aSJonathan Doman const std::string& objectPath, 8495df6eda2SShantappa Teekappanavar const dbus::utility::MapperServiceMap& serviceMap) 850c951448aSJonathan Doman { 851c951448aSJonathan Doman for (const auto& [serviceName, interfaceList] : serviceMap) 852c951448aSJonathan Doman { 853c951448aSJonathan Doman for (const auto& interface : interfaceList) 854c951448aSJonathan Doman { 855c951448aSJonathan Doman if (interface == "xyz.openbmc_project.Inventory.Decorator.Asset") 856c951448aSJonathan Doman { 857ac106bf6SEd Tanous getCpuAssetData(asyncResp, serviceName, objectPath); 858c951448aSJonathan Doman } 8590fda0f12SGeorge Liu else if (interface == 8600fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.Revision") 861c951448aSJonathan Doman { 862ac106bf6SEd Tanous getCpuRevisionData(asyncResp, serviceName, objectPath); 863c951448aSJonathan Doman } 864c951448aSJonathan Doman else if (interface == "xyz.openbmc_project.Inventory.Item.Cpu") 865c951448aSJonathan Doman { 866ac106bf6SEd Tanous getCpuDataByService(asyncResp, processorId, serviceName, 867c951448aSJonathan Doman objectPath); 868c951448aSJonathan Doman } 8690fda0f12SGeorge Liu else if (interface == 8700fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Item.Accelerator") 871c951448aSJonathan Doman { 872ac106bf6SEd Tanous getAcceleratorDataByService(asyncResp, processorId, serviceName, 873c951448aSJonathan Doman objectPath); 874c951448aSJonathan Doman } 8750fda0f12SGeorge Liu else if ( 8760fda0f12SGeorge Liu interface == 8770fda0f12SGeorge Liu "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig") 878c951448aSJonathan Doman { 879ac106bf6SEd Tanous getCpuConfigData(asyncResp, processorId, serviceName, 880ac106bf6SEd Tanous objectPath); 881c951448aSJonathan Doman } 8820fda0f12SGeorge Liu else if (interface == 8830fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.LocationCode") 884c951448aSJonathan Doman { 885ac106bf6SEd Tanous getCpuLocationCode(asyncResp, serviceName, objectPath); 886c951448aSJonathan Doman } 88771b82f26SSharad Yadav else if (interface == "xyz.openbmc_project.Common.UUID") 88871b82f26SSharad Yadav { 889ac106bf6SEd Tanous getProcessorUUID(asyncResp, serviceName, objectPath); 89071b82f26SSharad Yadav } 8910fda0f12SGeorge Liu else if (interface == 8920fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.UniqueIdentifier") 89349e429caSJonathan Doman { 894ac106bf6SEd Tanous getCpuUniqueId(asyncResp, serviceName, objectPath); 89549e429caSJonathan Doman } 896dfbf7de5SChris Cain else if (interface == "xyz.openbmc_project.Control.Power.Throttle") 897dfbf7de5SChris Cain { 898ac106bf6SEd Tanous getThrottleProperties(asyncResp, serviceName, objectPath); 899dfbf7de5SChris Cain } 900c951448aSJonathan Doman } 901c951448aSJonathan Doman } 902c951448aSJonathan Doman } 903c951448aSJonathan Doman 904dba0c291SJonathan Doman /** 905dba0c291SJonathan Doman * Request all the properties for the given D-Bus object and fill out the 906dba0c291SJonathan Doman * related entries in the Redfish OperatingConfig response. 907dba0c291SJonathan Doman * 908ac106bf6SEd Tanous * @param[in,out] asyncResp Async HTTP response. 909dba0c291SJonathan Doman * @param[in] service D-Bus service name to query. 910dba0c291SJonathan Doman * @param[in] objPath D-Bus object to query. 911dba0c291SJonathan Doman */ 9128d1b46d7Szhanghch05 inline void 913ac106bf6SEd Tanous getOperatingConfigData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 914dba0c291SJonathan Doman const std::string& service, 915dba0c291SJonathan Doman const std::string& objPath) 916dba0c291SJonathan Doman { 917351053f2SKrzysztof Grobelny sdbusplus::asio::getAllProperties( 918351053f2SKrzysztof Grobelny *crow::connections::systemBus, service, objPath, 919351053f2SKrzysztof Grobelny "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig", 920ac106bf6SEd Tanous [asyncResp](const boost::system::error_code& ec, 921351053f2SKrzysztof Grobelny const dbus::utility::DBusPropertiesMap& properties) { 922dba0c291SJonathan Doman if (ec) 923dba0c291SJonathan Doman { 92462598e31SEd Tanous BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec, ec.message()); 925ac106bf6SEd Tanous messages::internalError(asyncResp->res); 926dba0c291SJonathan Doman return; 927dba0c291SJonathan Doman } 928dba0c291SJonathan Doman 929351053f2SKrzysztof Grobelny const size_t* availableCoreCount = nullptr; 930351053f2SKrzysztof Grobelny const uint32_t* baseSpeed = nullptr; 931351053f2SKrzysztof Grobelny const uint32_t* maxJunctionTemperature = nullptr; 932351053f2SKrzysztof Grobelny const uint32_t* maxSpeed = nullptr; 933351053f2SKrzysztof Grobelny const uint32_t* powerLimit = nullptr; 934351053f2SKrzysztof Grobelny const TurboProfileProperty* turboProfile = nullptr; 935351053f2SKrzysztof Grobelny const BaseSpeedPrioritySettingsProperty* baseSpeedPrioritySettings = 936351053f2SKrzysztof Grobelny nullptr; 937351053f2SKrzysztof Grobelny 938351053f2SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 939351053f2SKrzysztof Grobelny dbus_utils::UnpackErrorPrinter(), properties, "AvailableCoreCount", 940351053f2SKrzysztof Grobelny availableCoreCount, "BaseSpeed", baseSpeed, 941351053f2SKrzysztof Grobelny "MaxJunctionTemperature", maxJunctionTemperature, "MaxSpeed", 942351053f2SKrzysztof Grobelny maxSpeed, "PowerLimit", powerLimit, "TurboProfile", turboProfile, 943351053f2SKrzysztof Grobelny "BaseSpeedPrioritySettings", baseSpeedPrioritySettings); 944351053f2SKrzysztof Grobelny 945351053f2SKrzysztof Grobelny if (!success) 946dba0c291SJonathan Doman { 947ac106bf6SEd Tanous messages::internalError(asyncResp->res); 948351053f2SKrzysztof Grobelny return; 949dba0c291SJonathan Doman } 950dba0c291SJonathan Doman 951ac106bf6SEd Tanous nlohmann::json& json = asyncResp->res.jsonValue; 952351053f2SKrzysztof Grobelny 953351053f2SKrzysztof Grobelny if (availableCoreCount != nullptr) 954351053f2SKrzysztof Grobelny { 955351053f2SKrzysztof Grobelny json["TotalAvailableCoreCount"] = *availableCoreCount; 956351053f2SKrzysztof Grobelny } 957351053f2SKrzysztof Grobelny 958351053f2SKrzysztof Grobelny if (baseSpeed != nullptr) 959351053f2SKrzysztof Grobelny { 960351053f2SKrzysztof Grobelny json["BaseSpeedMHz"] = *baseSpeed; 961351053f2SKrzysztof Grobelny } 962351053f2SKrzysztof Grobelny 963351053f2SKrzysztof Grobelny if (maxJunctionTemperature != nullptr) 964351053f2SKrzysztof Grobelny { 965351053f2SKrzysztof Grobelny json["MaxJunctionTemperatureCelsius"] = *maxJunctionTemperature; 966351053f2SKrzysztof Grobelny } 967351053f2SKrzysztof Grobelny 968351053f2SKrzysztof Grobelny if (maxSpeed != nullptr) 969351053f2SKrzysztof Grobelny { 970351053f2SKrzysztof Grobelny json["MaxSpeedMHz"] = *maxSpeed; 971351053f2SKrzysztof Grobelny } 972351053f2SKrzysztof Grobelny 973351053f2SKrzysztof Grobelny if (powerLimit != nullptr) 974351053f2SKrzysztof Grobelny { 975351053f2SKrzysztof Grobelny json["TDPWatts"] = *powerLimit; 976351053f2SKrzysztof Grobelny } 977351053f2SKrzysztof Grobelny 978351053f2SKrzysztof Grobelny if (turboProfile != nullptr) 979351053f2SKrzysztof Grobelny { 980dba0c291SJonathan Doman nlohmann::json& turboArray = json["TurboProfile"]; 981dba0c291SJonathan Doman turboArray = nlohmann::json::array(); 982351053f2SKrzysztof Grobelny for (const auto& [turboSpeed, coreCount] : *turboProfile) 983dba0c291SJonathan Doman { 9841476687dSEd Tanous nlohmann::json::object_t turbo; 9851476687dSEd Tanous turbo["ActiveCoreCount"] = coreCount; 9861476687dSEd Tanous turbo["MaxSpeedMHz"] = turboSpeed; 987b2ba3072SPatrick Williams turboArray.emplace_back(std::move(turbo)); 988dba0c291SJonathan Doman } 989dba0c291SJonathan Doman } 990dba0c291SJonathan Doman 991351053f2SKrzysztof Grobelny if (baseSpeedPrioritySettings != nullptr) 992351053f2SKrzysztof Grobelny { 993351053f2SKrzysztof Grobelny nlohmann::json& baseSpeedArray = json["BaseSpeedPrioritySettings"]; 994dba0c291SJonathan Doman baseSpeedArray = nlohmann::json::array(); 995351053f2SKrzysztof Grobelny for (const auto& [baseSpeedMhz, coreList] : 996351053f2SKrzysztof Grobelny *baseSpeedPrioritySettings) 997dba0c291SJonathan Doman { 9981476687dSEd Tanous nlohmann::json::object_t speed; 9991476687dSEd Tanous speed["CoreCount"] = coreList.size(); 10001476687dSEd Tanous speed["CoreIDs"] = coreList; 1001351053f2SKrzysztof Grobelny speed["BaseSpeedMHz"] = baseSpeedMhz; 1002b2ba3072SPatrick Williams baseSpeedArray.emplace_back(std::move(speed)); 1003dba0c291SJonathan Doman } 1004dba0c291SJonathan Doman } 1005351053f2SKrzysztof Grobelny }); 1006dba0c291SJonathan Doman } 1007dba0c291SJonathan Doman 10083cde86f1SJonathan Doman /** 10093cde86f1SJonathan Doman * Handle the D-Bus response from attempting to set the CPU's AppliedConfig 10103cde86f1SJonathan Doman * property. Main task is to translate error messages into Redfish errors. 10113cde86f1SJonathan Doman * 10123cde86f1SJonathan Doman * @param[in,out] resp HTTP response. 10133cde86f1SJonathan Doman * @param[in] setPropVal Value which we attempted to set. 10143cde86f1SJonathan Doman * @param[in] ec D-Bus response error code. 10153cde86f1SJonathan Doman * @param[in] msg D-Bus response message. 10163cde86f1SJonathan Doman */ 10173cde86f1SJonathan Doman inline void 10183cde86f1SJonathan Doman handleAppliedConfigResponse(const std::shared_ptr<bmcweb::AsyncResp>& resp, 10193cde86f1SJonathan Doman const std::string& setPropVal, 10205e7e2dc5SEd Tanous const boost::system::error_code& ec, 102159d494eeSPatrick Williams const sdbusplus::message_t& msg) 10223cde86f1SJonathan Doman { 10233cde86f1SJonathan Doman if (!ec) 10243cde86f1SJonathan Doman { 102562598e31SEd Tanous BMCWEB_LOG_DEBUG("Set Property succeeded"); 10263cde86f1SJonathan Doman return; 10273cde86f1SJonathan Doman } 10283cde86f1SJonathan Doman 102962598e31SEd Tanous BMCWEB_LOG_DEBUG("Set Property failed: {}", ec); 10303cde86f1SJonathan Doman 10313cde86f1SJonathan Doman const sd_bus_error* dbusError = msg.get_error(); 10323cde86f1SJonathan Doman if (dbusError == nullptr) 10333cde86f1SJonathan Doman { 10343cde86f1SJonathan Doman messages::internalError(resp->res); 10353cde86f1SJonathan Doman return; 10363cde86f1SJonathan Doman } 10373cde86f1SJonathan Doman 10383cde86f1SJonathan Doman // The asio error code doesn't know about our custom errors, so we have to 10393cde86f1SJonathan Doman // parse the error string. Some of these D-Bus -> Redfish translations are a 10403cde86f1SJonathan Doman // stretch, but it's good to try to communicate something vaguely useful. 10413cde86f1SJonathan Doman if (strcmp(dbusError->name, 10423cde86f1SJonathan Doman "xyz.openbmc_project.Common.Error.InvalidArgument") == 0) 10433cde86f1SJonathan Doman { 10443cde86f1SJonathan Doman // Service did not like the object_path we tried to set. 10453cde86f1SJonathan Doman messages::propertyValueIncorrect( 10463cde86f1SJonathan Doman resp->res, "AppliedOperatingConfig/@odata.id", setPropVal); 10473cde86f1SJonathan Doman } 10483cde86f1SJonathan Doman else if (strcmp(dbusError->name, 10493cde86f1SJonathan Doman "xyz.openbmc_project.Common.Error.NotAllowed") == 0) 10503cde86f1SJonathan Doman { 10513cde86f1SJonathan Doman // Service indicates we can never change the config for this processor. 10523cde86f1SJonathan Doman messages::propertyNotWritable(resp->res, "AppliedOperatingConfig"); 10533cde86f1SJonathan Doman } 10543cde86f1SJonathan Doman else if (strcmp(dbusError->name, 10553cde86f1SJonathan Doman "xyz.openbmc_project.Common.Error.Unavailable") == 0) 10563cde86f1SJonathan Doman { 10573cde86f1SJonathan Doman // Service indicates the config cannot be changed right now, but maybe 10583cde86f1SJonathan Doman // in a different system state. 10593cde86f1SJonathan Doman messages::resourceInStandby(resp->res); 10603cde86f1SJonathan Doman } 10613cde86f1SJonathan Doman else 10623cde86f1SJonathan Doman { 10633cde86f1SJonathan Doman messages::internalError(resp->res); 10643cde86f1SJonathan Doman } 10653cde86f1SJonathan Doman } 10663cde86f1SJonathan Doman 10673cde86f1SJonathan Doman /** 10683cde86f1SJonathan Doman * Handle the PATCH operation of the AppliedOperatingConfig property. Do basic 10693cde86f1SJonathan Doman * validation of the input data, and then set the D-Bus property. 10703cde86f1SJonathan Doman * 10713cde86f1SJonathan Doman * @param[in,out] resp Async HTTP response. 10723cde86f1SJonathan Doman * @param[in] processorId Processor's Id. 10733cde86f1SJonathan Doman * @param[in] appliedConfigUri New property value to apply. 10743cde86f1SJonathan Doman * @param[in] cpuObjectPath Path of CPU object to modify. 10753cde86f1SJonathan Doman * @param[in] serviceMap Service map for CPU object. 10763cde86f1SJonathan Doman */ 10773cde86f1SJonathan Doman inline void patchAppliedOperatingConfig( 10783cde86f1SJonathan Doman const std::shared_ptr<bmcweb::AsyncResp>& resp, 10793cde86f1SJonathan Doman const std::string& processorId, const std::string& appliedConfigUri, 10805df6eda2SShantappa Teekappanavar const std::string& cpuObjectPath, 10815df6eda2SShantappa Teekappanavar const dbus::utility::MapperServiceMap& serviceMap) 10823cde86f1SJonathan Doman { 10833cde86f1SJonathan Doman // Check that the property even exists by checking for the interface 10843cde86f1SJonathan Doman const std::string* controlService = nullptr; 10853cde86f1SJonathan Doman for (const auto& [serviceName, interfaceList] : serviceMap) 10863cde86f1SJonathan Doman { 10873544d2a7SEd Tanous if (std::ranges::find(interfaceList, 10883cde86f1SJonathan Doman "xyz.openbmc_project.Control.Processor." 10893cde86f1SJonathan Doman "CurrentOperatingConfig") != interfaceList.end()) 10903cde86f1SJonathan Doman { 10913cde86f1SJonathan Doman controlService = &serviceName; 10923cde86f1SJonathan Doman break; 10933cde86f1SJonathan Doman } 10943cde86f1SJonathan Doman } 10953cde86f1SJonathan Doman 10963cde86f1SJonathan Doman if (controlService == nullptr) 10973cde86f1SJonathan Doman { 10983cde86f1SJonathan Doman messages::internalError(resp->res); 10993cde86f1SJonathan Doman return; 11003cde86f1SJonathan Doman } 11013cde86f1SJonathan Doman 11023cde86f1SJonathan Doman // Check that the config URI is a child of the cpu URI being patched. 11033cde86f1SJonathan Doman std::string expectedPrefix("/redfish/v1/Systems/system/Processors/"); 11043cde86f1SJonathan Doman expectedPrefix += processorId; 11053cde86f1SJonathan Doman expectedPrefix += "/OperatingConfigs/"; 110611ba3979SEd Tanous if (!appliedConfigUri.starts_with(expectedPrefix) || 11073cde86f1SJonathan Doman expectedPrefix.size() == appliedConfigUri.size()) 11083cde86f1SJonathan Doman { 11093cde86f1SJonathan Doman messages::propertyValueIncorrect( 11103cde86f1SJonathan Doman resp->res, "AppliedOperatingConfig/@odata.id", appliedConfigUri); 11113cde86f1SJonathan Doman return; 11123cde86f1SJonathan Doman } 11133cde86f1SJonathan Doman 11143cde86f1SJonathan Doman // Generate the D-Bus path of the OperatingConfig object, by assuming it's a 11153cde86f1SJonathan Doman // direct child of the CPU object. 11163cde86f1SJonathan Doman // Strip the expectedPrefix from the config URI to get the "filename", and 11173cde86f1SJonathan Doman // append to the CPU's path. 11183cde86f1SJonathan Doman std::string configBaseName = appliedConfigUri.substr(expectedPrefix.size()); 11193cde86f1SJonathan Doman sdbusplus::message::object_path configPath(cpuObjectPath); 11203cde86f1SJonathan Doman configPath /= configBaseName; 11213cde86f1SJonathan Doman 112262598e31SEd Tanous BMCWEB_LOG_INFO("Setting config to {}", configPath.str); 11233cde86f1SJonathan Doman 11243cde86f1SJonathan Doman // Set the property, with handler to check error responses 11259ae226faSGeorge Liu sdbusplus::asio::setProperty( 11269ae226faSGeorge Liu *crow::connections::systemBus, *controlService, cpuObjectPath, 11279ae226faSGeorge Liu "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig", 11289ae226faSGeorge Liu "AppliedConfig", configPath, 11295e7e2dc5SEd Tanous [resp, appliedConfigUri](const boost::system::error_code& ec, 113059d494eeSPatrick Williams const sdbusplus::message_t& msg) { 11313cde86f1SJonathan Doman handleAppliedConfigResponse(resp, appliedConfigUri, ec, msg); 11329ae226faSGeorge Liu }); 11333cde86f1SJonathan Doman } 11343cde86f1SJonathan Doman 1135ac106bf6SEd Tanous inline void 1136ac106bf6SEd Tanous handleProcessorHead(crow::App& app, const crow::Request& req, 1137ac106bf6SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 113871a24ca4SNikhil Namjoshi const std::string& /* systemName */, 113971a24ca4SNikhil Namjoshi const std::string& /* processorId */) 114071a24ca4SNikhil Namjoshi { 1141ac106bf6SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 114271a24ca4SNikhil Namjoshi { 114371a24ca4SNikhil Namjoshi return; 114471a24ca4SNikhil Namjoshi } 1145ac106bf6SEd Tanous asyncResp->res.addHeader( 114671a24ca4SNikhil Namjoshi boost::beast::http::field::link, 114771a24ca4SNikhil Namjoshi "</redfish/v1/JsonSchemas/Processor/Processor.json>; rel=describedby"); 114871a24ca4SNikhil Namjoshi } 114971a24ca4SNikhil Namjoshi 115071a24ca4SNikhil Namjoshi inline void handleProcessorCollectionHead( 115171a24ca4SNikhil Namjoshi crow::App& app, const crow::Request& req, 1152ac106bf6SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 115371a24ca4SNikhil Namjoshi const std::string& /* systemName */) 115471a24ca4SNikhil Namjoshi { 1155ac106bf6SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 115671a24ca4SNikhil Namjoshi { 115771a24ca4SNikhil Namjoshi return; 115871a24ca4SNikhil Namjoshi } 1159ac106bf6SEd Tanous asyncResp->res.addHeader( 116071a24ca4SNikhil Namjoshi boost::beast::http::field::link, 116171a24ca4SNikhil Namjoshi "</redfish/v1/JsonSchemas/ProcessorCollection/ProcessorCollection.json>; rel=describedby"); 116271a24ca4SNikhil Namjoshi } 116371a24ca4SNikhil Namjoshi 11647e860f15SJohn Edward Broadbent inline void requestRoutesOperatingConfigCollection(App& app) 1165dba0c291SJonathan Doman { 11667f3e84a1SEd Tanous BMCWEB_ROUTE(app, 11677f3e84a1SEd Tanous "/redfish/v1/Systems/<str>/Processors/<str>/OperatingConfigs/") 1168ed398213SEd Tanous .privileges(redfish::privileges::getOperatingConfigCollection) 1169002d39b4SEd Tanous .methods(boost::beast::http::verb::get)( 1170002d39b4SEd Tanous [&app](const crow::Request& req, 117145ca1b86SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 11727f3e84a1SEd Tanous const std::string& systemName, const std::string& cpuName) { 11733ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 117445ca1b86SEd Tanous { 117545ca1b86SEd Tanous return; 117645ca1b86SEd Tanous } 11777f3e84a1SEd Tanous 11787f3e84a1SEd Tanous if constexpr (bmcwebEnableMultiHost) 11797f3e84a1SEd Tanous { 11807f3e84a1SEd Tanous // Option currently returns no systems. TBD 11817f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 11827f3e84a1SEd Tanous systemName); 11837f3e84a1SEd Tanous return; 11847f3e84a1SEd Tanous } 11857f3e84a1SEd Tanous 11867f3e84a1SEd Tanous if (systemName != "system") 11877f3e84a1SEd Tanous { 11887f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 11897f3e84a1SEd Tanous systemName); 11907f3e84a1SEd Tanous return; 11917f3e84a1SEd Tanous } 11928d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.type"] = 1193dba0c291SJonathan Doman "#OperatingConfigCollection.OperatingConfigCollection"; 1194ef4c65b7SEd Tanous asyncResp->res.jsonValue["@odata.id"] = boost::urls::format( 1195ef4c65b7SEd Tanous "/redfish/v1/Systems/system/Processors/{}/OperatingConfigs", 1196ef4c65b7SEd Tanous cpuName); 11970fda0f12SGeorge Liu asyncResp->res.jsonValue["Name"] = "Operating Config Collection"; 1198dba0c291SJonathan Doman 11997e860f15SJohn Edward Broadbent // First find the matching CPU object so we know how to 12007e860f15SJohn Edward Broadbent // constrain our search for related Config objects. 12017a1dbc48SGeorge Liu const std::array<std::string_view, 1> interfaces = { 12027a1dbc48SGeorge Liu "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig"}; 12037a1dbc48SGeorge Liu dbus::utility::getSubTreePaths( 12047a1dbc48SGeorge Liu "/xyz/openbmc_project/inventory", 0, interfaces, 1205002d39b4SEd Tanous [asyncResp, cpuName]( 12067a1dbc48SGeorge Liu const boost::system::error_code& ec, 1207002d39b4SEd Tanous const dbus::utility::MapperGetSubTreePathsResponse& objects) { 1208dba0c291SJonathan Doman if (ec) 1209dba0c291SJonathan Doman { 121062598e31SEd Tanous BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec, ec.message()); 1211dba0c291SJonathan Doman messages::internalError(asyncResp->res); 1212dba0c291SJonathan Doman return; 1213dba0c291SJonathan Doman } 1214dba0c291SJonathan Doman 1215dba0c291SJonathan Doman for (const std::string& object : objects) 1216dba0c291SJonathan Doman { 121711ba3979SEd Tanous if (!object.ends_with(cpuName)) 1218dba0c291SJonathan Doman { 1219dba0c291SJonathan Doman continue; 1220dba0c291SJonathan Doman } 1221dba0c291SJonathan Doman 12227e860f15SJohn Edward Broadbent // Not expected that there will be multiple matching 12237e860f15SJohn Edward Broadbent // CPU objects, but if there are just use the first 12247e860f15SJohn Edward Broadbent // one. 1225dba0c291SJonathan Doman 12267e860f15SJohn Edward Broadbent // Use the common search routine to construct the 12277e860f15SJohn Edward Broadbent // Collection of all Config objects under this CPU. 12287a1dbc48SGeorge Liu constexpr std::array<std::string_view, 1> interface{ 12295a39f77aSPatrick Williams "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig"}; 1230dba0c291SJonathan Doman collection_util::getCollectionMembers( 1231dba0c291SJonathan Doman asyncResp, 1232ef4c65b7SEd Tanous boost::urls::format( 1233ef4c65b7SEd Tanous "/redfish/v1/Systems/system/Processors/{}/OperatingConfigs", 1234ef4c65b7SEd Tanous cpuName), 123536b5f1edSLakshmi Yadlapati interface, object); 1236dba0c291SJonathan Doman return; 1237dba0c291SJonathan Doman } 12387a1dbc48SGeorge Liu }); 12397e860f15SJohn Edward Broadbent }); 1240dba0c291SJonathan Doman } 1241dba0c291SJonathan Doman 12427e860f15SJohn Edward Broadbent inline void requestRoutesOperatingConfig(App& app) 1243dba0c291SJonathan Doman { 12447e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 12457e860f15SJohn Edward Broadbent app, 12467f3e84a1SEd Tanous "/redfish/v1/Systems/<str>/Processors/<str>/OperatingConfigs/<str>/") 1247ed398213SEd Tanous .privileges(redfish::privileges::getOperatingConfig) 1248002d39b4SEd Tanous .methods(boost::beast::http::verb::get)( 1249002d39b4SEd Tanous [&app](const crow::Request& req, 125045ca1b86SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 12517f3e84a1SEd Tanous const std::string& systemName, const std::string& cpuName, 12527f3e84a1SEd Tanous const std::string& configName) { 12533ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 125445ca1b86SEd Tanous { 125545ca1b86SEd Tanous return; 125645ca1b86SEd Tanous } 12577f3e84a1SEd Tanous if constexpr (bmcwebEnableMultiHost) 12587f3e84a1SEd Tanous { 12597f3e84a1SEd Tanous // Option currently returns no systems. TBD 12607f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 12617f3e84a1SEd Tanous systemName); 12627f3e84a1SEd Tanous return; 12637f3e84a1SEd Tanous } 12647f3e84a1SEd Tanous 12657f3e84a1SEd Tanous if (systemName != "system") 12667f3e84a1SEd Tanous { 12677f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 12687f3e84a1SEd Tanous systemName); 12697f3e84a1SEd Tanous return; 12707f3e84a1SEd Tanous } 12717e860f15SJohn Edward Broadbent // Ask for all objects implementing OperatingConfig so we can search 12727e860f15SJohn Edward Broadbent // for one with a matching name 1273e99073f5SGeorge Liu constexpr std::array<std::string_view, 1> interfaces = { 1274e99073f5SGeorge Liu "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig"}; 1275e99073f5SGeorge Liu dbus::utility::getSubTree( 1276e99073f5SGeorge Liu "/xyz/openbmc_project/inventory", 0, interfaces, 127739662a3bSEd Tanous [asyncResp, cpuName, configName]( 1278e99073f5SGeorge Liu const boost::system::error_code& ec, 12795df6eda2SShantappa Teekappanavar const dbus::utility::MapperGetSubTreeResponse& subtree) { 1280dba0c291SJonathan Doman if (ec) 1281dba0c291SJonathan Doman { 128262598e31SEd Tanous BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec, ec.message()); 1283dba0c291SJonathan Doman messages::internalError(asyncResp->res); 1284dba0c291SJonathan Doman return; 1285dba0c291SJonathan Doman } 1286002d39b4SEd Tanous const std::string expectedEnding = cpuName + '/' + configName; 1287dba0c291SJonathan Doman for (const auto& [objectPath, serviceMap] : subtree) 1288dba0c291SJonathan Doman { 1289dba0c291SJonathan Doman // Ignore any configs without matching cpuX/configY 129011ba3979SEd Tanous if (!objectPath.ends_with(expectedEnding) || serviceMap.empty()) 1291dba0c291SJonathan Doman { 1292dba0c291SJonathan Doman continue; 1293dba0c291SJonathan Doman } 1294dba0c291SJonathan Doman 1295dba0c291SJonathan Doman nlohmann::json& json = asyncResp->res.jsonValue; 1296002d39b4SEd Tanous json["@odata.type"] = "#OperatingConfig.v1_0_0.OperatingConfig"; 1297ef4c65b7SEd Tanous json["@odata.id"] = boost::urls::format( 1298ef4c65b7SEd Tanous "/redfish/v1/Systems/system/Processors/{}/OperatingConfigs/{}", 1299ef4c65b7SEd Tanous cpuName, configName); 1300dba0c291SJonathan Doman json["Name"] = "Processor Profile"; 1301dba0c291SJonathan Doman json["Id"] = configName; 1302dba0c291SJonathan Doman 1303dba0c291SJonathan Doman // Just use the first implementation of the object - not 13047e860f15SJohn Edward Broadbent // expected that there would be multiple matching 13057e860f15SJohn Edward Broadbent // services 1306002d39b4SEd Tanous getOperatingConfigData(asyncResp, serviceMap.begin()->first, 1307002d39b4SEd Tanous objectPath); 1308dba0c291SJonathan Doman return; 1309dba0c291SJonathan Doman } 1310002d39b4SEd Tanous messages::resourceNotFound(asyncResp->res, "OperatingConfig", 1311002d39b4SEd Tanous configName); 1312e99073f5SGeorge Liu }); 13137e860f15SJohn Edward Broadbent }); 1314ac6a4445SGunnar Mills } 1315ac6a4445SGunnar Mills 13167e860f15SJohn Edward Broadbent inline void requestRoutesProcessorCollection(App& app) 13177e860f15SJohn Edward Broadbent { 1318ac6a4445SGunnar Mills /** 1319ac6a4445SGunnar Mills * Functions triggers appropriate requests on DBus 1320ac6a4445SGunnar Mills */ 132122d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/") 132271a24ca4SNikhil Namjoshi .privileges(redfish::privileges::headProcessorCollection) 132371a24ca4SNikhil Namjoshi .methods(boost::beast::http::verb::head)( 132471a24ca4SNikhil Namjoshi std::bind_front(handleProcessorCollectionHead, std::ref(app))); 132571a24ca4SNikhil Namjoshi 132671a24ca4SNikhil Namjoshi BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/") 1327ed398213SEd Tanous .privileges(redfish::privileges::getProcessorCollection) 13287e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 132945ca1b86SEd Tanous [&app](const crow::Request& req, 133022d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 133122d268cbSEd Tanous const std::string& systemName) { 13323ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 133345ca1b86SEd Tanous { 133445ca1b86SEd Tanous return; 133545ca1b86SEd Tanous } 13367f3e84a1SEd Tanous if constexpr (bmcwebEnableMultiHost) 13377f3e84a1SEd Tanous { 13387f3e84a1SEd Tanous // Option currently returns no systems. TBD 13397f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 13407f3e84a1SEd Tanous systemName); 13417f3e84a1SEd Tanous return; 13427f3e84a1SEd Tanous } 13437f3e84a1SEd Tanous 134422d268cbSEd Tanous if (systemName != "system") 134522d268cbSEd Tanous { 134622d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 134722d268cbSEd Tanous systemName); 134822d268cbSEd Tanous return; 134922d268cbSEd Tanous } 135022d268cbSEd Tanous 135171a24ca4SNikhil Namjoshi asyncResp->res.addHeader( 135271a24ca4SNikhil Namjoshi boost::beast::http::field::link, 135371a24ca4SNikhil Namjoshi "</redfish/v1/JsonSchemas/ProcessorCollection/ProcessorCollection.json>; rel=describedby"); 135471a24ca4SNikhil Namjoshi 13558d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.type"] = 1356ac6a4445SGunnar Mills "#ProcessorCollection.ProcessorCollection"; 13578d1b46d7Szhanghch05 asyncResp->res.jsonValue["Name"] = "Processor Collection"; 1358ac6a4445SGunnar Mills 13598d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.id"] = 13608d1b46d7Szhanghch05 "/redfish/v1/Systems/system/Processors"; 1361ac6a4445SGunnar Mills 136205030b8eSGunnar Mills collection_util::getCollectionMembers( 1363ae9031f0SWilly Tu asyncResp, 1364ae9031f0SWilly Tu boost::urls::url("/redfish/v1/Systems/system/Processors"), 136536b5f1edSLakshmi Yadlapati processorInterfaces, "/xyz/openbmc_project/inventory"); 13667e860f15SJohn Edward Broadbent }); 1367ac6a4445SGunnar Mills } 1368ac6a4445SGunnar Mills 13697e860f15SJohn Edward Broadbent inline void requestRoutesProcessor(App& app) 13707e860f15SJohn Edward Broadbent { 1371ac6a4445SGunnar Mills /** 1372ac6a4445SGunnar Mills * Functions triggers appropriate requests on DBus 1373ac6a4445SGunnar Mills */ 13747e860f15SJohn Edward Broadbent 137522d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/<str>/") 137671a24ca4SNikhil Namjoshi .privileges(redfish::privileges::headProcessor) 137771a24ca4SNikhil Namjoshi .methods(boost::beast::http::verb::head)( 137871a24ca4SNikhil Namjoshi std::bind_front(handleProcessorHead, std::ref(app))); 137971a24ca4SNikhil Namjoshi 138071a24ca4SNikhil Namjoshi BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/<str>/") 1381ed398213SEd Tanous .privileges(redfish::privileges::getProcessor) 13827e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 138345ca1b86SEd Tanous [&app](const crow::Request& req, 13847e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 138522d268cbSEd Tanous const std::string& systemName, 13867e860f15SJohn Edward Broadbent const std::string& processorId) { 13873ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 138845ca1b86SEd Tanous { 138945ca1b86SEd Tanous return; 139045ca1b86SEd Tanous } 13917f3e84a1SEd Tanous if constexpr (bmcwebEnableMultiHost) 13927f3e84a1SEd Tanous { 13937f3e84a1SEd Tanous // Option currently returns no systems. TBD 13947f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 13957f3e84a1SEd Tanous systemName); 13967f3e84a1SEd Tanous return; 13977f3e84a1SEd Tanous } 139822d268cbSEd Tanous if (systemName != "system") 139922d268cbSEd Tanous { 140022d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 140122d268cbSEd Tanous systemName); 140222d268cbSEd Tanous return; 140322d268cbSEd Tanous } 140422d268cbSEd Tanous 140571a24ca4SNikhil Namjoshi asyncResp->res.addHeader( 140671a24ca4SNikhil Namjoshi boost::beast::http::field::link, 140771a24ca4SNikhil Namjoshi "</redfish/v1/JsonSchemas/Processor/Processor.json>; rel=describedby"); 14088d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.type"] = 1409dfbf7de5SChris Cain "#Processor.v1_18_0.Processor"; 1410ef4c65b7SEd Tanous asyncResp->res.jsonValue["@odata.id"] = boost::urls::format( 1411ef4c65b7SEd Tanous "/redfish/v1/Systems/system/Processors/{}", processorId); 1412ac6a4445SGunnar Mills 14138a592810SEd Tanous getProcessorObject( 14148a592810SEd Tanous asyncResp, processorId, 14158a592810SEd Tanous std::bind_front(getProcessorData, asyncResp, processorId)); 14167e860f15SJohn Edward Broadbent }); 14173cde86f1SJonathan Doman 141822d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/<str>/") 1419ed398213SEd Tanous .privileges(redfish::privileges::patchProcessor) 14207e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::patch)( 142145ca1b86SEd Tanous [&app](const crow::Request& req, 14227e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 142322d268cbSEd Tanous const std::string& systemName, 14247e860f15SJohn Edward Broadbent const std::string& processorId) { 14253ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 142645ca1b86SEd Tanous { 142745ca1b86SEd Tanous return; 142845ca1b86SEd Tanous } 14297f3e84a1SEd Tanous if constexpr (bmcwebEnableMultiHost) 14307f3e84a1SEd Tanous { 14317f3e84a1SEd Tanous // Option currently returns no systems. TBD 14327f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 14337f3e84a1SEd Tanous systemName); 14347f3e84a1SEd Tanous return; 14357f3e84a1SEd Tanous } 143622d268cbSEd Tanous if (systemName != "system") 143722d268cbSEd Tanous { 143822d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 143922d268cbSEd Tanous systemName); 144022d268cbSEd Tanous return; 144122d268cbSEd Tanous } 144222d268cbSEd Tanous 1443*3c569218SEd Tanous std::optional<std::string> appliedConfigUri; 144415ed6780SWilly Tu if (!json_util::readJsonPatch(req, asyncResp->res, 1445*3c569218SEd Tanous "AppliedOperatingConfig/@odata.id", 1446*3c569218SEd Tanous appliedConfigUri)) 14473cde86f1SJonathan Doman { 14483cde86f1SJonathan Doman return; 14493cde86f1SJonathan Doman } 14503cde86f1SJonathan Doman 1451*3c569218SEd Tanous if (appliedConfigUri) 14523cde86f1SJonathan Doman { 14537e860f15SJohn Edward Broadbent // Check for 404 and find matching D-Bus object, then run 14547e860f15SJohn Edward Broadbent // property patch handlers if that all succeeds. 14558a592810SEd Tanous getProcessorObject(asyncResp, processorId, 14568a592810SEd Tanous std::bind_front(patchAppliedOperatingConfig, 14577e860f15SJohn Edward Broadbent asyncResp, processorId, 1458*3c569218SEd Tanous *appliedConfigUri)); 14593cde86f1SJonathan Doman } 14607e860f15SJohn Edward Broadbent }); 14613cde86f1SJonathan Doman } 1462ac6a4445SGunnar Mills 1463ac6a4445SGunnar Mills } // namespace redfish 1464