1ac6a4445SGunnar Mills /* 26be832e2SEd Tanous Copyright (c) 2018 Intel Corporation 36be832e2SEd Tanous 46be832e2SEd Tanous Licensed under the Apache License, Version 2.0 (the "License"); 56be832e2SEd Tanous you may not use this file except in compliance with the License. 66be832e2SEd Tanous You may obtain a copy of the License at 76be832e2SEd Tanous 86be832e2SEd Tanous http://www.apache.org/licenses/LICENSE-2.0 96be832e2SEd Tanous 106be832e2SEd Tanous Unless required by applicable law or agreed to in writing, software 116be832e2SEd Tanous distributed under the License is distributed on an "AS IS" BASIS, 126be832e2SEd Tanous WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136be832e2SEd Tanous See the License for the specific language governing permissions and 146be832e2SEd Tanous 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" 23539d8c6bSEd Tanous #include "generated/enums/resource.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> 413c569218SEd 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 87539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled; 88539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["Health"] = resource::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 106539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["State"] = 107539d8c6bSEd Tanous resource::State::Absent; 108a1649ec6SChicago Duan } 109a1649ec6SChicago Duan } 110a1649ec6SChicago Duan else if (property.first == "Functional") 111a1649ec6SChicago Duan { 112a1649ec6SChicago Duan const bool* cpuFunctional = std::get_if<bool>(&property.second); 113a1649ec6SChicago Duan if (cpuFunctional == nullptr) 114a1649ec6SChicago Duan { 115ac106bf6SEd Tanous messages::internalError(asyncResp->res); 116ac6a4445SGunnar Mills return; 117ac6a4445SGunnar Mills } 118e05aec50SEd Tanous if (!*cpuFunctional) 119a1649ec6SChicago Duan { 120539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["Health"] = 121539d8c6bSEd Tanous resource::Health::Critical; 122a1649ec6SChicago Duan } 123a1649ec6SChicago Duan } 124a1649ec6SChicago Duan else if (property.first == "CoreCount") 125a1649ec6SChicago Duan { 126a1649ec6SChicago Duan const uint16_t* coresCount = 127a1649ec6SChicago Duan std::get_if<uint16_t>(&property.second); 128a1649ec6SChicago Duan if (coresCount == nullptr) 129a1649ec6SChicago Duan { 130ac106bf6SEd Tanous messages::internalError(asyncResp->res); 131a1649ec6SChicago Duan return; 132a1649ec6SChicago Duan } 133ac106bf6SEd Tanous asyncResp->res.jsonValue["TotalCores"] = *coresCount; 134ac6a4445SGunnar Mills } 135dc3fa667SJonathan Doman else if (property.first == "MaxSpeedInMhz") 136dc3fa667SJonathan Doman { 137dc3fa667SJonathan Doman const uint32_t* value = std::get_if<uint32_t>(&property.second); 138dc3fa667SJonathan Doman if (value != nullptr) 139dc3fa667SJonathan Doman { 140ac106bf6SEd Tanous asyncResp->res.jsonValue["MaxSpeedMHz"] = *value; 141dc3fa667SJonathan Doman } 142dc3fa667SJonathan Doman } 143ac6a4445SGunnar Mills else if (property.first == "Socket") 144ac6a4445SGunnar Mills { 145ac6a4445SGunnar Mills const std::string* value = 146ac6a4445SGunnar Mills std::get_if<std::string>(&property.second); 147ac6a4445SGunnar Mills if (value != nullptr) 148ac6a4445SGunnar Mills { 149ac106bf6SEd Tanous asyncResp->res.jsonValue["Socket"] = *value; 150ac6a4445SGunnar Mills } 151ac6a4445SGunnar Mills } 152ac6a4445SGunnar Mills else if (property.first == "ThreadCount") 153ac6a4445SGunnar Mills { 154dc3fa667SJonathan Doman const uint16_t* value = std::get_if<uint16_t>(&property.second); 155ac6a4445SGunnar Mills if (value != nullptr) 156ac6a4445SGunnar Mills { 157ac106bf6SEd Tanous asyncResp->res.jsonValue["TotalThreads"] = *value; 158ac6a4445SGunnar Mills } 159ac6a4445SGunnar Mills } 1601930fbd4SBrandon Kim else if (property.first == "EffectiveFamily") 161ac6a4445SGunnar Mills { 1621930fbd4SBrandon Kim const uint16_t* value = std::get_if<uint16_t>(&property.second); 1636169de2cSBrad Bishop if (value != nullptr && *value != 2) 164ac6a4445SGunnar Mills { 165ac106bf6SEd Tanous asyncResp->res.jsonValue["ProcessorId"]["EffectiveFamily"] = 166866e4862SEd Tanous "0x" + intToHexString(*value, 4); 167ac6a4445SGunnar Mills } 168ac6a4445SGunnar Mills } 1691930fbd4SBrandon Kim else if (property.first == "EffectiveModel") 1701930fbd4SBrandon Kim { 1711930fbd4SBrandon Kim const uint16_t* value = std::get_if<uint16_t>(&property.second); 1721930fbd4SBrandon Kim if (value == nullptr) 1731930fbd4SBrandon Kim { 174ac106bf6SEd Tanous messages::internalError(asyncResp->res); 1751930fbd4SBrandon Kim return; 1761930fbd4SBrandon Kim } 1776169de2cSBrad Bishop if (*value != 0) 1786169de2cSBrad Bishop { 179ac106bf6SEd Tanous asyncResp->res.jsonValue["ProcessorId"]["EffectiveModel"] = 180866e4862SEd Tanous "0x" + intToHexString(*value, 4); 1811930fbd4SBrandon Kim } 1826169de2cSBrad Bishop } 183ac6a4445SGunnar Mills else if (property.first == "Id") 184ac6a4445SGunnar Mills { 185ac6a4445SGunnar Mills const uint64_t* value = std::get_if<uint64_t>(&property.second); 186ac6a4445SGunnar Mills if (value != nullptr && *value != 0) 187ac6a4445SGunnar Mills { 188ac106bf6SEd Tanous asyncResp->res 189ac6a4445SGunnar Mills .jsonValue["ProcessorId"]["IdentificationRegisters"] = 190866e4862SEd Tanous "0x" + intToHexString(*value, 16); 191ac6a4445SGunnar Mills } 192ac6a4445SGunnar Mills } 1931930fbd4SBrandon Kim else if (property.first == "Microcode") 1941930fbd4SBrandon Kim { 1951930fbd4SBrandon Kim const uint32_t* value = std::get_if<uint32_t>(&property.second); 1961930fbd4SBrandon Kim if (value == nullptr) 1971930fbd4SBrandon Kim { 198ac106bf6SEd Tanous messages::internalError(asyncResp->res); 1991930fbd4SBrandon Kim return; 2001930fbd4SBrandon Kim } 2016169de2cSBrad Bishop if (*value != 0) 2026169de2cSBrad Bishop { 203ac106bf6SEd Tanous asyncResp->res.jsonValue["ProcessorId"]["MicrocodeInfo"] = 204866e4862SEd Tanous "0x" + intToHexString(*value, 8); 2051930fbd4SBrandon Kim } 2066169de2cSBrad Bishop } 2071930fbd4SBrandon Kim else if (property.first == "Step") 2081930fbd4SBrandon Kim { 2091930fbd4SBrandon Kim const uint16_t* value = std::get_if<uint16_t>(&property.second); 2101930fbd4SBrandon Kim if (value == nullptr) 2111930fbd4SBrandon Kim { 212ac106bf6SEd Tanous messages::internalError(asyncResp->res); 2131930fbd4SBrandon Kim return; 2141930fbd4SBrandon Kim } 215b9d679d1SMichael Shen if (*value != std::numeric_limits<uint16_t>::max()) 2166169de2cSBrad Bishop { 217ac106bf6SEd Tanous asyncResp->res.jsonValue["ProcessorId"]["Step"] = 218866e4862SEd Tanous "0x" + intToHexString(*value, 4); 2191930fbd4SBrandon Kim } 220ac6a4445SGunnar Mills } 221ac6a4445SGunnar Mills } 222ac6a4445SGunnar Mills } 2236169de2cSBrad Bishop } 224ac6a4445SGunnar Mills 225bd79bce8SPatrick Williams inline void getCpuDataByService( 226bd79bce8SPatrick Williams std::shared_ptr<bmcweb::AsyncResp> asyncResp, const std::string& cpuId, 227bd79bce8SPatrick Williams const std::string& service, const std::string& objPath) 228ac6a4445SGunnar Mills { 22962598e31SEd Tanous BMCWEB_LOG_DEBUG("Get available system cpu resources by service."); 230ac6a4445SGunnar Mills 2315eb468daSGeorge Liu sdbusplus::message::object_path path("/xyz/openbmc_project/inventory"); 2325eb468daSGeorge Liu dbus::utility::getManagedObjects( 2335eb468daSGeorge Liu service, path, 234ac106bf6SEd Tanous [cpuId, service, objPath, asyncResp{std::move(asyncResp)}]( 2355e7e2dc5SEd Tanous const boost::system::error_code& ec, 236ac6a4445SGunnar Mills const dbus::utility::ManagedObjectType& dbusData) { 237ac6a4445SGunnar Mills if (ec) 238ac6a4445SGunnar Mills { 23962598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error"); 240ac106bf6SEd Tanous messages::internalError(asyncResp->res); 241ac6a4445SGunnar Mills return; 242ac6a4445SGunnar Mills } 243ac106bf6SEd Tanous asyncResp->res.jsonValue["Id"] = cpuId; 244ac106bf6SEd Tanous asyncResp->res.jsonValue["Name"] = "Processor"; 245539d8c6bSEd Tanous asyncResp->res.jsonValue["ProcessorType"] = 246539d8c6bSEd Tanous processor::ProcessorType::CPU; 247ac6a4445SGunnar Mills 248ac6a4445SGunnar Mills bool slotPresent = false; 249ac6a4445SGunnar Mills std::string corePath = objPath + "/core"; 250ac6a4445SGunnar Mills size_t totalCores = 0; 251ac6a4445SGunnar Mills for (const auto& object : dbusData) 252ac6a4445SGunnar Mills { 253ac6a4445SGunnar Mills if (object.first.str == objPath) 254ac6a4445SGunnar Mills { 255ac106bf6SEd Tanous getCpuDataByInterface(asyncResp, object.second); 256ac6a4445SGunnar Mills } 25711ba3979SEd Tanous else if (object.first.str.starts_with(corePath)) 258ac6a4445SGunnar Mills { 259ac6a4445SGunnar Mills for (const auto& interface : object.second) 260ac6a4445SGunnar Mills { 261bd79bce8SPatrick Williams if (interface.first == 262bd79bce8SPatrick Williams "xyz.openbmc_project.Inventory.Item") 263ac6a4445SGunnar Mills { 264ac6a4445SGunnar Mills for (const auto& property : interface.second) 265ac6a4445SGunnar Mills { 266ac6a4445SGunnar Mills if (property.first == "Present") 267ac6a4445SGunnar Mills { 268ac6a4445SGunnar Mills const bool* present = 269ac6a4445SGunnar Mills std::get_if<bool>(&property.second); 270ac6a4445SGunnar Mills if (present != nullptr) 271ac6a4445SGunnar Mills { 272e05aec50SEd Tanous if (*present) 273ac6a4445SGunnar Mills { 274ac6a4445SGunnar Mills slotPresent = true; 275ac6a4445SGunnar Mills totalCores++; 276ac6a4445SGunnar Mills } 277ac6a4445SGunnar Mills } 278ac6a4445SGunnar Mills } 279ac6a4445SGunnar Mills } 280ac6a4445SGunnar Mills } 281ac6a4445SGunnar Mills } 282ac6a4445SGunnar Mills } 283ac6a4445SGunnar Mills } 284ac6a4445SGunnar Mills // In getCpuDataByInterface(), state and health are set 285ac6a4445SGunnar Mills // based on the present and functional status. If core 286ac6a4445SGunnar Mills // count is zero, then it has a higher precedence. 287ac6a4445SGunnar Mills if (slotPresent) 288ac6a4445SGunnar Mills { 289ac106bf6SEd Tanous asyncResp->res.jsonValue["TotalCores"] = totalCores; 290ac6a4445SGunnar Mills } 291ac6a4445SGunnar Mills return; 2925eb468daSGeorge Liu }); 293ac6a4445SGunnar Mills } 294ac6a4445SGunnar Mills 295dfbf7de5SChris Cain /** 296dfbf7de5SChris Cain * @brief Translates throttle cause DBUS property to redfish. 297dfbf7de5SChris Cain * 298dfbf7de5SChris Cain * @param[in] dbusSource The throttle cause from DBUS 299dfbf7de5SChris Cain * 300dfbf7de5SChris Cain * @return Returns as a string, the throttle cause in Redfish terms. If 301dfbf7de5SChris Cain * translation cannot be done, returns "Unknown" throttle reason. 302dfbf7de5SChris Cain */ 303dfbf7de5SChris Cain inline processor::ThrottleCause 304dfbf7de5SChris Cain dbusToRfThrottleCause(const std::string& dbusSource) 305dfbf7de5SChris Cain { 306dfbf7de5SChris Cain if (dbusSource == 307dfbf7de5SChris Cain "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.ClockLimit") 308dfbf7de5SChris Cain { 309dfbf7de5SChris Cain return processor::ThrottleCause::ClockLimit; 310dfbf7de5SChris Cain } 311dfbf7de5SChris Cain if (dbusSource == 312dfbf7de5SChris Cain "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.ManagementDetectedFault") 313dfbf7de5SChris Cain { 314dfbf7de5SChris Cain return processor::ThrottleCause::ManagementDetectedFault; 315dfbf7de5SChris Cain } 316dfbf7de5SChris Cain if (dbusSource == 317dfbf7de5SChris Cain "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.PowerLimit") 318dfbf7de5SChris Cain { 319dfbf7de5SChris Cain return processor::ThrottleCause::PowerLimit; 320dfbf7de5SChris Cain } 321dfbf7de5SChris Cain if (dbusSource == 322dfbf7de5SChris Cain "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.ThermalLimit") 323dfbf7de5SChris Cain { 324dfbf7de5SChris Cain return processor::ThrottleCause::ThermalLimit; 325dfbf7de5SChris Cain } 326dfbf7de5SChris Cain if (dbusSource == 327dfbf7de5SChris Cain "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.Unknown") 328dfbf7de5SChris Cain { 329dfbf7de5SChris Cain return processor::ThrottleCause::Unknown; 330dfbf7de5SChris Cain } 331dfbf7de5SChris Cain return processor::ThrottleCause::Invalid; 332dfbf7de5SChris Cain } 333dfbf7de5SChris Cain 334dfbf7de5SChris Cain inline void 335ac106bf6SEd Tanous readThrottleProperties(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 336dfbf7de5SChris Cain const boost::system::error_code& ec, 337dfbf7de5SChris Cain const dbus::utility::DBusPropertiesMap& properties) 338dfbf7de5SChris Cain { 339dfbf7de5SChris Cain if (ec) 340dfbf7de5SChris Cain { 34162598e31SEd Tanous BMCWEB_LOG_ERROR("Processor Throttle getAllProperties error {}", ec); 342ac106bf6SEd Tanous messages::internalError(asyncResp->res); 343dfbf7de5SChris Cain return; 344dfbf7de5SChris Cain } 345dfbf7de5SChris Cain 346dfbf7de5SChris Cain const bool* status = nullptr; 347dfbf7de5SChris Cain const std::vector<std::string>* causes = nullptr; 348dfbf7de5SChris Cain 349dfbf7de5SChris Cain if (!sdbusplus::unpackPropertiesNoThrow(dbus_utils::UnpackErrorPrinter(), 350dfbf7de5SChris Cain properties, "Throttled", status, 351dfbf7de5SChris Cain "ThrottleCauses", causes)) 352dfbf7de5SChris Cain { 353ac106bf6SEd Tanous messages::internalError(asyncResp->res); 354dfbf7de5SChris Cain return; 355dfbf7de5SChris Cain } 356dfbf7de5SChris Cain 357ac106bf6SEd Tanous asyncResp->res.jsonValue["Throttled"] = *status; 358dfbf7de5SChris Cain nlohmann::json::array_t rCauses; 359dfbf7de5SChris Cain for (const std::string& cause : *causes) 360dfbf7de5SChris Cain { 361dfbf7de5SChris Cain processor::ThrottleCause rfCause = dbusToRfThrottleCause(cause); 362dfbf7de5SChris Cain if (rfCause == processor::ThrottleCause::Invalid) 363dfbf7de5SChris Cain { 364ac106bf6SEd Tanous messages::internalError(asyncResp->res); 365dfbf7de5SChris Cain return; 366dfbf7de5SChris Cain } 367dfbf7de5SChris Cain 368dfbf7de5SChris Cain rCauses.emplace_back(rfCause); 369dfbf7de5SChris Cain } 370ac106bf6SEd Tanous asyncResp->res.jsonValue["ThrottleCauses"] = std::move(rCauses); 371dfbf7de5SChris Cain } 372dfbf7de5SChris Cain 373bd79bce8SPatrick Williams inline void getThrottleProperties( 374bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 375bd79bce8SPatrick Williams const std::string& service, const std::string& objectPath) 376dfbf7de5SChris Cain { 37762598e31SEd Tanous BMCWEB_LOG_DEBUG("Get processor throttle resources"); 378dfbf7de5SChris Cain 379dfbf7de5SChris Cain sdbusplus::asio::getAllProperties( 380dfbf7de5SChris Cain *crow::connections::systemBus, service, objectPath, 381dfbf7de5SChris Cain "xyz.openbmc_project.Control.Power.Throttle", 382ac106bf6SEd Tanous [asyncResp](const boost::system::error_code& ec, 383dfbf7de5SChris Cain const dbus::utility::DBusPropertiesMap& properties) { 384ac106bf6SEd Tanous readThrottleProperties(asyncResp, ec, properties); 385dfbf7de5SChris Cain }); 386dfbf7de5SChris Cain } 387dfbf7de5SChris Cain 388ac106bf6SEd Tanous inline void getCpuAssetData(std::shared_ptr<bmcweb::AsyncResp> asyncResp, 389ac6a4445SGunnar Mills const std::string& service, 390ac6a4445SGunnar Mills const std::string& objPath) 391ac6a4445SGunnar Mills { 39262598e31SEd Tanous BMCWEB_LOG_DEBUG("Get Cpu Asset Data"); 393351053f2SKrzysztof Grobelny sdbusplus::asio::getAllProperties( 394351053f2SKrzysztof Grobelny *crow::connections::systemBus, service, objPath, 395351053f2SKrzysztof Grobelny "xyz.openbmc_project.Inventory.Decorator.Asset", 396ac106bf6SEd Tanous [objPath, asyncResp{std::move(asyncResp)}]( 3975e7e2dc5SEd Tanous const boost::system::error_code& ec, 398351053f2SKrzysztof Grobelny const dbus::utility::DBusPropertiesMap& properties) { 399ac6a4445SGunnar Mills if (ec) 400ac6a4445SGunnar Mills { 40162598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error"); 402ac106bf6SEd Tanous messages::internalError(asyncResp->res); 403ac6a4445SGunnar Mills return; 404ac6a4445SGunnar Mills } 405ac6a4445SGunnar Mills 406351053f2SKrzysztof Grobelny const std::string* serialNumber = nullptr; 407351053f2SKrzysztof Grobelny const std::string* model = nullptr; 408351053f2SKrzysztof Grobelny const std::string* manufacturer = nullptr; 409351053f2SKrzysztof Grobelny const std::string* partNumber = nullptr; 410351053f2SKrzysztof Grobelny const std::string* sparePartNumber = nullptr; 411351053f2SKrzysztof Grobelny 412351053f2SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 413351053f2SKrzysztof Grobelny dbus_utils::UnpackErrorPrinter(), properties, "SerialNumber", 414351053f2SKrzysztof Grobelny serialNumber, "Model", model, "Manufacturer", manufacturer, 415351053f2SKrzysztof Grobelny "PartNumber", partNumber, "SparePartNumber", sparePartNumber); 416351053f2SKrzysztof Grobelny 417351053f2SKrzysztof Grobelny if (!success) 418ac6a4445SGunnar Mills { 419ac106bf6SEd Tanous messages::internalError(asyncResp->res); 420351053f2SKrzysztof Grobelny return; 421ac6a4445SGunnar Mills } 422351053f2SKrzysztof Grobelny 423351053f2SKrzysztof Grobelny if (serialNumber != nullptr && !serialNumber->empty()) 424ac6a4445SGunnar Mills { 425ac106bf6SEd Tanous asyncResp->res.jsonValue["SerialNumber"] = *serialNumber; 426351053f2SKrzysztof Grobelny } 427351053f2SKrzysztof Grobelny 428351053f2SKrzysztof Grobelny if ((model != nullptr) && !model->empty()) 429ac6a4445SGunnar Mills { 430ac106bf6SEd Tanous asyncResp->res.jsonValue["Model"] = *model; 431ac6a4445SGunnar Mills } 432ac6a4445SGunnar Mills 433351053f2SKrzysztof Grobelny if (manufacturer != nullptr) 434ac6a4445SGunnar Mills { 435ac106bf6SEd Tanous asyncResp->res.jsonValue["Manufacturer"] = *manufacturer; 436ac6a4445SGunnar Mills 437ac6a4445SGunnar Mills // Otherwise would be unexpected. 438351053f2SKrzysztof Grobelny if (manufacturer->find("Intel") != std::string::npos) 439ac6a4445SGunnar Mills { 440ac106bf6SEd Tanous asyncResp->res.jsonValue["ProcessorArchitecture"] = "x86"; 441ac106bf6SEd Tanous asyncResp->res.jsonValue["InstructionSet"] = "x86-64"; 442ac6a4445SGunnar Mills } 443351053f2SKrzysztof Grobelny else if (manufacturer->find("IBM") != std::string::npos) 444ac6a4445SGunnar Mills { 445ac106bf6SEd Tanous asyncResp->res.jsonValue["ProcessorArchitecture"] = "Power"; 446ac106bf6SEd Tanous asyncResp->res.jsonValue["InstructionSet"] = "PowerISA"; 447ac6a4445SGunnar Mills } 448ac6a4445SGunnar Mills } 449cba4f448SSunnySrivastava1984 450351053f2SKrzysztof Grobelny if (partNumber != nullptr) 451cba4f448SSunnySrivastava1984 { 452ac106bf6SEd Tanous asyncResp->res.jsonValue["PartNumber"] = *partNumber; 453cba4f448SSunnySrivastava1984 } 454cba4f448SSunnySrivastava1984 4556169de2cSBrad Bishop if (sparePartNumber != nullptr && !sparePartNumber->empty()) 456cba4f448SSunnySrivastava1984 { 457ac106bf6SEd Tanous asyncResp->res.jsonValue["SparePartNumber"] = *sparePartNumber; 458cba4f448SSunnySrivastava1984 } 459351053f2SKrzysztof Grobelny }); 460ac6a4445SGunnar Mills } 461ac6a4445SGunnar Mills 462ac106bf6SEd Tanous inline void getCpuRevisionData(std::shared_ptr<bmcweb::AsyncResp> asyncResp, 463ac6a4445SGunnar Mills const std::string& service, 464ac6a4445SGunnar Mills const std::string& objPath) 465ac6a4445SGunnar Mills { 46662598e31SEd Tanous BMCWEB_LOG_DEBUG("Get Cpu Revision Data"); 467351053f2SKrzysztof Grobelny sdbusplus::asio::getAllProperties( 468351053f2SKrzysztof Grobelny *crow::connections::systemBus, service, objPath, 469351053f2SKrzysztof Grobelny "xyz.openbmc_project.Inventory.Decorator.Revision", 470ac106bf6SEd Tanous [objPath, asyncResp{std::move(asyncResp)}]( 4715e7e2dc5SEd Tanous const boost::system::error_code& ec, 472351053f2SKrzysztof Grobelny const dbus::utility::DBusPropertiesMap& properties) { 473ac6a4445SGunnar Mills if (ec) 474ac6a4445SGunnar Mills { 47562598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error"); 476ac106bf6SEd Tanous messages::internalError(asyncResp->res); 477ac6a4445SGunnar Mills return; 478ac6a4445SGunnar Mills } 479ac6a4445SGunnar Mills 480351053f2SKrzysztof Grobelny const std::string* version = nullptr; 481351053f2SKrzysztof Grobelny 482351053f2SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 483bd79bce8SPatrick Williams dbus_utils::UnpackErrorPrinter(), properties, "Version", 484bd79bce8SPatrick Williams version); 485351053f2SKrzysztof Grobelny 486351053f2SKrzysztof Grobelny if (!success) 487ac6a4445SGunnar Mills { 488ac106bf6SEd Tanous messages::internalError(asyncResp->res); 489351053f2SKrzysztof Grobelny return; 490351053f2SKrzysztof Grobelny } 491351053f2SKrzysztof Grobelny 492351053f2SKrzysztof Grobelny if (version != nullptr) 493ac6a4445SGunnar Mills { 494ac106bf6SEd Tanous asyncResp->res.jsonValue["Version"] = *version; 495ac6a4445SGunnar Mills } 496351053f2SKrzysztof Grobelny }); 497ac6a4445SGunnar Mills } 498ac6a4445SGunnar Mills 4998d1b46d7Szhanghch05 inline void getAcceleratorDataByService( 500ac106bf6SEd Tanous std::shared_ptr<bmcweb::AsyncResp> asyncResp, const std::string& acclrtrId, 5018d1b46d7Szhanghch05 const std::string& service, const std::string& objPath) 502ac6a4445SGunnar Mills { 50362598e31SEd Tanous BMCWEB_LOG_DEBUG("Get available system Accelerator resources by service."); 504351053f2SKrzysztof Grobelny sdbusplus::asio::getAllProperties( 505351053f2SKrzysztof Grobelny *crow::connections::systemBus, service, objPath, "", 506ac106bf6SEd Tanous [acclrtrId, asyncResp{std::move(asyncResp)}]( 5075e7e2dc5SEd Tanous const boost::system::error_code& ec, 508351053f2SKrzysztof Grobelny const dbus::utility::DBusPropertiesMap& properties) { 509ac6a4445SGunnar Mills if (ec) 510ac6a4445SGunnar Mills { 51162598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error"); 512ac106bf6SEd Tanous messages::internalError(asyncResp->res); 513ac6a4445SGunnar Mills return; 514ac6a4445SGunnar Mills } 515ac6a4445SGunnar Mills 516351053f2SKrzysztof Grobelny const bool* functional = nullptr; 517351053f2SKrzysztof Grobelny const bool* present = nullptr; 518351053f2SKrzysztof Grobelny 519351053f2SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 520351053f2SKrzysztof Grobelny dbus_utils::UnpackErrorPrinter(), properties, "Functional", 521351053f2SKrzysztof Grobelny functional, "Present", present); 522351053f2SKrzysztof Grobelny 523351053f2SKrzysztof Grobelny if (!success) 524ac6a4445SGunnar Mills { 525ac106bf6SEd Tanous messages::internalError(asyncResp->res); 526351053f2SKrzysztof Grobelny return; 527ac6a4445SGunnar Mills } 528ac6a4445SGunnar Mills 529ac6a4445SGunnar Mills std::string state = "Enabled"; 530ac6a4445SGunnar Mills std::string health = "OK"; 531ac6a4445SGunnar Mills 532351053f2SKrzysztof Grobelny if (present != nullptr && !*present) 533ac6a4445SGunnar Mills { 534ac6a4445SGunnar Mills state = "Absent"; 535ac6a4445SGunnar Mills } 536ac6a4445SGunnar Mills 537351053f2SKrzysztof Grobelny if (functional != nullptr && !*functional) 538ac6a4445SGunnar Mills { 539ac6a4445SGunnar Mills if (state == "Enabled") 540ac6a4445SGunnar Mills { 541ac6a4445SGunnar Mills health = "Critical"; 542ac6a4445SGunnar Mills } 543ac6a4445SGunnar Mills } 544ac6a4445SGunnar Mills 545ac106bf6SEd Tanous asyncResp->res.jsonValue["Id"] = acclrtrId; 546ac106bf6SEd Tanous asyncResp->res.jsonValue["Name"] = "Processor"; 547ac106bf6SEd Tanous asyncResp->res.jsonValue["Status"]["State"] = state; 548ac106bf6SEd Tanous asyncResp->res.jsonValue["Status"]["Health"] = health; 549539d8c6bSEd Tanous asyncResp->res.jsonValue["ProcessorType"] = 550539d8c6bSEd Tanous processor::ProcessorType::Accelerator; 551351053f2SKrzysztof Grobelny }); 552ac6a4445SGunnar Mills } 553ac6a4445SGunnar Mills 554dba0c291SJonathan Doman // OperatingConfig D-Bus Types 555dba0c291SJonathan Doman using TurboProfileProperty = std::vector<std::tuple<uint32_t, size_t>>; 556dba0c291SJonathan Doman using BaseSpeedPrioritySettingsProperty = 557dba0c291SJonathan Doman std::vector<std::tuple<uint32_t, std::vector<uint32_t>>>; 558dba0c291SJonathan Doman // uint32_t and size_t may or may not be the same type, requiring a dedup'd 559dba0c291SJonathan Doman // variant 560dba0c291SJonathan Doman 561dba0c291SJonathan Doman /** 562dba0c291SJonathan Doman * Fill out the HighSpeedCoreIDs in a Processor resource from the given 563dba0c291SJonathan Doman * OperatingConfig D-Bus property. 564dba0c291SJonathan Doman * 565ac106bf6SEd Tanous * @param[in,out] asyncResp Async HTTP response. 566dba0c291SJonathan Doman * @param[in] baseSpeedSettings Full list of base speed priority groups, 567dba0c291SJonathan Doman * to use to determine the list of high 568dba0c291SJonathan Doman * speed cores. 569dba0c291SJonathan Doman */ 570dba0c291SJonathan Doman inline void highSpeedCoreIdsHandler( 571ac106bf6SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 572dba0c291SJonathan Doman const BaseSpeedPrioritySettingsProperty& baseSpeedSettings) 573dba0c291SJonathan Doman { 574dba0c291SJonathan Doman // The D-Bus property does not indicate which bucket is the "high 575dba0c291SJonathan Doman // priority" group, so let's discern that by looking for the one with 576dba0c291SJonathan Doman // highest base frequency. 577dba0c291SJonathan Doman auto highPriorityGroup = baseSpeedSettings.cend(); 578dba0c291SJonathan Doman uint32_t highestBaseSpeed = 0; 579dba0c291SJonathan Doman for (auto it = baseSpeedSettings.cbegin(); it != baseSpeedSettings.cend(); 580dba0c291SJonathan Doman ++it) 581dba0c291SJonathan Doman { 582dba0c291SJonathan Doman const uint32_t baseFreq = std::get<uint32_t>(*it); 583dba0c291SJonathan Doman if (baseFreq > highestBaseSpeed) 584dba0c291SJonathan Doman { 585dba0c291SJonathan Doman highestBaseSpeed = baseFreq; 586dba0c291SJonathan Doman highPriorityGroup = it; 587dba0c291SJonathan Doman } 588dba0c291SJonathan Doman } 589dba0c291SJonathan Doman 590ac106bf6SEd Tanous nlohmann::json& jsonCoreIds = asyncResp->res.jsonValue["HighSpeedCoreIDs"]; 591dba0c291SJonathan Doman jsonCoreIds = nlohmann::json::array(); 592dba0c291SJonathan Doman 593dba0c291SJonathan Doman // There may not be any entries in the D-Bus property, so only populate 594dba0c291SJonathan Doman // if there was actually something there. 595dba0c291SJonathan Doman if (highPriorityGroup != baseSpeedSettings.cend()) 596dba0c291SJonathan Doman { 597dba0c291SJonathan Doman jsonCoreIds = std::get<std::vector<uint32_t>>(*highPriorityGroup); 598dba0c291SJonathan Doman } 599dba0c291SJonathan Doman } 600dba0c291SJonathan Doman 601dba0c291SJonathan Doman /** 602dba0c291SJonathan Doman * Fill out OperatingConfig related items in a Processor resource by requesting 603dba0c291SJonathan Doman * data from the given D-Bus object. 604dba0c291SJonathan Doman * 605ac106bf6SEd Tanous * @param[in,out] asyncResp Async HTTP response. 606dba0c291SJonathan Doman * @param[in] cpuId CPU D-Bus name. 607dba0c291SJonathan Doman * @param[in] service D-Bus service to query. 608dba0c291SJonathan Doman * @param[in] objPath D-Bus object to query. 609dba0c291SJonathan Doman */ 610ac106bf6SEd Tanous inline void 611ac106bf6SEd Tanous getCpuConfigData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 612ac106bf6SEd Tanous const std::string& cpuId, const std::string& service, 613dba0c291SJonathan Doman const std::string& objPath) 614dba0c291SJonathan Doman { 61562598e31SEd Tanous BMCWEB_LOG_INFO("Getting CPU operating configs for {}", cpuId); 616dba0c291SJonathan Doman 617dba0c291SJonathan Doman // First, GetAll CurrentOperatingConfig properties on the object 618351053f2SKrzysztof Grobelny sdbusplus::asio::getAllProperties( 619351053f2SKrzysztof Grobelny *crow::connections::systemBus, service, objPath, 620351053f2SKrzysztof Grobelny "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig", 621ac106bf6SEd Tanous [asyncResp, cpuId, 6225e7e2dc5SEd Tanous service](const boost::system::error_code& ec, 623351053f2SKrzysztof Grobelny const dbus::utility::DBusPropertiesMap& properties) { 624dba0c291SJonathan Doman if (ec) 625dba0c291SJonathan Doman { 62662598e31SEd Tanous BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec, ec.message()); 627ac106bf6SEd Tanous messages::internalError(asyncResp->res); 628dba0c291SJonathan Doman return; 629dba0c291SJonathan Doman } 630dba0c291SJonathan Doman 631ac106bf6SEd Tanous nlohmann::json& json = asyncResp->res.jsonValue; 632dba0c291SJonathan Doman 633351053f2SKrzysztof Grobelny const sdbusplus::message::object_path* appliedConfig = nullptr; 634351053f2SKrzysztof Grobelny const bool* baseSpeedPriorityEnabled = nullptr; 635351053f2SKrzysztof Grobelny 636351053f2SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 637351053f2SKrzysztof Grobelny dbus_utils::UnpackErrorPrinter(), properties, "AppliedConfig", 638351053f2SKrzysztof Grobelny appliedConfig, "BaseSpeedPriorityEnabled", 639351053f2SKrzysztof Grobelny baseSpeedPriorityEnabled); 640351053f2SKrzysztof Grobelny 641351053f2SKrzysztof Grobelny if (!success) 642dba0c291SJonathan Doman { 643ac106bf6SEd Tanous messages::internalError(asyncResp->res); 644351053f2SKrzysztof Grobelny return; 645dba0c291SJonathan Doman } 646dba0c291SJonathan Doman 647351053f2SKrzysztof Grobelny if (appliedConfig != nullptr) 648351053f2SKrzysztof Grobelny { 649351053f2SKrzysztof Grobelny const std::string& dbusPath = appliedConfig->str; 6501476687dSEd Tanous nlohmann::json::object_t operatingConfig; 651ef4c65b7SEd Tanous operatingConfig["@odata.id"] = boost::urls::format( 652253f11b8SEd Tanous "/redfish/v1/Systems/{}/Processors/{}/OperatingConfigs", 653253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME, cpuId); 6541476687dSEd Tanous json["OperatingConfigs"] = std::move(operatingConfig); 655dba0c291SJonathan Doman 656dba0c291SJonathan Doman // Reuse the D-Bus config object name for the Redfish 657dba0c291SJonathan Doman // URI 658dba0c291SJonathan Doman size_t baseNamePos = dbusPath.rfind('/'); 659dba0c291SJonathan Doman if (baseNamePos == std::string::npos || 660dba0c291SJonathan Doman baseNamePos == (dbusPath.size() - 1)) 661dba0c291SJonathan Doman { 662dba0c291SJonathan Doman // If the AppliedConfig was somehow not a valid path, 663dba0c291SJonathan Doman // skip adding any more properties, since everything 664dba0c291SJonathan Doman // else is tied to this applied config. 665ac106bf6SEd Tanous messages::internalError(asyncResp->res); 666351053f2SKrzysztof Grobelny return; 667dba0c291SJonathan Doman } 6681476687dSEd Tanous nlohmann::json::object_t appliedOperatingConfig; 669ef4c65b7SEd Tanous appliedOperatingConfig["@odata.id"] = boost::urls::format( 670253f11b8SEd Tanous "/redfish/v1/Systems/{}/Processors/{}/OperatingConfigs/{}", 671253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME, cpuId, 672253f11b8SEd Tanous dbusPath.substr(baseNamePos + 1)); 673bd79bce8SPatrick Williams json["AppliedOperatingConfig"] = 674bd79bce8SPatrick Williams 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", 684bd79bce8SPatrick Williams [asyncResp](const boost::system::error_code& ec2, 685bd79bce8SPatrick Williams const BaseSpeedPrioritySettingsProperty& 686bd79bce8SPatrick Williams baseSpeedList) { 6878a592810SEd Tanous if (ec2) 688dba0c291SJonathan Doman { 689bd79bce8SPatrick Williams BMCWEB_LOG_WARNING("D-Bus Property Get error: {}", 690bd79bce8SPatrick Williams ec2); 691ac106bf6SEd Tanous messages::internalError(asyncResp->res); 692dba0c291SJonathan Doman return; 693dba0c291SJonathan Doman } 6941e1e598dSJonathan Doman 695ac106bf6SEd Tanous highSpeedCoreIdsHandler(asyncResp, baseSpeedList); 6961e1e598dSJonathan Doman }); 697dba0c291SJonathan Doman } 698351053f2SKrzysztof Grobelny 699351053f2SKrzysztof Grobelny if (baseSpeedPriorityEnabled != nullptr) 700dba0c291SJonathan Doman { 701dba0c291SJonathan Doman json["BaseSpeedPriorityState"] = 702351053f2SKrzysztof Grobelny *baseSpeedPriorityEnabled ? "Enabled" : "Disabled"; 703dba0c291SJonathan Doman } 704351053f2SKrzysztof Grobelny }); 705dba0c291SJonathan Doman } 706dba0c291SJonathan Doman 707cba4f448SSunnySrivastava1984 /** 708cba4f448SSunnySrivastava1984 * @brief Fill out location info of a processor by 709cba4f448SSunnySrivastava1984 * requesting data from the given D-Bus object. 710cba4f448SSunnySrivastava1984 * 711ac106bf6SEd Tanous * @param[in,out] asyncResp Async HTTP response. 712cba4f448SSunnySrivastava1984 * @param[in] service D-Bus service to query. 713cba4f448SSunnySrivastava1984 * @param[in] objPath D-Bus object to query. 714cba4f448SSunnySrivastava1984 */ 715ac106bf6SEd Tanous inline void getCpuLocationCode(std::shared_ptr<bmcweb::AsyncResp> asyncResp, 716cba4f448SSunnySrivastava1984 const std::string& service, 717cba4f448SSunnySrivastava1984 const std::string& objPath) 718cba4f448SSunnySrivastava1984 { 71962598e31SEd Tanous BMCWEB_LOG_DEBUG("Get Cpu Location Data"); 7201e1e598dSJonathan Doman sdbusplus::asio::getProperty<std::string>( 7211e1e598dSJonathan Doman *crow::connections::systemBus, service, objPath, 7221e1e598dSJonathan Doman "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode", 723ac106bf6SEd Tanous [objPath, asyncResp{std::move(asyncResp)}]( 724ac106bf6SEd Tanous const boost::system::error_code& ec, const std::string& property) { 725cba4f448SSunnySrivastava1984 if (ec) 726cba4f448SSunnySrivastava1984 { 72762598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error"); 728ac106bf6SEd Tanous messages::internalError(asyncResp->res); 729cba4f448SSunnySrivastava1984 return; 730cba4f448SSunnySrivastava1984 } 731cba4f448SSunnySrivastava1984 732bd79bce8SPatrick Williams asyncResp->res 733bd79bce8SPatrick Williams .jsonValue["Location"]["PartLocation"]["ServiceLabel"] = 7341e1e598dSJonathan Doman property; 7351e1e598dSJonathan Doman }); 736cba4f448SSunnySrivastava1984 } 737cba4f448SSunnySrivastava1984 738c951448aSJonathan Doman /** 73949e429caSJonathan Doman * Populate the unique identifier in a Processor resource by requesting data 74049e429caSJonathan Doman * from the given D-Bus object. 74149e429caSJonathan Doman * 742ac106bf6SEd Tanous * @param[in,out] asyncResp Async HTTP response. 74349e429caSJonathan Doman * @param[in] service D-Bus service to query. 74449e429caSJonathan Doman * @param[in] objPath D-Bus object to query. 74549e429caSJonathan Doman */ 746ac106bf6SEd Tanous inline void getCpuUniqueId(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 74749e429caSJonathan Doman const std::string& service, 74849e429caSJonathan Doman const std::string& objectPath) 74949e429caSJonathan Doman { 75062598e31SEd Tanous BMCWEB_LOG_DEBUG("Get CPU UniqueIdentifier"); 7511e1e598dSJonathan Doman sdbusplus::asio::getProperty<std::string>( 7521e1e598dSJonathan Doman *crow::connections::systemBus, service, objectPath, 7531e1e598dSJonathan Doman "xyz.openbmc_project.Inventory.Decorator.UniqueIdentifier", 7541e1e598dSJonathan Doman "UniqueIdentifier", 755ac106bf6SEd Tanous [asyncResp](const boost::system::error_code& ec, 756ac106bf6SEd Tanous const std::string& id) { 7571e1e598dSJonathan Doman if (ec) 75849e429caSJonathan Doman { 75962598e31SEd Tanous BMCWEB_LOG_ERROR("Failed to read cpu unique id: {}", ec); 760ac106bf6SEd Tanous messages::internalError(asyncResp->res); 76149e429caSJonathan Doman return; 76249e429caSJonathan Doman } 763ac106bf6SEd Tanous asyncResp->res 764ac106bf6SEd Tanous .jsonValue["ProcessorId"]["ProtectedIdentificationNumber"] = id; 7651e1e598dSJonathan Doman }); 76649e429caSJonathan Doman } 76749e429caSJonathan Doman 76849e429caSJonathan Doman /** 769c951448aSJonathan Doman * Find the D-Bus object representing the requested Processor, and call the 770c951448aSJonathan Doman * handler with the results. If matching object is not found, add 404 error to 771c951448aSJonathan Doman * response and don't call the handler. 772c951448aSJonathan Doman * 773c951448aSJonathan Doman * @param[in,out] resp Async HTTP response. 774c951448aSJonathan Doman * @param[in] processorId Redfish Processor Id. 775c951448aSJonathan Doman * @param[in] handler Callback to continue processing request upon 776c951448aSJonathan Doman * successfully finding object. 777c951448aSJonathan Doman */ 778c951448aSJonathan Doman template <typename Handler> 7798d1b46d7Szhanghch05 inline void getProcessorObject(const std::shared_ptr<bmcweb::AsyncResp>& resp, 780c951448aSJonathan Doman const std::string& processorId, 781c951448aSJonathan Doman Handler&& handler) 782ac6a4445SGunnar Mills { 78362598e31SEd Tanous BMCWEB_LOG_DEBUG("Get available system processor resources."); 784ac6a4445SGunnar Mills 785c951448aSJonathan Doman // GetSubTree on all interfaces which provide info about a Processor 786dfbf7de5SChris Cain constexpr std::array<std::string_view, 9> interfaces = { 787e99073f5SGeorge Liu "xyz.openbmc_project.Common.UUID", 788e99073f5SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.Asset", 789e99073f5SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.Revision", 790e99073f5SGeorge Liu "xyz.openbmc_project.Inventory.Item.Cpu", 791e99073f5SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.LocationCode", 792e99073f5SGeorge Liu "xyz.openbmc_project.Inventory.Item.Accelerator", 793e99073f5SGeorge Liu "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig", 794dfbf7de5SChris Cain "xyz.openbmc_project.Inventory.Decorator.UniqueIdentifier", 795dfbf7de5SChris Cain "xyz.openbmc_project.Control.Power.Throttle"}; 796e99073f5SGeorge Liu dbus::utility::getSubTree( 797e99073f5SGeorge Liu "/xyz/openbmc_project/inventory", 0, interfaces, 798c951448aSJonathan Doman [resp, processorId, handler = std::forward<Handler>(handler)]( 799e99073f5SGeorge Liu const boost::system::error_code& ec, 800e99073f5SGeorge Liu const dbus::utility::MapperGetSubTreeResponse& subtree) { 801ac6a4445SGunnar Mills if (ec) 802ac6a4445SGunnar Mills { 80362598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error: {}", ec); 804c951448aSJonathan Doman messages::internalError(resp->res); 805ac6a4445SGunnar Mills return; 806ac6a4445SGunnar Mills } 8072bab9831SJonathan Doman for (const auto& [objectPath, serviceMap] : subtree) 808ac6a4445SGunnar Mills { 8092bab9831SJonathan Doman // Ignore any objects which don't end with our desired cpu name 81011ba3979SEd Tanous if (!objectPath.ends_with(processorId)) 811ac6a4445SGunnar Mills { 8122bab9831SJonathan Doman continue; 813ac6a4445SGunnar Mills } 8142bab9831SJonathan Doman 815c951448aSJonathan Doman bool found = false; 816c951448aSJonathan Doman // Filter out objects that don't have the CPU-specific 817c951448aSJonathan Doman // interfaces to make sure we can return 404 on non-CPUs 818c951448aSJonathan Doman // (e.g. /redfish/../Processors/dimm0) 8192bab9831SJonathan Doman for (const auto& [serviceName, interfaceList] : serviceMap) 820ac6a4445SGunnar Mills { 8213544d2a7SEd Tanous if (std::ranges::find_first_of(interfaceList, 8223544d2a7SEd Tanous processorInterfaces) != 8233544d2a7SEd Tanous std::end(interfaceList)) 8242bab9831SJonathan Doman { 825c951448aSJonathan Doman found = true; 826c951448aSJonathan Doman break; 827c951448aSJonathan Doman } 828c951448aSJonathan Doman } 829c951448aSJonathan Doman 830c951448aSJonathan Doman if (!found) 8312bab9831SJonathan Doman { 832c951448aSJonathan Doman continue; 833ac6a4445SGunnar Mills } 834c951448aSJonathan Doman 835c951448aSJonathan Doman // Process the first object which does match our cpu name and 836c951448aSJonathan Doman // required interfaces, and potentially ignore any other 837c951448aSJonathan Doman // matching objects. Assume all interfaces we want to process 838c951448aSJonathan Doman // must be on the same object path. 839c951448aSJonathan Doman 8408a592810SEd Tanous handler(objectPath, serviceMap); 841ac6a4445SGunnar Mills return; 842ac6a4445SGunnar Mills } 843c951448aSJonathan Doman messages::resourceNotFound(resp->res, "Processor", processorId); 844e99073f5SGeorge Liu }); 845ac6a4445SGunnar Mills } 846ac6a4445SGunnar Mills 847bd79bce8SPatrick Williams inline void getProcessorData( 848bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 849bd79bce8SPatrick Williams const std::string& processorId, const std::string& objectPath, 8505df6eda2SShantappa Teekappanavar const dbus::utility::MapperServiceMap& serviceMap) 851c951448aSJonathan Doman { 852c951448aSJonathan Doman for (const auto& [serviceName, interfaceList] : serviceMap) 853c951448aSJonathan Doman { 854c951448aSJonathan Doman for (const auto& interface : interfaceList) 855c951448aSJonathan Doman { 856c951448aSJonathan Doman if (interface == "xyz.openbmc_project.Inventory.Decorator.Asset") 857c951448aSJonathan Doman { 858ac106bf6SEd Tanous getCpuAssetData(asyncResp, serviceName, objectPath); 859c951448aSJonathan Doman } 8600fda0f12SGeorge Liu else if (interface == 8610fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.Revision") 862c951448aSJonathan Doman { 863ac106bf6SEd Tanous getCpuRevisionData(asyncResp, serviceName, objectPath); 864c951448aSJonathan Doman } 865c951448aSJonathan Doman else if (interface == "xyz.openbmc_project.Inventory.Item.Cpu") 866c951448aSJonathan Doman { 867ac106bf6SEd Tanous getCpuDataByService(asyncResp, processorId, serviceName, 868c951448aSJonathan Doman objectPath); 869c951448aSJonathan Doman } 8700fda0f12SGeorge Liu else if (interface == 8710fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Item.Accelerator") 872c951448aSJonathan Doman { 873ac106bf6SEd Tanous getAcceleratorDataByService(asyncResp, processorId, serviceName, 874c951448aSJonathan Doman objectPath); 875c951448aSJonathan Doman } 8760fda0f12SGeorge Liu else if ( 8770fda0f12SGeorge Liu interface == 8780fda0f12SGeorge Liu "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig") 879c951448aSJonathan Doman { 880ac106bf6SEd Tanous getCpuConfigData(asyncResp, processorId, serviceName, 881ac106bf6SEd Tanous objectPath); 882c951448aSJonathan Doman } 8830fda0f12SGeorge Liu else if (interface == 8840fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.LocationCode") 885c951448aSJonathan Doman { 886ac106bf6SEd Tanous getCpuLocationCode(asyncResp, serviceName, objectPath); 887c951448aSJonathan Doman } 88871b82f26SSharad Yadav else if (interface == "xyz.openbmc_project.Common.UUID") 88971b82f26SSharad Yadav { 890ac106bf6SEd Tanous getProcessorUUID(asyncResp, serviceName, objectPath); 89171b82f26SSharad Yadav } 8920fda0f12SGeorge Liu else if (interface == 8930fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.UniqueIdentifier") 89449e429caSJonathan Doman { 895ac106bf6SEd Tanous getCpuUniqueId(asyncResp, serviceName, objectPath); 89649e429caSJonathan Doman } 897dfbf7de5SChris Cain else if (interface == "xyz.openbmc_project.Control.Power.Throttle") 898dfbf7de5SChris Cain { 899ac106bf6SEd Tanous getThrottleProperties(asyncResp, serviceName, objectPath); 900dfbf7de5SChris Cain } 901c951448aSJonathan Doman } 902c951448aSJonathan Doman } 903c951448aSJonathan Doman } 904c951448aSJonathan Doman 905dba0c291SJonathan Doman /** 906dba0c291SJonathan Doman * Request all the properties for the given D-Bus object and fill out the 907dba0c291SJonathan Doman * related entries in the Redfish OperatingConfig response. 908dba0c291SJonathan Doman * 909ac106bf6SEd Tanous * @param[in,out] asyncResp Async HTTP response. 910dba0c291SJonathan Doman * @param[in] service D-Bus service name to query. 911dba0c291SJonathan Doman * @param[in] objPath D-Bus object to query. 912dba0c291SJonathan Doman */ 913bd79bce8SPatrick Williams inline void getOperatingConfigData( 914bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 915bd79bce8SPatrick Williams const std::string& service, 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( 939bd79bce8SPatrick Williams dbus_utils::UnpackErrorPrinter(), properties, 940bd79bce8SPatrick Williams "AvailableCoreCount", availableCoreCount, "BaseSpeed", 941bd79bce8SPatrick Williams baseSpeed, "MaxJunctionTemperature", maxJunctionTemperature, 942bd79bce8SPatrick Williams "MaxSpeed", maxSpeed, "PowerLimit", powerLimit, "TurboProfile", 943bd79bce8SPatrick Williams turboProfile, "BaseSpeedPrioritySettings", 944bd79bce8SPatrick Williams baseSpeedPrioritySettings); 945351053f2SKrzysztof Grobelny 946351053f2SKrzysztof Grobelny if (!success) 947dba0c291SJonathan Doman { 948ac106bf6SEd Tanous messages::internalError(asyncResp->res); 949351053f2SKrzysztof Grobelny return; 950dba0c291SJonathan Doman } 951dba0c291SJonathan Doman 952ac106bf6SEd Tanous nlohmann::json& json = asyncResp->res.jsonValue; 953351053f2SKrzysztof Grobelny 954351053f2SKrzysztof Grobelny if (availableCoreCount != nullptr) 955351053f2SKrzysztof Grobelny { 956351053f2SKrzysztof Grobelny json["TotalAvailableCoreCount"] = *availableCoreCount; 957351053f2SKrzysztof Grobelny } 958351053f2SKrzysztof Grobelny 959351053f2SKrzysztof Grobelny if (baseSpeed != nullptr) 960351053f2SKrzysztof Grobelny { 961351053f2SKrzysztof Grobelny json["BaseSpeedMHz"] = *baseSpeed; 962351053f2SKrzysztof Grobelny } 963351053f2SKrzysztof Grobelny 964351053f2SKrzysztof Grobelny if (maxJunctionTemperature != nullptr) 965351053f2SKrzysztof Grobelny { 966351053f2SKrzysztof Grobelny json["MaxJunctionTemperatureCelsius"] = *maxJunctionTemperature; 967351053f2SKrzysztof Grobelny } 968351053f2SKrzysztof Grobelny 969351053f2SKrzysztof Grobelny if (maxSpeed != nullptr) 970351053f2SKrzysztof Grobelny { 971351053f2SKrzysztof Grobelny json["MaxSpeedMHz"] = *maxSpeed; 972351053f2SKrzysztof Grobelny } 973351053f2SKrzysztof Grobelny 974351053f2SKrzysztof Grobelny if (powerLimit != nullptr) 975351053f2SKrzysztof Grobelny { 976351053f2SKrzysztof Grobelny json["TDPWatts"] = *powerLimit; 977351053f2SKrzysztof Grobelny } 978351053f2SKrzysztof Grobelny 979351053f2SKrzysztof Grobelny if (turboProfile != nullptr) 980351053f2SKrzysztof Grobelny { 981dba0c291SJonathan Doman nlohmann::json& turboArray = json["TurboProfile"]; 982dba0c291SJonathan Doman turboArray = nlohmann::json::array(); 983351053f2SKrzysztof Grobelny for (const auto& [turboSpeed, coreCount] : *turboProfile) 984dba0c291SJonathan Doman { 9851476687dSEd Tanous nlohmann::json::object_t turbo; 9861476687dSEd Tanous turbo["ActiveCoreCount"] = coreCount; 9871476687dSEd Tanous turbo["MaxSpeedMHz"] = turboSpeed; 988b2ba3072SPatrick Williams turboArray.emplace_back(std::move(turbo)); 989dba0c291SJonathan Doman } 990dba0c291SJonathan Doman } 991dba0c291SJonathan Doman 992351053f2SKrzysztof Grobelny if (baseSpeedPrioritySettings != nullptr) 993351053f2SKrzysztof Grobelny { 994bd79bce8SPatrick Williams nlohmann::json& baseSpeedArray = 995bd79bce8SPatrick Williams json["BaseSpeedPrioritySettings"]; 996dba0c291SJonathan Doman baseSpeedArray = nlohmann::json::array(); 997351053f2SKrzysztof Grobelny for (const auto& [baseSpeedMhz, coreList] : 998351053f2SKrzysztof Grobelny *baseSpeedPrioritySettings) 999dba0c291SJonathan Doman { 10001476687dSEd Tanous nlohmann::json::object_t speed; 10011476687dSEd Tanous speed["CoreCount"] = coreList.size(); 10021476687dSEd Tanous speed["CoreIDs"] = coreList; 1003351053f2SKrzysztof Grobelny speed["BaseSpeedMHz"] = baseSpeedMhz; 1004b2ba3072SPatrick Williams baseSpeedArray.emplace_back(std::move(speed)); 1005dba0c291SJonathan Doman } 1006dba0c291SJonathan Doman } 1007351053f2SKrzysztof Grobelny }); 1008dba0c291SJonathan Doman } 1009dba0c291SJonathan Doman 10103cde86f1SJonathan Doman /** 10113cde86f1SJonathan Doman * Handle the PATCH operation of the AppliedOperatingConfig property. Do basic 10123cde86f1SJonathan Doman * validation of the input data, and then set the D-Bus property. 10133cde86f1SJonathan Doman * 10143cde86f1SJonathan Doman * @param[in,out] resp Async HTTP response. 10153cde86f1SJonathan Doman * @param[in] processorId Processor's Id. 10163cde86f1SJonathan Doman * @param[in] appliedConfigUri New property value to apply. 10173cde86f1SJonathan Doman * @param[in] cpuObjectPath Path of CPU object to modify. 10183cde86f1SJonathan Doman * @param[in] serviceMap Service map for CPU object. 10193cde86f1SJonathan Doman */ 10203cde86f1SJonathan Doman inline void patchAppliedOperatingConfig( 10213cde86f1SJonathan Doman const std::shared_ptr<bmcweb::AsyncResp>& resp, 10223cde86f1SJonathan Doman const std::string& processorId, const std::string& appliedConfigUri, 10235df6eda2SShantappa Teekappanavar const std::string& cpuObjectPath, 10245df6eda2SShantappa Teekappanavar const dbus::utility::MapperServiceMap& serviceMap) 10253cde86f1SJonathan Doman { 10263cde86f1SJonathan Doman // Check that the property even exists by checking for the interface 10273cde86f1SJonathan Doman const std::string* controlService = nullptr; 10283cde86f1SJonathan Doman for (const auto& [serviceName, interfaceList] : serviceMap) 10293cde86f1SJonathan Doman { 10303544d2a7SEd Tanous if (std::ranges::find(interfaceList, 10313cde86f1SJonathan Doman "xyz.openbmc_project.Control.Processor." 10323cde86f1SJonathan Doman "CurrentOperatingConfig") != interfaceList.end()) 10333cde86f1SJonathan Doman { 10343cde86f1SJonathan Doman controlService = &serviceName; 10353cde86f1SJonathan Doman break; 10363cde86f1SJonathan Doman } 10373cde86f1SJonathan Doman } 10383cde86f1SJonathan Doman 10393cde86f1SJonathan Doman if (controlService == nullptr) 10403cde86f1SJonathan Doman { 10413cde86f1SJonathan Doman messages::internalError(resp->res); 10423cde86f1SJonathan Doman return; 10433cde86f1SJonathan Doman } 10443cde86f1SJonathan Doman 10453cde86f1SJonathan Doman // Check that the config URI is a child of the cpu URI being patched. 1046253f11b8SEd Tanous std::string expectedPrefix(std::format("/redfish/v1/Systems/{}/Processors/", 1047253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME)); 10483cde86f1SJonathan Doman expectedPrefix += processorId; 10493cde86f1SJonathan Doman expectedPrefix += "/OperatingConfigs/"; 105011ba3979SEd Tanous if (!appliedConfigUri.starts_with(expectedPrefix) || 10513cde86f1SJonathan Doman expectedPrefix.size() == appliedConfigUri.size()) 10523cde86f1SJonathan Doman { 105387c44966SAsmitha Karunanithi messages::propertyValueIncorrect(resp->res, "AppliedOperatingConfig", 105487c44966SAsmitha Karunanithi appliedConfigUri); 10553cde86f1SJonathan Doman return; 10563cde86f1SJonathan Doman } 10573cde86f1SJonathan Doman 10583cde86f1SJonathan Doman // Generate the D-Bus path of the OperatingConfig object, by assuming it's a 10593cde86f1SJonathan Doman // direct child of the CPU object. 10603cde86f1SJonathan Doman // Strip the expectedPrefix from the config URI to get the "filename", and 10613cde86f1SJonathan Doman // append to the CPU's path. 10623cde86f1SJonathan Doman std::string configBaseName = appliedConfigUri.substr(expectedPrefix.size()); 10633cde86f1SJonathan Doman sdbusplus::message::object_path configPath(cpuObjectPath); 10643cde86f1SJonathan Doman configPath /= configBaseName; 10653cde86f1SJonathan Doman 106662598e31SEd Tanous BMCWEB_LOG_INFO("Setting config to {}", configPath.str); 10673cde86f1SJonathan Doman 10683cde86f1SJonathan Doman // Set the property, with handler to check error responses 106987c44966SAsmitha Karunanithi setDbusProperty( 1070e93abac6SGinu George resp, "AppliedOperatingConfig", *controlService, cpuObjectPath, 10719ae226faSGeorge Liu "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig", 1072e93abac6SGinu George "AppliedConfig", configPath); 10733cde86f1SJonathan Doman } 10743cde86f1SJonathan Doman 1075bd79bce8SPatrick Williams inline void handleProcessorHead( 1076bd79bce8SPatrick Williams crow::App& app, const crow::Request& req, 1077ac106bf6SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1078bd79bce8SPatrick Williams const std::string& /* systemName */, const std::string& /* processorId */) 107971a24ca4SNikhil Namjoshi { 1080ac106bf6SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 108171a24ca4SNikhil Namjoshi { 108271a24ca4SNikhil Namjoshi return; 108371a24ca4SNikhil Namjoshi } 1084ac106bf6SEd Tanous asyncResp->res.addHeader( 108571a24ca4SNikhil Namjoshi boost::beast::http::field::link, 108671a24ca4SNikhil Namjoshi "</redfish/v1/JsonSchemas/Processor/Processor.json>; rel=describedby"); 108771a24ca4SNikhil Namjoshi } 108871a24ca4SNikhil Namjoshi 108971a24ca4SNikhil Namjoshi inline void handleProcessorCollectionHead( 109071a24ca4SNikhil Namjoshi crow::App& app, const crow::Request& req, 1091ac106bf6SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 109271a24ca4SNikhil Namjoshi const std::string& /* systemName */) 109371a24ca4SNikhil Namjoshi { 1094ac106bf6SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 109571a24ca4SNikhil Namjoshi { 109671a24ca4SNikhil Namjoshi return; 109771a24ca4SNikhil Namjoshi } 1098ac106bf6SEd Tanous asyncResp->res.addHeader( 109971a24ca4SNikhil Namjoshi boost::beast::http::field::link, 110071a24ca4SNikhil Namjoshi "</redfish/v1/JsonSchemas/ProcessorCollection/ProcessorCollection.json>; rel=describedby"); 110171a24ca4SNikhil Namjoshi } 110271a24ca4SNikhil Namjoshi 11037e860f15SJohn Edward Broadbent inline void requestRoutesOperatingConfigCollection(App& app) 1104dba0c291SJonathan Doman { 11057f3e84a1SEd Tanous BMCWEB_ROUTE(app, 11067f3e84a1SEd Tanous "/redfish/v1/Systems/<str>/Processors/<str>/OperatingConfigs/") 1107ed398213SEd Tanous .privileges(redfish::privileges::getOperatingConfigCollection) 1108bd79bce8SPatrick Williams .methods( 1109bd79bce8SPatrick Williams boost::beast::http::verb:: 1110bd79bce8SPatrick Williams get)([&app](const crow::Request& req, 111145ca1b86SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1112bd79bce8SPatrick Williams const std::string& systemName, 1113bd79bce8SPatrick Williams const std::string& cpuName) { 11143ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 111545ca1b86SEd Tanous { 111645ca1b86SEd Tanous return; 111745ca1b86SEd Tanous } 11187f3e84a1SEd Tanous 111925b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 11207f3e84a1SEd Tanous { 11217f3e84a1SEd Tanous // Option currently returns no systems. TBD 11227f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 11237f3e84a1SEd Tanous systemName); 11247f3e84a1SEd Tanous return; 11257f3e84a1SEd Tanous } 11267f3e84a1SEd Tanous 1127253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 11287f3e84a1SEd Tanous { 11297f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 11307f3e84a1SEd Tanous systemName); 11317f3e84a1SEd Tanous return; 11327f3e84a1SEd Tanous } 11338d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.type"] = 1134dba0c291SJonathan Doman "#OperatingConfigCollection.OperatingConfigCollection"; 1135ef4c65b7SEd Tanous asyncResp->res.jsonValue["@odata.id"] = boost::urls::format( 1136253f11b8SEd Tanous "/redfish/v1/Systems/{}/Processors/{}/OperatingConfigs", 1137253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME, cpuName); 11380fda0f12SGeorge Liu asyncResp->res.jsonValue["Name"] = "Operating Config Collection"; 1139dba0c291SJonathan Doman 11407e860f15SJohn Edward Broadbent // First find the matching CPU object so we know how to 11417e860f15SJohn Edward Broadbent // constrain our search for related Config objects. 11427a1dbc48SGeorge Liu const std::array<std::string_view, 1> interfaces = { 11437a1dbc48SGeorge Liu "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig"}; 11447a1dbc48SGeorge Liu dbus::utility::getSubTreePaths( 11457a1dbc48SGeorge Liu "/xyz/openbmc_project/inventory", 0, interfaces, 1146bd79bce8SPatrick Williams [asyncResp, 1147bd79bce8SPatrick Williams cpuName](const boost::system::error_code& ec, 1148bd79bce8SPatrick Williams const dbus::utility::MapperGetSubTreePathsResponse& 1149bd79bce8SPatrick Williams objects) { 1150dba0c291SJonathan Doman if (ec) 1151dba0c291SJonathan Doman { 1152bd79bce8SPatrick Williams BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec, 1153bd79bce8SPatrick Williams ec.message()); 1154dba0c291SJonathan Doman messages::internalError(asyncResp->res); 1155dba0c291SJonathan Doman return; 1156dba0c291SJonathan Doman } 1157dba0c291SJonathan Doman 1158dba0c291SJonathan Doman for (const std::string& object : objects) 1159dba0c291SJonathan Doman { 116011ba3979SEd Tanous if (!object.ends_with(cpuName)) 1161dba0c291SJonathan Doman { 1162dba0c291SJonathan Doman continue; 1163dba0c291SJonathan Doman } 1164dba0c291SJonathan Doman 11657e860f15SJohn Edward Broadbent // Not expected that there will be multiple matching 11667e860f15SJohn Edward Broadbent // CPU objects, but if there are just use the first 11677e860f15SJohn Edward Broadbent // one. 1168dba0c291SJonathan Doman 11697e860f15SJohn Edward Broadbent // Use the common search routine to construct the 11707e860f15SJohn Edward Broadbent // Collection of all Config objects under this CPU. 11717a1dbc48SGeorge Liu constexpr std::array<std::string_view, 1> interface{ 11725a39f77aSPatrick Williams "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig"}; 1173dba0c291SJonathan Doman collection_util::getCollectionMembers( 1174dba0c291SJonathan Doman asyncResp, 1175ef4c65b7SEd Tanous boost::urls::format( 1176253f11b8SEd Tanous "/redfish/v1/Systems/{}/Processors/{}/OperatingConfigs", 1177253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME, cpuName), 117836b5f1edSLakshmi Yadlapati interface, object); 1179dba0c291SJonathan Doman return; 1180dba0c291SJonathan Doman } 11817a1dbc48SGeorge Liu }); 11827e860f15SJohn Edward Broadbent }); 1183dba0c291SJonathan Doman } 1184dba0c291SJonathan Doman 11857e860f15SJohn Edward Broadbent inline void requestRoutesOperatingConfig(App& app) 1186dba0c291SJonathan Doman { 11877e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 11887e860f15SJohn Edward Broadbent app, 11897f3e84a1SEd Tanous "/redfish/v1/Systems/<str>/Processors/<str>/OperatingConfigs/<str>/") 1190ed398213SEd Tanous .privileges(redfish::privileges::getOperatingConfig) 1191bd79bce8SPatrick Williams .methods( 1192bd79bce8SPatrick Williams boost::beast::http::verb:: 1193bd79bce8SPatrick Williams get)([&app](const crow::Request& req, 119445ca1b86SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1195bd79bce8SPatrick Williams const std::string& systemName, 1196bd79bce8SPatrick Williams const std::string& cpuName, 11977f3e84a1SEd Tanous const std::string& configName) { 11983ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 119945ca1b86SEd Tanous { 120045ca1b86SEd Tanous return; 120145ca1b86SEd Tanous } 120225b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 12037f3e84a1SEd Tanous { 12047f3e84a1SEd Tanous // Option currently returns no systems. TBD 12057f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 12067f3e84a1SEd Tanous systemName); 12077f3e84a1SEd Tanous return; 12087f3e84a1SEd Tanous } 12097f3e84a1SEd Tanous 1210253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 12117f3e84a1SEd Tanous { 12127f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 12137f3e84a1SEd Tanous systemName); 12147f3e84a1SEd Tanous return; 12157f3e84a1SEd Tanous } 12167e860f15SJohn Edward Broadbent // Ask for all objects implementing OperatingConfig so we can search 12177e860f15SJohn Edward Broadbent // for one with a matching name 1218e99073f5SGeorge Liu constexpr std::array<std::string_view, 1> interfaces = { 1219e99073f5SGeorge Liu "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig"}; 1220e99073f5SGeorge Liu dbus::utility::getSubTree( 1221e99073f5SGeorge Liu "/xyz/openbmc_project/inventory", 0, interfaces, 122239662a3bSEd Tanous [asyncResp, cpuName, configName]( 1223e99073f5SGeorge Liu const boost::system::error_code& ec, 12245df6eda2SShantappa Teekappanavar const dbus::utility::MapperGetSubTreeResponse& subtree) { 1225dba0c291SJonathan Doman if (ec) 1226dba0c291SJonathan Doman { 1227bd79bce8SPatrick Williams BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec, 1228bd79bce8SPatrick Williams ec.message()); 1229dba0c291SJonathan Doman messages::internalError(asyncResp->res); 1230dba0c291SJonathan Doman return; 1231dba0c291SJonathan Doman } 1232bd79bce8SPatrick Williams const std::string expectedEnding = 1233bd79bce8SPatrick Williams cpuName + '/' + configName; 1234dba0c291SJonathan Doman for (const auto& [objectPath, serviceMap] : subtree) 1235dba0c291SJonathan Doman { 1236dba0c291SJonathan Doman // Ignore any configs without matching cpuX/configY 1237bd79bce8SPatrick Williams if (!objectPath.ends_with(expectedEnding) || 1238bd79bce8SPatrick Williams serviceMap.empty()) 1239dba0c291SJonathan Doman { 1240dba0c291SJonathan Doman continue; 1241dba0c291SJonathan Doman } 1242dba0c291SJonathan Doman 1243dba0c291SJonathan Doman nlohmann::json& json = asyncResp->res.jsonValue; 1244bd79bce8SPatrick Williams json["@odata.type"] = 1245bd79bce8SPatrick Williams "#OperatingConfig.v1_0_0.OperatingConfig"; 1246ef4c65b7SEd Tanous json["@odata.id"] = boost::urls::format( 1247253f11b8SEd Tanous "/redfish/v1/Systems/{}/Processors/{}/OperatingConfigs/{}", 1248bd79bce8SPatrick Williams BMCWEB_REDFISH_SYSTEM_URI_NAME, cpuName, 1249bd79bce8SPatrick Williams configName); 1250dba0c291SJonathan Doman json["Name"] = "Processor Profile"; 1251dba0c291SJonathan Doman json["Id"] = configName; 1252dba0c291SJonathan Doman 1253dba0c291SJonathan Doman // Just use the first implementation of the object - not 12547e860f15SJohn Edward Broadbent // expected that there would be multiple matching 12557e860f15SJohn Edward Broadbent // services 1256bd79bce8SPatrick Williams getOperatingConfigData( 1257bd79bce8SPatrick Williams asyncResp, serviceMap.begin()->first, objectPath); 1258dba0c291SJonathan Doman return; 1259dba0c291SJonathan Doman } 1260bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, 1261bd79bce8SPatrick Williams "OperatingConfig", configName); 1262e99073f5SGeorge Liu }); 12637e860f15SJohn Edward Broadbent }); 1264ac6a4445SGunnar Mills } 1265ac6a4445SGunnar Mills 12667e860f15SJohn Edward Broadbent inline void requestRoutesProcessorCollection(App& app) 12677e860f15SJohn Edward Broadbent { 1268ac6a4445SGunnar Mills /** 1269ac6a4445SGunnar Mills * Functions triggers appropriate requests on DBus 1270ac6a4445SGunnar Mills */ 127122d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/") 127271a24ca4SNikhil Namjoshi .privileges(redfish::privileges::headProcessorCollection) 127371a24ca4SNikhil Namjoshi .methods(boost::beast::http::verb::head)( 127471a24ca4SNikhil Namjoshi std::bind_front(handleProcessorCollectionHead, std::ref(app))); 127571a24ca4SNikhil Namjoshi 127671a24ca4SNikhil Namjoshi BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/") 1277ed398213SEd Tanous .privileges(redfish::privileges::getProcessorCollection) 1278bd79bce8SPatrick Williams .methods( 1279bd79bce8SPatrick Williams boost::beast::http::verb:: 1280bd79bce8SPatrick Williams get)([&app](const crow::Request& req, 128122d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 128222d268cbSEd Tanous const std::string& systemName) { 12833ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 128445ca1b86SEd Tanous { 128545ca1b86SEd Tanous return; 128645ca1b86SEd Tanous } 128725b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 12887f3e84a1SEd Tanous { 12897f3e84a1SEd Tanous // Option currently returns no systems. TBD 12907f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 12917f3e84a1SEd Tanous systemName); 12927f3e84a1SEd Tanous return; 12937f3e84a1SEd Tanous } 12947f3e84a1SEd Tanous 1295253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 129622d268cbSEd Tanous { 129722d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 129822d268cbSEd Tanous systemName); 129922d268cbSEd Tanous return; 130022d268cbSEd Tanous } 130122d268cbSEd Tanous 130271a24ca4SNikhil Namjoshi asyncResp->res.addHeader( 130371a24ca4SNikhil Namjoshi boost::beast::http::field::link, 130471a24ca4SNikhil Namjoshi "</redfish/v1/JsonSchemas/ProcessorCollection/ProcessorCollection.json>; rel=describedby"); 130571a24ca4SNikhil Namjoshi 13068d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.type"] = 1307ac6a4445SGunnar Mills "#ProcessorCollection.ProcessorCollection"; 13088d1b46d7Szhanghch05 asyncResp->res.jsonValue["Name"] = "Processor Collection"; 1309ac6a4445SGunnar Mills 13108d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.id"] = 1311253f11b8SEd Tanous std::format("/redfish/v1/Systems/{}/Processors", 1312253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 1313ac6a4445SGunnar Mills 131405030b8eSGunnar Mills collection_util::getCollectionMembers( 1315ae9031f0SWilly Tu asyncResp, 1316253f11b8SEd Tanous boost::urls::format("/redfish/v1/Systems/{}/Processors", 1317253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME), 131836b5f1edSLakshmi Yadlapati processorInterfaces, "/xyz/openbmc_project/inventory"); 13197e860f15SJohn Edward Broadbent }); 1320ac6a4445SGunnar Mills } 1321ac6a4445SGunnar Mills 13227e860f15SJohn Edward Broadbent inline void requestRoutesProcessor(App& app) 13237e860f15SJohn Edward Broadbent { 1324ac6a4445SGunnar Mills /** 1325ac6a4445SGunnar Mills * Functions triggers appropriate requests on DBus 1326ac6a4445SGunnar Mills */ 13277e860f15SJohn Edward Broadbent 132822d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/<str>/") 132971a24ca4SNikhil Namjoshi .privileges(redfish::privileges::headProcessor) 133071a24ca4SNikhil Namjoshi .methods(boost::beast::http::verb::head)( 133171a24ca4SNikhil Namjoshi std::bind_front(handleProcessorHead, std::ref(app))); 133271a24ca4SNikhil Namjoshi 133371a24ca4SNikhil Namjoshi BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/<str>/") 1334ed398213SEd Tanous .privileges(redfish::privileges::getProcessor) 1335bd79bce8SPatrick Williams .methods( 1336bd79bce8SPatrick Williams boost::beast::http::verb:: 1337bd79bce8SPatrick Williams get)([&app](const crow::Request& req, 13387e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 133922d268cbSEd Tanous const std::string& systemName, 13407e860f15SJohn Edward Broadbent const std::string& processorId) { 13413ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 134245ca1b86SEd Tanous { 134345ca1b86SEd Tanous return; 134445ca1b86SEd Tanous } 134525b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 13467f3e84a1SEd Tanous { 13477f3e84a1SEd Tanous // Option currently returns no systems. TBD 13487f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 13497f3e84a1SEd Tanous systemName); 13507f3e84a1SEd Tanous return; 13517f3e84a1SEd Tanous } 1352253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 135322d268cbSEd Tanous { 135422d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 135522d268cbSEd Tanous systemName); 135622d268cbSEd Tanous return; 135722d268cbSEd Tanous } 135822d268cbSEd Tanous 135971a24ca4SNikhil Namjoshi asyncResp->res.addHeader( 136071a24ca4SNikhil Namjoshi boost::beast::http::field::link, 136171a24ca4SNikhil Namjoshi "</redfish/v1/JsonSchemas/Processor/Processor.json>; rel=describedby"); 13628d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.type"] = 1363dfbf7de5SChris Cain "#Processor.v1_18_0.Processor"; 1364bd79bce8SPatrick Williams asyncResp->res.jsonValue["@odata.id"] = boost::urls::format( 1365bd79bce8SPatrick Williams "/redfish/v1/Systems/{}/Processors/{}", 1366253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME, processorId); 1367ac6a4445SGunnar Mills 13688a592810SEd Tanous getProcessorObject( 13698a592810SEd Tanous asyncResp, processorId, 13708a592810SEd Tanous std::bind_front(getProcessorData, asyncResp, processorId)); 13717e860f15SJohn Edward Broadbent }); 13723cde86f1SJonathan Doman 137322d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/<str>/") 1374ed398213SEd Tanous .privileges(redfish::privileges::patchProcessor) 13757e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::patch)( 137645ca1b86SEd Tanous [&app](const crow::Request& req, 13777e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 137822d268cbSEd Tanous const std::string& systemName, 13797e860f15SJohn Edward Broadbent const std::string& processorId) { 13803ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 138145ca1b86SEd Tanous { 138245ca1b86SEd Tanous return; 138345ca1b86SEd Tanous } 138425b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 13857f3e84a1SEd Tanous { 13867f3e84a1SEd Tanous // Option currently returns no systems. TBD 13877f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 13887f3e84a1SEd Tanous systemName); 13897f3e84a1SEd Tanous return; 13907f3e84a1SEd Tanous } 1391253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 139222d268cbSEd Tanous { 139322d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 139422d268cbSEd Tanous systemName); 139522d268cbSEd Tanous return; 139622d268cbSEd Tanous } 139722d268cbSEd Tanous 13983c569218SEd Tanous std::optional<std::string> appliedConfigUri; 1399bd79bce8SPatrick Williams if (!json_util::readJsonPatch( 1400*afc474aeSMyung Bae req, asyncResp->res, // 1401*afc474aeSMyung Bae "AppliedOperatingConfig/@odata.id", appliedConfigUri // 1402*afc474aeSMyung Bae )) 14033cde86f1SJonathan Doman { 14043cde86f1SJonathan Doman return; 14053cde86f1SJonathan Doman } 14063cde86f1SJonathan Doman 14073c569218SEd Tanous if (appliedConfigUri) 14083cde86f1SJonathan Doman { 14097e860f15SJohn Edward Broadbent // Check for 404 and find matching D-Bus object, then run 14107e860f15SJohn Edward Broadbent // property patch handlers if that all succeeds. 1411bd79bce8SPatrick Williams getProcessorObject( 14127e860f15SJohn Edward Broadbent asyncResp, processorId, 1413bd79bce8SPatrick Williams std::bind_front(patchAppliedOperatingConfig, asyncResp, 1414bd79bce8SPatrick Williams processorId, *appliedConfigUri)); 14153cde86f1SJonathan Doman } 14167e860f15SJohn Edward Broadbent }); 14173cde86f1SJonathan Doman } 1418ac6a4445SGunnar Mills 1419ac6a4445SGunnar Mills } // namespace redfish 1420