1ac6a4445SGunnar Mills /* 2*6be832e2SEd Tanous Copyright (c) 2018 Intel Corporation 3*6be832e2SEd Tanous 4*6be832e2SEd Tanous Licensed under the Apache License, Version 2.0 (the "License"); 5*6be832e2SEd Tanous you may not use this file except in compliance with the License. 6*6be832e2SEd Tanous You may obtain a copy of the License at 7*6be832e2SEd Tanous 8*6be832e2SEd Tanous http://www.apache.org/licenses/LICENSE-2.0 9*6be832e2SEd Tanous 10*6be832e2SEd Tanous Unless required by applicable law or agreed to in writing, software 11*6be832e2SEd Tanous distributed under the License is distributed on an "AS IS" BASIS, 12*6be832e2SEd Tanous WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*6be832e2SEd Tanous See the License for the specific language governing permissions and 14*6be832e2SEd 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( 1400bd79bce8SPatrick Williams req, asyncResp->res, "AppliedOperatingConfig/@odata.id", 14013c569218SEd Tanous appliedConfigUri)) 14023cde86f1SJonathan Doman { 14033cde86f1SJonathan Doman return; 14043cde86f1SJonathan Doman } 14053cde86f1SJonathan Doman 14063c569218SEd Tanous if (appliedConfigUri) 14073cde86f1SJonathan Doman { 14087e860f15SJohn Edward Broadbent // Check for 404 and find matching D-Bus object, then run 14097e860f15SJohn Edward Broadbent // property patch handlers if that all succeeds. 1410bd79bce8SPatrick Williams getProcessorObject( 14117e860f15SJohn Edward Broadbent asyncResp, processorId, 1412bd79bce8SPatrick Williams std::bind_front(patchAppliedOperatingConfig, asyncResp, 1413bd79bce8SPatrick Williams processorId, *appliedConfigUri)); 14143cde86f1SJonathan Doman } 14157e860f15SJohn Edward Broadbent }); 14163cde86f1SJonathan Doman } 1417ac6a4445SGunnar Mills 1418ac6a4445SGunnar Mills } // namespace redfish 1419