1ac6a4445SGunnar Mills /* 2ac6a4445SGunnar Mills // Copyright (c) 2018 Intel Corporation 3ac6a4445SGunnar Mills // 4ac6a4445SGunnar Mills // Licensed under the Apache License, Version 2.0 (the "License"); 5ac6a4445SGunnar Mills // you may not use this file except in compliance with the License. 6ac6a4445SGunnar Mills // You may obtain a copy of the License at 7ac6a4445SGunnar Mills // 8ac6a4445SGunnar Mills // http://www.apache.org/licenses/LICENSE-2.0 9ac6a4445SGunnar Mills // 10ac6a4445SGunnar Mills // Unless required by applicable law or agreed to in writing, software 11ac6a4445SGunnar Mills // distributed under the License is distributed on an "AS IS" BASIS, 12ac6a4445SGunnar Mills // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ac6a4445SGunnar Mills // See the License for the specific language governing permissions and 14ac6a4445SGunnar Mills // limitations under the License. 15ac6a4445SGunnar Mills */ 16ac6a4445SGunnar Mills #pragma once 17ac6a4445SGunnar Mills 183ccb3adbSEd Tanous #include "app.hpp" 191e1e598dSJonathan Doman #include "dbus_singleton.hpp" 207a1dbc48SGeorge Liu #include "dbus_utility.hpp" 211e1e598dSJonathan Doman #include "error_messages.hpp" 22dfbf7de5SChris Cain #include "generated/enums/processor.hpp" 233ccb3adbSEd Tanous #include "query.hpp" 243ccb3adbSEd Tanous #include "registries/privilege_registry.hpp" 253ccb3adbSEd Tanous #include "utils/collection.hpp" 263ccb3adbSEd Tanous #include "utils/dbus_utils.hpp" 273ccb3adbSEd Tanous #include "utils/json_utils.hpp" 28ac6a4445SGunnar Mills 29ac6a4445SGunnar Mills #include <boost/container/flat_map.hpp> 30e99073f5SGeorge Liu #include <boost/system/error_code.hpp> 31ef4c65b7SEd Tanous #include <boost/url/format.hpp> 321e1e598dSJonathan Doman #include <sdbusplus/asio/property.hpp> 33dba0c291SJonathan Doman #include <sdbusplus/message/native_types.hpp> 34351053f2SKrzysztof Grobelny #include <sdbusplus/unpack_properties.hpp> 35dba0c291SJonathan Doman #include <sdbusplus/utility/dedup_variant.hpp> 36ac6a4445SGunnar Mills 377a1dbc48SGeorge Liu #include <array> 38b9d679d1SMichael Shen #include <limits> 393544d2a7SEd Tanous #include <ranges> 403c569218SEd Tanous #include <string> 417a1dbc48SGeorge Liu #include <string_view> 427a1dbc48SGeorge Liu 43ac6a4445SGunnar Mills namespace redfish 44ac6a4445SGunnar Mills { 45ac6a4445SGunnar Mills 46c951448aSJonathan Doman // Interfaces which imply a D-Bus object represents a Processor 477a1dbc48SGeorge Liu constexpr std::array<std::string_view, 2> processorInterfaces = { 48c951448aSJonathan Doman "xyz.openbmc_project.Inventory.Item.Cpu", 49c951448aSJonathan Doman "xyz.openbmc_project.Inventory.Item.Accelerator"}; 502bab9831SJonathan Doman 5171b82f26SSharad Yadav /** 5271b82f26SSharad Yadav * @brief Fill out uuid info of a processor by 5371b82f26SSharad Yadav * requesting data from the given D-Bus object. 5471b82f26SSharad Yadav * 55ac106bf6SEd Tanous * @param[in,out] asyncResp Async HTTP response. 5671b82f26SSharad Yadav * @param[in] service D-Bus service to query. 5771b82f26SSharad Yadav * @param[in] objPath D-Bus object to query. 5871b82f26SSharad Yadav */ 59ac106bf6SEd Tanous inline void getProcessorUUID(std::shared_ptr<bmcweb::AsyncResp> asyncResp, 6071b82f26SSharad Yadav const std::string& service, 6171b82f26SSharad Yadav const std::string& objPath) 6271b82f26SSharad Yadav { 6362598e31SEd Tanous BMCWEB_LOG_DEBUG("Get Processor UUID"); 641e1e598dSJonathan Doman sdbusplus::asio::getProperty<std::string>( 651e1e598dSJonathan Doman *crow::connections::systemBus, service, objPath, 661e1e598dSJonathan Doman "xyz.openbmc_project.Common.UUID", "UUID", 67ac106bf6SEd Tanous [objPath, asyncResp{std::move(asyncResp)}]( 68ac106bf6SEd Tanous const boost::system::error_code& ec, const std::string& property) { 6971b82f26SSharad Yadav if (ec) 7071b82f26SSharad Yadav { 7162598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error"); 72ac106bf6SEd Tanous messages::internalError(asyncResp->res); 7371b82f26SSharad Yadav return; 7471b82f26SSharad Yadav } 75ac106bf6SEd Tanous asyncResp->res.jsonValue["UUID"] = property; 761e1e598dSJonathan Doman }); 7771b82f26SSharad Yadav } 7871b82f26SSharad Yadav 79711ac7a9SEd Tanous inline void getCpuDataByInterface( 80ac106bf6SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 8180f79a40SMichael Shen const dbus::utility::DBusInterfacesMap& cpuInterfacesProperties) 82ac6a4445SGunnar Mills { 8362598e31SEd Tanous BMCWEB_LOG_DEBUG("Get CPU resources by interface."); 84ac6a4445SGunnar Mills 85a1649ec6SChicago Duan // Set the default value of state 86ac106bf6SEd Tanous asyncResp->res.jsonValue["Status"]["State"] = "Enabled"; 87ac106bf6SEd Tanous asyncResp->res.jsonValue["Status"]["Health"] = "OK"; 88ac6a4445SGunnar Mills 89ac6a4445SGunnar Mills for (const auto& interface : cpuInterfacesProperties) 90ac6a4445SGunnar Mills { 91ac6a4445SGunnar Mills for (const auto& property : interface.second) 92ac6a4445SGunnar Mills { 93a1649ec6SChicago Duan if (property.first == "Present") 94ac6a4445SGunnar Mills { 95a1649ec6SChicago Duan const bool* cpuPresent = std::get_if<bool>(&property.second); 96a1649ec6SChicago Duan if (cpuPresent == nullptr) 97ac6a4445SGunnar Mills { 98ac6a4445SGunnar Mills // Important property not in desired type 99ac106bf6SEd Tanous messages::internalError(asyncResp->res); 100ac6a4445SGunnar Mills return; 101ac6a4445SGunnar Mills } 102e05aec50SEd Tanous if (!*cpuPresent) 103ac6a4445SGunnar Mills { 104a1649ec6SChicago Duan // Slot is not populated 105ac106bf6SEd Tanous asyncResp->res.jsonValue["Status"]["State"] = "Absent"; 106a1649ec6SChicago Duan } 107a1649ec6SChicago Duan } 108a1649ec6SChicago Duan else if (property.first == "Functional") 109a1649ec6SChicago Duan { 110a1649ec6SChicago Duan const bool* cpuFunctional = std::get_if<bool>(&property.second); 111a1649ec6SChicago Duan if (cpuFunctional == nullptr) 112a1649ec6SChicago Duan { 113ac106bf6SEd Tanous messages::internalError(asyncResp->res); 114ac6a4445SGunnar Mills return; 115ac6a4445SGunnar Mills } 116e05aec50SEd Tanous if (!*cpuFunctional) 117a1649ec6SChicago Duan { 118ac106bf6SEd Tanous asyncResp->res.jsonValue["Status"]["Health"] = "Critical"; 119a1649ec6SChicago Duan } 120a1649ec6SChicago Duan } 121a1649ec6SChicago Duan else if (property.first == "CoreCount") 122a1649ec6SChicago Duan { 123a1649ec6SChicago Duan const uint16_t* coresCount = 124a1649ec6SChicago Duan std::get_if<uint16_t>(&property.second); 125a1649ec6SChicago Duan if (coresCount == nullptr) 126a1649ec6SChicago Duan { 127ac106bf6SEd Tanous messages::internalError(asyncResp->res); 128a1649ec6SChicago Duan return; 129a1649ec6SChicago Duan } 130ac106bf6SEd Tanous asyncResp->res.jsonValue["TotalCores"] = *coresCount; 131ac6a4445SGunnar Mills } 132dc3fa667SJonathan Doman else if (property.first == "MaxSpeedInMhz") 133dc3fa667SJonathan Doman { 134dc3fa667SJonathan Doman const uint32_t* value = std::get_if<uint32_t>(&property.second); 135dc3fa667SJonathan Doman if (value != nullptr) 136dc3fa667SJonathan Doman { 137ac106bf6SEd Tanous asyncResp->res.jsonValue["MaxSpeedMHz"] = *value; 138dc3fa667SJonathan Doman } 139dc3fa667SJonathan Doman } 140ac6a4445SGunnar Mills else if (property.first == "Socket") 141ac6a4445SGunnar Mills { 142ac6a4445SGunnar Mills const std::string* value = 143ac6a4445SGunnar Mills std::get_if<std::string>(&property.second); 144ac6a4445SGunnar Mills if (value != nullptr) 145ac6a4445SGunnar Mills { 146ac106bf6SEd Tanous asyncResp->res.jsonValue["Socket"] = *value; 147ac6a4445SGunnar Mills } 148ac6a4445SGunnar Mills } 149ac6a4445SGunnar Mills else if (property.first == "ThreadCount") 150ac6a4445SGunnar Mills { 151dc3fa667SJonathan Doman const uint16_t* value = std::get_if<uint16_t>(&property.second); 152ac6a4445SGunnar Mills if (value != nullptr) 153ac6a4445SGunnar Mills { 154ac106bf6SEd Tanous asyncResp->res.jsonValue["TotalThreads"] = *value; 155ac6a4445SGunnar Mills } 156ac6a4445SGunnar Mills } 1571930fbd4SBrandon Kim else if (property.first == "EffectiveFamily") 158ac6a4445SGunnar Mills { 1591930fbd4SBrandon Kim const uint16_t* value = std::get_if<uint16_t>(&property.second); 1606169de2cSBrad Bishop if (value != nullptr && *value != 2) 161ac6a4445SGunnar Mills { 162ac106bf6SEd Tanous asyncResp->res.jsonValue["ProcessorId"]["EffectiveFamily"] = 163866e4862SEd Tanous "0x" + intToHexString(*value, 4); 164ac6a4445SGunnar Mills } 165ac6a4445SGunnar Mills } 1661930fbd4SBrandon Kim else if (property.first == "EffectiveModel") 1671930fbd4SBrandon Kim { 1681930fbd4SBrandon Kim const uint16_t* value = std::get_if<uint16_t>(&property.second); 1691930fbd4SBrandon Kim if (value == nullptr) 1701930fbd4SBrandon Kim { 171ac106bf6SEd Tanous messages::internalError(asyncResp->res); 1721930fbd4SBrandon Kim return; 1731930fbd4SBrandon Kim } 1746169de2cSBrad Bishop if (*value != 0) 1756169de2cSBrad Bishop { 176ac106bf6SEd Tanous asyncResp->res.jsonValue["ProcessorId"]["EffectiveModel"] = 177866e4862SEd Tanous "0x" + intToHexString(*value, 4); 1781930fbd4SBrandon Kim } 1796169de2cSBrad Bishop } 180ac6a4445SGunnar Mills else if (property.first == "Id") 181ac6a4445SGunnar Mills { 182ac6a4445SGunnar Mills const uint64_t* value = std::get_if<uint64_t>(&property.second); 183ac6a4445SGunnar Mills if (value != nullptr && *value != 0) 184ac6a4445SGunnar Mills { 185ac106bf6SEd Tanous asyncResp->res 186ac6a4445SGunnar Mills .jsonValue["ProcessorId"]["IdentificationRegisters"] = 187866e4862SEd Tanous "0x" + intToHexString(*value, 16); 188ac6a4445SGunnar Mills } 189ac6a4445SGunnar Mills } 1901930fbd4SBrandon Kim else if (property.first == "Microcode") 1911930fbd4SBrandon Kim { 1921930fbd4SBrandon Kim const uint32_t* value = std::get_if<uint32_t>(&property.second); 1931930fbd4SBrandon Kim if (value == nullptr) 1941930fbd4SBrandon Kim { 195ac106bf6SEd Tanous messages::internalError(asyncResp->res); 1961930fbd4SBrandon Kim return; 1971930fbd4SBrandon Kim } 1986169de2cSBrad Bishop if (*value != 0) 1996169de2cSBrad Bishop { 200ac106bf6SEd Tanous asyncResp->res.jsonValue["ProcessorId"]["MicrocodeInfo"] = 201866e4862SEd Tanous "0x" + intToHexString(*value, 8); 2021930fbd4SBrandon Kim } 2036169de2cSBrad Bishop } 2041930fbd4SBrandon Kim else if (property.first == "Step") 2051930fbd4SBrandon Kim { 2061930fbd4SBrandon Kim const uint16_t* value = std::get_if<uint16_t>(&property.second); 2071930fbd4SBrandon Kim if (value == nullptr) 2081930fbd4SBrandon Kim { 209ac106bf6SEd Tanous messages::internalError(asyncResp->res); 2101930fbd4SBrandon Kim return; 2111930fbd4SBrandon Kim } 212b9d679d1SMichael Shen if (*value != std::numeric_limits<uint16_t>::max()) 2136169de2cSBrad Bishop { 214ac106bf6SEd Tanous asyncResp->res.jsonValue["ProcessorId"]["Step"] = 215866e4862SEd Tanous "0x" + intToHexString(*value, 4); 2161930fbd4SBrandon Kim } 217ac6a4445SGunnar Mills } 218ac6a4445SGunnar Mills } 219ac6a4445SGunnar Mills } 2206169de2cSBrad Bishop } 221ac6a4445SGunnar Mills 222ac106bf6SEd Tanous inline void getCpuDataByService(std::shared_ptr<bmcweb::AsyncResp> asyncResp, 223ac6a4445SGunnar Mills const std::string& cpuId, 224ac6a4445SGunnar Mills const std::string& service, 225ac6a4445SGunnar Mills const std::string& objPath) 226ac6a4445SGunnar Mills { 22762598e31SEd Tanous BMCWEB_LOG_DEBUG("Get available system cpu resources by service."); 228ac6a4445SGunnar Mills 2295eb468daSGeorge Liu sdbusplus::message::object_path path("/xyz/openbmc_project/inventory"); 2305eb468daSGeorge Liu dbus::utility::getManagedObjects( 2315eb468daSGeorge Liu service, path, 232ac106bf6SEd Tanous [cpuId, service, objPath, asyncResp{std::move(asyncResp)}]( 2335e7e2dc5SEd Tanous const boost::system::error_code& ec, 234ac6a4445SGunnar Mills const dbus::utility::ManagedObjectType& dbusData) { 235ac6a4445SGunnar Mills if (ec) 236ac6a4445SGunnar Mills { 23762598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error"); 238ac106bf6SEd Tanous messages::internalError(asyncResp->res); 239ac6a4445SGunnar Mills return; 240ac6a4445SGunnar Mills } 241ac106bf6SEd Tanous asyncResp->res.jsonValue["Id"] = cpuId; 242ac106bf6SEd Tanous asyncResp->res.jsonValue["Name"] = "Processor"; 243ac106bf6SEd Tanous asyncResp->res.jsonValue["ProcessorType"] = "CPU"; 244ac6a4445SGunnar Mills 245ac6a4445SGunnar Mills bool slotPresent = false; 246ac6a4445SGunnar Mills std::string corePath = objPath + "/core"; 247ac6a4445SGunnar Mills size_t totalCores = 0; 248ac6a4445SGunnar Mills for (const auto& object : dbusData) 249ac6a4445SGunnar Mills { 250ac6a4445SGunnar Mills if (object.first.str == objPath) 251ac6a4445SGunnar Mills { 252ac106bf6SEd Tanous getCpuDataByInterface(asyncResp, object.second); 253ac6a4445SGunnar Mills } 25411ba3979SEd Tanous else if (object.first.str.starts_with(corePath)) 255ac6a4445SGunnar Mills { 256ac6a4445SGunnar Mills for (const auto& interface : object.second) 257ac6a4445SGunnar Mills { 258002d39b4SEd Tanous if (interface.first == "xyz.openbmc_project.Inventory.Item") 259ac6a4445SGunnar Mills { 260ac6a4445SGunnar Mills for (const auto& property : interface.second) 261ac6a4445SGunnar Mills { 262ac6a4445SGunnar Mills if (property.first == "Present") 263ac6a4445SGunnar Mills { 264ac6a4445SGunnar Mills const bool* present = 265ac6a4445SGunnar Mills std::get_if<bool>(&property.second); 266ac6a4445SGunnar Mills if (present != nullptr) 267ac6a4445SGunnar Mills { 268e05aec50SEd Tanous if (*present) 269ac6a4445SGunnar Mills { 270ac6a4445SGunnar Mills slotPresent = true; 271ac6a4445SGunnar Mills totalCores++; 272ac6a4445SGunnar Mills } 273ac6a4445SGunnar Mills } 274ac6a4445SGunnar Mills } 275ac6a4445SGunnar Mills } 276ac6a4445SGunnar Mills } 277ac6a4445SGunnar Mills } 278ac6a4445SGunnar Mills } 279ac6a4445SGunnar Mills } 280ac6a4445SGunnar Mills // In getCpuDataByInterface(), state and health are set 281ac6a4445SGunnar Mills // based on the present and functional status. If core 282ac6a4445SGunnar Mills // count is zero, then it has a higher precedence. 283ac6a4445SGunnar Mills if (slotPresent) 284ac6a4445SGunnar Mills { 285ac106bf6SEd Tanous asyncResp->res.jsonValue["TotalCores"] = totalCores; 286ac6a4445SGunnar Mills } 287ac6a4445SGunnar Mills return; 2885eb468daSGeorge Liu }); 289ac6a4445SGunnar Mills } 290ac6a4445SGunnar Mills 291dfbf7de5SChris Cain /** 292dfbf7de5SChris Cain * @brief Translates throttle cause DBUS property to redfish. 293dfbf7de5SChris Cain * 294dfbf7de5SChris Cain * @param[in] dbusSource The throttle cause from DBUS 295dfbf7de5SChris Cain * 296dfbf7de5SChris Cain * @return Returns as a string, the throttle cause in Redfish terms. If 297dfbf7de5SChris Cain * translation cannot be done, returns "Unknown" throttle reason. 298dfbf7de5SChris Cain */ 299dfbf7de5SChris Cain inline processor::ThrottleCause 300dfbf7de5SChris Cain dbusToRfThrottleCause(const std::string& dbusSource) 301dfbf7de5SChris Cain { 302dfbf7de5SChris Cain if (dbusSource == 303dfbf7de5SChris Cain "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.ClockLimit") 304dfbf7de5SChris Cain { 305dfbf7de5SChris Cain return processor::ThrottleCause::ClockLimit; 306dfbf7de5SChris Cain } 307dfbf7de5SChris Cain if (dbusSource == 308dfbf7de5SChris Cain "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.ManagementDetectedFault") 309dfbf7de5SChris Cain { 310dfbf7de5SChris Cain return processor::ThrottleCause::ManagementDetectedFault; 311dfbf7de5SChris Cain } 312dfbf7de5SChris Cain if (dbusSource == 313dfbf7de5SChris Cain "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.PowerLimit") 314dfbf7de5SChris Cain { 315dfbf7de5SChris Cain return processor::ThrottleCause::PowerLimit; 316dfbf7de5SChris Cain } 317dfbf7de5SChris Cain if (dbusSource == 318dfbf7de5SChris Cain "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.ThermalLimit") 319dfbf7de5SChris Cain { 320dfbf7de5SChris Cain return processor::ThrottleCause::ThermalLimit; 321dfbf7de5SChris Cain } 322dfbf7de5SChris Cain if (dbusSource == 323dfbf7de5SChris Cain "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.Unknown") 324dfbf7de5SChris Cain { 325dfbf7de5SChris Cain return processor::ThrottleCause::Unknown; 326dfbf7de5SChris Cain } 327dfbf7de5SChris Cain return processor::ThrottleCause::Invalid; 328dfbf7de5SChris Cain } 329dfbf7de5SChris Cain 330dfbf7de5SChris Cain inline void 331ac106bf6SEd Tanous readThrottleProperties(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 332dfbf7de5SChris Cain const boost::system::error_code& ec, 333dfbf7de5SChris Cain const dbus::utility::DBusPropertiesMap& properties) 334dfbf7de5SChris Cain { 335dfbf7de5SChris Cain if (ec) 336dfbf7de5SChris Cain { 33762598e31SEd Tanous BMCWEB_LOG_ERROR("Processor Throttle getAllProperties error {}", ec); 338ac106bf6SEd Tanous messages::internalError(asyncResp->res); 339dfbf7de5SChris Cain return; 340dfbf7de5SChris Cain } 341dfbf7de5SChris Cain 342dfbf7de5SChris Cain const bool* status = nullptr; 343dfbf7de5SChris Cain const std::vector<std::string>* causes = nullptr; 344dfbf7de5SChris Cain 345dfbf7de5SChris Cain if (!sdbusplus::unpackPropertiesNoThrow(dbus_utils::UnpackErrorPrinter(), 346dfbf7de5SChris Cain properties, "Throttled", status, 347dfbf7de5SChris Cain "ThrottleCauses", causes)) 348dfbf7de5SChris Cain { 349ac106bf6SEd Tanous messages::internalError(asyncResp->res); 350dfbf7de5SChris Cain return; 351dfbf7de5SChris Cain } 352dfbf7de5SChris Cain 353ac106bf6SEd Tanous asyncResp->res.jsonValue["Throttled"] = *status; 354dfbf7de5SChris Cain nlohmann::json::array_t rCauses; 355dfbf7de5SChris Cain for (const std::string& cause : *causes) 356dfbf7de5SChris Cain { 357dfbf7de5SChris Cain processor::ThrottleCause rfCause = dbusToRfThrottleCause(cause); 358dfbf7de5SChris Cain if (rfCause == processor::ThrottleCause::Invalid) 359dfbf7de5SChris Cain { 360ac106bf6SEd Tanous messages::internalError(asyncResp->res); 361dfbf7de5SChris Cain return; 362dfbf7de5SChris Cain } 363dfbf7de5SChris Cain 364dfbf7de5SChris Cain rCauses.emplace_back(rfCause); 365dfbf7de5SChris Cain } 366ac106bf6SEd Tanous asyncResp->res.jsonValue["ThrottleCauses"] = std::move(rCauses); 367dfbf7de5SChris Cain } 368dfbf7de5SChris Cain 369dfbf7de5SChris Cain inline void 370ac106bf6SEd Tanous getThrottleProperties(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 371dfbf7de5SChris Cain const std::string& service, 372dfbf7de5SChris Cain const std::string& objectPath) 373dfbf7de5SChris Cain { 37462598e31SEd Tanous BMCWEB_LOG_DEBUG("Get processor throttle resources"); 375dfbf7de5SChris Cain 376dfbf7de5SChris Cain sdbusplus::asio::getAllProperties( 377dfbf7de5SChris Cain *crow::connections::systemBus, service, objectPath, 378dfbf7de5SChris Cain "xyz.openbmc_project.Control.Power.Throttle", 379ac106bf6SEd Tanous [asyncResp](const boost::system::error_code& ec, 380dfbf7de5SChris Cain const dbus::utility::DBusPropertiesMap& properties) { 381ac106bf6SEd Tanous readThrottleProperties(asyncResp, ec, properties); 382dfbf7de5SChris Cain }); 383dfbf7de5SChris Cain } 384dfbf7de5SChris Cain 385ac106bf6SEd Tanous inline void getCpuAssetData(std::shared_ptr<bmcweb::AsyncResp> asyncResp, 386ac6a4445SGunnar Mills const std::string& service, 387ac6a4445SGunnar Mills const std::string& objPath) 388ac6a4445SGunnar Mills { 38962598e31SEd Tanous BMCWEB_LOG_DEBUG("Get Cpu Asset Data"); 390351053f2SKrzysztof Grobelny sdbusplus::asio::getAllProperties( 391351053f2SKrzysztof Grobelny *crow::connections::systemBus, service, objPath, 392351053f2SKrzysztof Grobelny "xyz.openbmc_project.Inventory.Decorator.Asset", 393ac106bf6SEd Tanous [objPath, asyncResp{std::move(asyncResp)}]( 3945e7e2dc5SEd Tanous const boost::system::error_code& ec, 395351053f2SKrzysztof Grobelny const dbus::utility::DBusPropertiesMap& properties) { 396ac6a4445SGunnar Mills if (ec) 397ac6a4445SGunnar Mills { 39862598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error"); 399ac106bf6SEd Tanous messages::internalError(asyncResp->res); 400ac6a4445SGunnar Mills return; 401ac6a4445SGunnar Mills } 402ac6a4445SGunnar Mills 403351053f2SKrzysztof Grobelny const std::string* serialNumber = nullptr; 404351053f2SKrzysztof Grobelny const std::string* model = nullptr; 405351053f2SKrzysztof Grobelny const std::string* manufacturer = nullptr; 406351053f2SKrzysztof Grobelny const std::string* partNumber = nullptr; 407351053f2SKrzysztof Grobelny const std::string* sparePartNumber = nullptr; 408351053f2SKrzysztof Grobelny 409351053f2SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 410351053f2SKrzysztof Grobelny dbus_utils::UnpackErrorPrinter(), properties, "SerialNumber", 411351053f2SKrzysztof Grobelny serialNumber, "Model", model, "Manufacturer", manufacturer, 412351053f2SKrzysztof Grobelny "PartNumber", partNumber, "SparePartNumber", sparePartNumber); 413351053f2SKrzysztof Grobelny 414351053f2SKrzysztof Grobelny if (!success) 415ac6a4445SGunnar Mills { 416ac106bf6SEd Tanous messages::internalError(asyncResp->res); 417351053f2SKrzysztof Grobelny return; 418ac6a4445SGunnar Mills } 419351053f2SKrzysztof Grobelny 420351053f2SKrzysztof Grobelny if (serialNumber != nullptr && !serialNumber->empty()) 421ac6a4445SGunnar Mills { 422ac106bf6SEd Tanous asyncResp->res.jsonValue["SerialNumber"] = *serialNumber; 423351053f2SKrzysztof Grobelny } 424351053f2SKrzysztof Grobelny 425351053f2SKrzysztof Grobelny if ((model != nullptr) && !model->empty()) 426ac6a4445SGunnar Mills { 427ac106bf6SEd Tanous asyncResp->res.jsonValue["Model"] = *model; 428ac6a4445SGunnar Mills } 429ac6a4445SGunnar Mills 430351053f2SKrzysztof Grobelny if (manufacturer != nullptr) 431ac6a4445SGunnar Mills { 432ac106bf6SEd Tanous asyncResp->res.jsonValue["Manufacturer"] = *manufacturer; 433ac6a4445SGunnar Mills 434ac6a4445SGunnar Mills // Otherwise would be unexpected. 435351053f2SKrzysztof Grobelny if (manufacturer->find("Intel") != std::string::npos) 436ac6a4445SGunnar Mills { 437ac106bf6SEd Tanous asyncResp->res.jsonValue["ProcessorArchitecture"] = "x86"; 438ac106bf6SEd Tanous asyncResp->res.jsonValue["InstructionSet"] = "x86-64"; 439ac6a4445SGunnar Mills } 440351053f2SKrzysztof Grobelny else if (manufacturer->find("IBM") != std::string::npos) 441ac6a4445SGunnar Mills { 442ac106bf6SEd Tanous asyncResp->res.jsonValue["ProcessorArchitecture"] = "Power"; 443ac106bf6SEd Tanous asyncResp->res.jsonValue["InstructionSet"] = "PowerISA"; 444ac6a4445SGunnar Mills } 445ac6a4445SGunnar Mills } 446cba4f448SSunnySrivastava1984 447351053f2SKrzysztof Grobelny if (partNumber != nullptr) 448cba4f448SSunnySrivastava1984 { 449ac106bf6SEd Tanous asyncResp->res.jsonValue["PartNumber"] = *partNumber; 450cba4f448SSunnySrivastava1984 } 451cba4f448SSunnySrivastava1984 4526169de2cSBrad Bishop if (sparePartNumber != nullptr && !sparePartNumber->empty()) 453cba4f448SSunnySrivastava1984 { 454ac106bf6SEd Tanous asyncResp->res.jsonValue["SparePartNumber"] = *sparePartNumber; 455cba4f448SSunnySrivastava1984 } 456351053f2SKrzysztof Grobelny }); 457ac6a4445SGunnar Mills } 458ac6a4445SGunnar Mills 459ac106bf6SEd Tanous inline void getCpuRevisionData(std::shared_ptr<bmcweb::AsyncResp> asyncResp, 460ac6a4445SGunnar Mills const std::string& service, 461ac6a4445SGunnar Mills const std::string& objPath) 462ac6a4445SGunnar Mills { 46362598e31SEd Tanous BMCWEB_LOG_DEBUG("Get Cpu Revision Data"); 464351053f2SKrzysztof Grobelny sdbusplus::asio::getAllProperties( 465351053f2SKrzysztof Grobelny *crow::connections::systemBus, service, objPath, 466351053f2SKrzysztof Grobelny "xyz.openbmc_project.Inventory.Decorator.Revision", 467ac106bf6SEd Tanous [objPath, asyncResp{std::move(asyncResp)}]( 4685e7e2dc5SEd Tanous const boost::system::error_code& ec, 469351053f2SKrzysztof Grobelny const dbus::utility::DBusPropertiesMap& properties) { 470ac6a4445SGunnar Mills if (ec) 471ac6a4445SGunnar Mills { 47262598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error"); 473ac106bf6SEd Tanous messages::internalError(asyncResp->res); 474ac6a4445SGunnar Mills return; 475ac6a4445SGunnar Mills } 476ac6a4445SGunnar Mills 477351053f2SKrzysztof Grobelny const std::string* version = nullptr; 478351053f2SKrzysztof Grobelny 479351053f2SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 480351053f2SKrzysztof Grobelny dbus_utils::UnpackErrorPrinter(), properties, "Version", version); 481351053f2SKrzysztof Grobelny 482351053f2SKrzysztof Grobelny if (!success) 483ac6a4445SGunnar Mills { 484ac106bf6SEd Tanous messages::internalError(asyncResp->res); 485351053f2SKrzysztof Grobelny return; 486351053f2SKrzysztof Grobelny } 487351053f2SKrzysztof Grobelny 488351053f2SKrzysztof Grobelny if (version != nullptr) 489ac6a4445SGunnar Mills { 490ac106bf6SEd Tanous asyncResp->res.jsonValue["Version"] = *version; 491ac6a4445SGunnar Mills } 492351053f2SKrzysztof Grobelny }); 493ac6a4445SGunnar Mills } 494ac6a4445SGunnar Mills 4958d1b46d7Szhanghch05 inline void getAcceleratorDataByService( 496ac106bf6SEd Tanous std::shared_ptr<bmcweb::AsyncResp> asyncResp, const std::string& acclrtrId, 4978d1b46d7Szhanghch05 const std::string& service, const std::string& objPath) 498ac6a4445SGunnar Mills { 49962598e31SEd Tanous BMCWEB_LOG_DEBUG("Get available system Accelerator resources by service."); 500351053f2SKrzysztof Grobelny sdbusplus::asio::getAllProperties( 501351053f2SKrzysztof Grobelny *crow::connections::systemBus, service, objPath, "", 502ac106bf6SEd Tanous [acclrtrId, asyncResp{std::move(asyncResp)}]( 5035e7e2dc5SEd Tanous const boost::system::error_code& ec, 504351053f2SKrzysztof Grobelny const dbus::utility::DBusPropertiesMap& properties) { 505ac6a4445SGunnar Mills if (ec) 506ac6a4445SGunnar Mills { 50762598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error"); 508ac106bf6SEd Tanous messages::internalError(asyncResp->res); 509ac6a4445SGunnar Mills return; 510ac6a4445SGunnar Mills } 511ac6a4445SGunnar Mills 512351053f2SKrzysztof Grobelny const bool* functional = nullptr; 513351053f2SKrzysztof Grobelny const bool* present = nullptr; 514351053f2SKrzysztof Grobelny 515351053f2SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 516351053f2SKrzysztof Grobelny dbus_utils::UnpackErrorPrinter(), properties, "Functional", 517351053f2SKrzysztof Grobelny functional, "Present", present); 518351053f2SKrzysztof Grobelny 519351053f2SKrzysztof Grobelny if (!success) 520ac6a4445SGunnar Mills { 521ac106bf6SEd Tanous messages::internalError(asyncResp->res); 522351053f2SKrzysztof Grobelny return; 523ac6a4445SGunnar Mills } 524ac6a4445SGunnar Mills 525ac6a4445SGunnar Mills std::string state = "Enabled"; 526ac6a4445SGunnar Mills std::string health = "OK"; 527ac6a4445SGunnar Mills 528351053f2SKrzysztof Grobelny if (present != nullptr && !*present) 529ac6a4445SGunnar Mills { 530ac6a4445SGunnar Mills state = "Absent"; 531ac6a4445SGunnar Mills } 532ac6a4445SGunnar Mills 533351053f2SKrzysztof Grobelny if (functional != nullptr && !*functional) 534ac6a4445SGunnar Mills { 535ac6a4445SGunnar Mills if (state == "Enabled") 536ac6a4445SGunnar Mills { 537ac6a4445SGunnar Mills health = "Critical"; 538ac6a4445SGunnar Mills } 539ac6a4445SGunnar Mills } 540ac6a4445SGunnar Mills 541ac106bf6SEd Tanous asyncResp->res.jsonValue["Id"] = acclrtrId; 542ac106bf6SEd Tanous asyncResp->res.jsonValue["Name"] = "Processor"; 543ac106bf6SEd Tanous asyncResp->res.jsonValue["Status"]["State"] = state; 544ac106bf6SEd Tanous asyncResp->res.jsonValue["Status"]["Health"] = health; 545ac106bf6SEd Tanous asyncResp->res.jsonValue["ProcessorType"] = "Accelerator"; 546351053f2SKrzysztof Grobelny }); 547ac6a4445SGunnar Mills } 548ac6a4445SGunnar Mills 549dba0c291SJonathan Doman // OperatingConfig D-Bus Types 550dba0c291SJonathan Doman using TurboProfileProperty = std::vector<std::tuple<uint32_t, size_t>>; 551dba0c291SJonathan Doman using BaseSpeedPrioritySettingsProperty = 552dba0c291SJonathan Doman std::vector<std::tuple<uint32_t, std::vector<uint32_t>>>; 553dba0c291SJonathan Doman // uint32_t and size_t may or may not be the same type, requiring a dedup'd 554dba0c291SJonathan Doman // variant 555dba0c291SJonathan Doman 556dba0c291SJonathan Doman /** 557dba0c291SJonathan Doman * Fill out the HighSpeedCoreIDs in a Processor resource from the given 558dba0c291SJonathan Doman * OperatingConfig D-Bus property. 559dba0c291SJonathan Doman * 560ac106bf6SEd Tanous * @param[in,out] asyncResp Async HTTP response. 561dba0c291SJonathan Doman * @param[in] baseSpeedSettings Full list of base speed priority groups, 562dba0c291SJonathan Doman * to use to determine the list of high 563dba0c291SJonathan Doman * speed cores. 564dba0c291SJonathan Doman */ 565dba0c291SJonathan Doman inline void highSpeedCoreIdsHandler( 566ac106bf6SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 567dba0c291SJonathan Doman const BaseSpeedPrioritySettingsProperty& baseSpeedSettings) 568dba0c291SJonathan Doman { 569dba0c291SJonathan Doman // The D-Bus property does not indicate which bucket is the "high 570dba0c291SJonathan Doman // priority" group, so let's discern that by looking for the one with 571dba0c291SJonathan Doman // highest base frequency. 572dba0c291SJonathan Doman auto highPriorityGroup = baseSpeedSettings.cend(); 573dba0c291SJonathan Doman uint32_t highestBaseSpeed = 0; 574dba0c291SJonathan Doman for (auto it = baseSpeedSettings.cbegin(); it != baseSpeedSettings.cend(); 575dba0c291SJonathan Doman ++it) 576dba0c291SJonathan Doman { 577dba0c291SJonathan Doman const uint32_t baseFreq = std::get<uint32_t>(*it); 578dba0c291SJonathan Doman if (baseFreq > highestBaseSpeed) 579dba0c291SJonathan Doman { 580dba0c291SJonathan Doman highestBaseSpeed = baseFreq; 581dba0c291SJonathan Doman highPriorityGroup = it; 582dba0c291SJonathan Doman } 583dba0c291SJonathan Doman } 584dba0c291SJonathan Doman 585ac106bf6SEd Tanous nlohmann::json& jsonCoreIds = asyncResp->res.jsonValue["HighSpeedCoreIDs"]; 586dba0c291SJonathan Doman jsonCoreIds = nlohmann::json::array(); 587dba0c291SJonathan Doman 588dba0c291SJonathan Doman // There may not be any entries in the D-Bus property, so only populate 589dba0c291SJonathan Doman // if there was actually something there. 590dba0c291SJonathan Doman if (highPriorityGroup != baseSpeedSettings.cend()) 591dba0c291SJonathan Doman { 592dba0c291SJonathan Doman jsonCoreIds = std::get<std::vector<uint32_t>>(*highPriorityGroup); 593dba0c291SJonathan Doman } 594dba0c291SJonathan Doman } 595dba0c291SJonathan Doman 596dba0c291SJonathan Doman /** 597dba0c291SJonathan Doman * Fill out OperatingConfig related items in a Processor resource by requesting 598dba0c291SJonathan Doman * data from the given D-Bus object. 599dba0c291SJonathan Doman * 600ac106bf6SEd Tanous * @param[in,out] asyncResp Async HTTP response. 601dba0c291SJonathan Doman * @param[in] cpuId CPU D-Bus name. 602dba0c291SJonathan Doman * @param[in] service D-Bus service to query. 603dba0c291SJonathan Doman * @param[in] objPath D-Bus object to query. 604dba0c291SJonathan Doman */ 605ac106bf6SEd Tanous inline void 606ac106bf6SEd Tanous getCpuConfigData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 607ac106bf6SEd Tanous const std::string& cpuId, const std::string& service, 608dba0c291SJonathan Doman const std::string& objPath) 609dba0c291SJonathan Doman { 61062598e31SEd Tanous BMCWEB_LOG_INFO("Getting CPU operating configs for {}", cpuId); 611dba0c291SJonathan Doman 612dba0c291SJonathan Doman // First, GetAll CurrentOperatingConfig properties on the object 613351053f2SKrzysztof Grobelny sdbusplus::asio::getAllProperties( 614351053f2SKrzysztof Grobelny *crow::connections::systemBus, service, objPath, 615351053f2SKrzysztof Grobelny "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig", 616ac106bf6SEd Tanous [asyncResp, cpuId, 6175e7e2dc5SEd Tanous service](const boost::system::error_code& ec, 618351053f2SKrzysztof Grobelny const dbus::utility::DBusPropertiesMap& properties) { 619dba0c291SJonathan Doman if (ec) 620dba0c291SJonathan Doman { 62162598e31SEd Tanous BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec, ec.message()); 622ac106bf6SEd Tanous messages::internalError(asyncResp->res); 623dba0c291SJonathan Doman return; 624dba0c291SJonathan Doman } 625dba0c291SJonathan Doman 626ac106bf6SEd Tanous nlohmann::json& json = asyncResp->res.jsonValue; 627dba0c291SJonathan Doman 628351053f2SKrzysztof Grobelny const sdbusplus::message::object_path* appliedConfig = nullptr; 629351053f2SKrzysztof Grobelny const bool* baseSpeedPriorityEnabled = nullptr; 630351053f2SKrzysztof Grobelny 631351053f2SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 632351053f2SKrzysztof Grobelny dbus_utils::UnpackErrorPrinter(), properties, "AppliedConfig", 633351053f2SKrzysztof Grobelny appliedConfig, "BaseSpeedPriorityEnabled", 634351053f2SKrzysztof Grobelny baseSpeedPriorityEnabled); 635351053f2SKrzysztof Grobelny 636351053f2SKrzysztof Grobelny if (!success) 637dba0c291SJonathan Doman { 638ac106bf6SEd Tanous messages::internalError(asyncResp->res); 639351053f2SKrzysztof Grobelny return; 640dba0c291SJonathan Doman } 641dba0c291SJonathan Doman 642351053f2SKrzysztof Grobelny if (appliedConfig != nullptr) 643351053f2SKrzysztof Grobelny { 644351053f2SKrzysztof Grobelny const std::string& dbusPath = appliedConfig->str; 6451476687dSEd Tanous nlohmann::json::object_t operatingConfig; 646ef4c65b7SEd Tanous operatingConfig["@odata.id"] = boost::urls::format( 647253f11b8SEd Tanous "/redfish/v1/Systems/{}/Processors/{}/OperatingConfigs", 648253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME, cpuId); 6491476687dSEd Tanous json["OperatingConfigs"] = std::move(operatingConfig); 650dba0c291SJonathan Doman 651dba0c291SJonathan Doman // Reuse the D-Bus config object name for the Redfish 652dba0c291SJonathan Doman // URI 653dba0c291SJonathan Doman size_t baseNamePos = dbusPath.rfind('/'); 654dba0c291SJonathan Doman if (baseNamePos == std::string::npos || 655dba0c291SJonathan Doman baseNamePos == (dbusPath.size() - 1)) 656dba0c291SJonathan Doman { 657dba0c291SJonathan Doman // If the AppliedConfig was somehow not a valid path, 658dba0c291SJonathan Doman // skip adding any more properties, since everything 659dba0c291SJonathan Doman // else is tied to this applied config. 660ac106bf6SEd Tanous messages::internalError(asyncResp->res); 661351053f2SKrzysztof Grobelny return; 662dba0c291SJonathan Doman } 6631476687dSEd Tanous nlohmann::json::object_t appliedOperatingConfig; 664ef4c65b7SEd Tanous appliedOperatingConfig["@odata.id"] = boost::urls::format( 665253f11b8SEd Tanous "/redfish/v1/Systems/{}/Processors/{}/OperatingConfigs/{}", 666253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME, cpuId, 667253f11b8SEd Tanous dbusPath.substr(baseNamePos + 1)); 668351053f2SKrzysztof Grobelny json["AppliedOperatingConfig"] = std::move(appliedOperatingConfig); 669dba0c291SJonathan Doman 670dba0c291SJonathan Doman // Once we found the current applied config, queue another 671dba0c291SJonathan Doman // request to read the base freq core ids out of that 672dba0c291SJonathan Doman // config. 673002d39b4SEd Tanous sdbusplus::asio::getProperty<BaseSpeedPrioritySettingsProperty>( 6741e1e598dSJonathan Doman *crow::connections::systemBus, service, dbusPath, 6751e1e598dSJonathan Doman "xyz.openbmc_project.Inventory.Item.Cpu." 6761e1e598dSJonathan Doman "OperatingConfig", 6771e1e598dSJonathan Doman "BaseSpeedPrioritySettings", 678ac106bf6SEd Tanous [asyncResp]( 6795e7e2dc5SEd Tanous const boost::system::error_code& ec2, 680351053f2SKrzysztof Grobelny const BaseSpeedPrioritySettingsProperty& baseSpeedList) { 6818a592810SEd Tanous if (ec2) 682dba0c291SJonathan Doman { 68362598e31SEd Tanous BMCWEB_LOG_WARNING("D-Bus Property Get error: {}", ec2); 684ac106bf6SEd Tanous messages::internalError(asyncResp->res); 685dba0c291SJonathan Doman return; 686dba0c291SJonathan Doman } 6871e1e598dSJonathan Doman 688ac106bf6SEd Tanous highSpeedCoreIdsHandler(asyncResp, baseSpeedList); 6891e1e598dSJonathan Doman }); 690dba0c291SJonathan Doman } 691351053f2SKrzysztof Grobelny 692351053f2SKrzysztof Grobelny if (baseSpeedPriorityEnabled != nullptr) 693dba0c291SJonathan Doman { 694dba0c291SJonathan Doman json["BaseSpeedPriorityState"] = 695351053f2SKrzysztof Grobelny *baseSpeedPriorityEnabled ? "Enabled" : "Disabled"; 696dba0c291SJonathan Doman } 697351053f2SKrzysztof Grobelny }); 698dba0c291SJonathan Doman } 699dba0c291SJonathan Doman 700cba4f448SSunnySrivastava1984 /** 701cba4f448SSunnySrivastava1984 * @brief Fill out location info of a processor by 702cba4f448SSunnySrivastava1984 * requesting data from the given D-Bus object. 703cba4f448SSunnySrivastava1984 * 704ac106bf6SEd Tanous * @param[in,out] asyncResp Async HTTP response. 705cba4f448SSunnySrivastava1984 * @param[in] service D-Bus service to query. 706cba4f448SSunnySrivastava1984 * @param[in] objPath D-Bus object to query. 707cba4f448SSunnySrivastava1984 */ 708ac106bf6SEd Tanous inline void getCpuLocationCode(std::shared_ptr<bmcweb::AsyncResp> asyncResp, 709cba4f448SSunnySrivastava1984 const std::string& service, 710cba4f448SSunnySrivastava1984 const std::string& objPath) 711cba4f448SSunnySrivastava1984 { 71262598e31SEd Tanous BMCWEB_LOG_DEBUG("Get Cpu Location Data"); 7131e1e598dSJonathan Doman sdbusplus::asio::getProperty<std::string>( 7141e1e598dSJonathan Doman *crow::connections::systemBus, service, objPath, 7151e1e598dSJonathan Doman "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode", 716ac106bf6SEd Tanous [objPath, asyncResp{std::move(asyncResp)}]( 717ac106bf6SEd Tanous const boost::system::error_code& ec, const std::string& property) { 718cba4f448SSunnySrivastava1984 if (ec) 719cba4f448SSunnySrivastava1984 { 72062598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error"); 721ac106bf6SEd Tanous messages::internalError(asyncResp->res); 722cba4f448SSunnySrivastava1984 return; 723cba4f448SSunnySrivastava1984 } 724cba4f448SSunnySrivastava1984 725ac106bf6SEd Tanous asyncResp->res.jsonValue["Location"]["PartLocation"]["ServiceLabel"] = 7261e1e598dSJonathan Doman property; 7271e1e598dSJonathan Doman }); 728cba4f448SSunnySrivastava1984 } 729cba4f448SSunnySrivastava1984 730c951448aSJonathan Doman /** 73149e429caSJonathan Doman * Populate the unique identifier in a Processor resource by requesting data 73249e429caSJonathan Doman * from the given D-Bus object. 73349e429caSJonathan Doman * 734ac106bf6SEd Tanous * @param[in,out] asyncResp Async HTTP response. 73549e429caSJonathan Doman * @param[in] service D-Bus service to query. 73649e429caSJonathan Doman * @param[in] objPath D-Bus object to query. 73749e429caSJonathan Doman */ 738ac106bf6SEd Tanous inline void getCpuUniqueId(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 73949e429caSJonathan Doman const std::string& service, 74049e429caSJonathan Doman const std::string& objectPath) 74149e429caSJonathan Doman { 74262598e31SEd Tanous BMCWEB_LOG_DEBUG("Get CPU UniqueIdentifier"); 7431e1e598dSJonathan Doman sdbusplus::asio::getProperty<std::string>( 7441e1e598dSJonathan Doman *crow::connections::systemBus, service, objectPath, 7451e1e598dSJonathan Doman "xyz.openbmc_project.Inventory.Decorator.UniqueIdentifier", 7461e1e598dSJonathan Doman "UniqueIdentifier", 747ac106bf6SEd Tanous [asyncResp](const boost::system::error_code& ec, 748ac106bf6SEd Tanous const std::string& id) { 7491e1e598dSJonathan Doman if (ec) 75049e429caSJonathan Doman { 75162598e31SEd Tanous BMCWEB_LOG_ERROR("Failed to read cpu unique id: {}", ec); 752ac106bf6SEd Tanous messages::internalError(asyncResp->res); 75349e429caSJonathan Doman return; 75449e429caSJonathan Doman } 755ac106bf6SEd Tanous asyncResp->res 756ac106bf6SEd Tanous .jsonValue["ProcessorId"]["ProtectedIdentificationNumber"] = id; 7571e1e598dSJonathan Doman }); 75849e429caSJonathan Doman } 75949e429caSJonathan Doman 76049e429caSJonathan Doman /** 761c951448aSJonathan Doman * Find the D-Bus object representing the requested Processor, and call the 762c951448aSJonathan Doman * handler with the results. If matching object is not found, add 404 error to 763c951448aSJonathan Doman * response and don't call the handler. 764c951448aSJonathan Doman * 765c951448aSJonathan Doman * @param[in,out] resp Async HTTP response. 766c951448aSJonathan Doman * @param[in] processorId Redfish Processor Id. 767c951448aSJonathan Doman * @param[in] handler Callback to continue processing request upon 768c951448aSJonathan Doman * successfully finding object. 769c951448aSJonathan Doman */ 770c951448aSJonathan Doman template <typename Handler> 7718d1b46d7Szhanghch05 inline void getProcessorObject(const std::shared_ptr<bmcweb::AsyncResp>& resp, 772c951448aSJonathan Doman const std::string& processorId, 773c951448aSJonathan Doman Handler&& handler) 774ac6a4445SGunnar Mills { 77562598e31SEd Tanous BMCWEB_LOG_DEBUG("Get available system processor resources."); 776ac6a4445SGunnar Mills 777c951448aSJonathan Doman // GetSubTree on all interfaces which provide info about a Processor 778dfbf7de5SChris Cain constexpr std::array<std::string_view, 9> interfaces = { 779e99073f5SGeorge Liu "xyz.openbmc_project.Common.UUID", 780e99073f5SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.Asset", 781e99073f5SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.Revision", 782e99073f5SGeorge Liu "xyz.openbmc_project.Inventory.Item.Cpu", 783e99073f5SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.LocationCode", 784e99073f5SGeorge Liu "xyz.openbmc_project.Inventory.Item.Accelerator", 785e99073f5SGeorge Liu "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig", 786dfbf7de5SChris Cain "xyz.openbmc_project.Inventory.Decorator.UniqueIdentifier", 787dfbf7de5SChris Cain "xyz.openbmc_project.Control.Power.Throttle"}; 788e99073f5SGeorge Liu dbus::utility::getSubTree( 789e99073f5SGeorge Liu "/xyz/openbmc_project/inventory", 0, interfaces, 790c951448aSJonathan Doman [resp, processorId, handler = std::forward<Handler>(handler)]( 791e99073f5SGeorge Liu const boost::system::error_code& ec, 792e99073f5SGeorge Liu const dbus::utility::MapperGetSubTreeResponse& subtree) { 793ac6a4445SGunnar Mills if (ec) 794ac6a4445SGunnar Mills { 79562598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error: {}", ec); 796c951448aSJonathan Doman messages::internalError(resp->res); 797ac6a4445SGunnar Mills return; 798ac6a4445SGunnar Mills } 7992bab9831SJonathan Doman for (const auto& [objectPath, serviceMap] : subtree) 800ac6a4445SGunnar Mills { 8012bab9831SJonathan Doman // Ignore any objects which don't end with our desired cpu name 80211ba3979SEd Tanous if (!objectPath.ends_with(processorId)) 803ac6a4445SGunnar Mills { 8042bab9831SJonathan Doman continue; 805ac6a4445SGunnar Mills } 8062bab9831SJonathan Doman 807c951448aSJonathan Doman bool found = false; 808c951448aSJonathan Doman // Filter out objects that don't have the CPU-specific 809c951448aSJonathan Doman // interfaces to make sure we can return 404 on non-CPUs 810c951448aSJonathan Doman // (e.g. /redfish/../Processors/dimm0) 8112bab9831SJonathan Doman for (const auto& [serviceName, interfaceList] : serviceMap) 812ac6a4445SGunnar Mills { 8133544d2a7SEd Tanous if (std::ranges::find_first_of(interfaceList, 8143544d2a7SEd Tanous processorInterfaces) != 8153544d2a7SEd Tanous std::end(interfaceList)) 8162bab9831SJonathan Doman { 817c951448aSJonathan Doman found = true; 818c951448aSJonathan Doman break; 819c951448aSJonathan Doman } 820c951448aSJonathan Doman } 821c951448aSJonathan Doman 822c951448aSJonathan Doman if (!found) 8232bab9831SJonathan Doman { 824c951448aSJonathan Doman continue; 825ac6a4445SGunnar Mills } 826c951448aSJonathan Doman 827c951448aSJonathan Doman // Process the first object which does match our cpu name and 828c951448aSJonathan Doman // required interfaces, and potentially ignore any other 829c951448aSJonathan Doman // matching objects. Assume all interfaces we want to process 830c951448aSJonathan Doman // must be on the same object path. 831c951448aSJonathan Doman 8328a592810SEd Tanous handler(objectPath, serviceMap); 833ac6a4445SGunnar Mills return; 834ac6a4445SGunnar Mills } 835c951448aSJonathan Doman messages::resourceNotFound(resp->res, "Processor", processorId); 836e99073f5SGeorge Liu }); 837ac6a4445SGunnar Mills } 838ac6a4445SGunnar Mills 839ac106bf6SEd Tanous inline void 840ac106bf6SEd Tanous getProcessorData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 841c951448aSJonathan Doman const std::string& processorId, 842c951448aSJonathan Doman const std::string& objectPath, 8435df6eda2SShantappa Teekappanavar const dbus::utility::MapperServiceMap& serviceMap) 844c951448aSJonathan Doman { 845c951448aSJonathan Doman for (const auto& [serviceName, interfaceList] : serviceMap) 846c951448aSJonathan Doman { 847c951448aSJonathan Doman for (const auto& interface : interfaceList) 848c951448aSJonathan Doman { 849c951448aSJonathan Doman if (interface == "xyz.openbmc_project.Inventory.Decorator.Asset") 850c951448aSJonathan Doman { 851ac106bf6SEd Tanous getCpuAssetData(asyncResp, serviceName, objectPath); 852c951448aSJonathan Doman } 8530fda0f12SGeorge Liu else if (interface == 8540fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.Revision") 855c951448aSJonathan Doman { 856ac106bf6SEd Tanous getCpuRevisionData(asyncResp, serviceName, objectPath); 857c951448aSJonathan Doman } 858c951448aSJonathan Doman else if (interface == "xyz.openbmc_project.Inventory.Item.Cpu") 859c951448aSJonathan Doman { 860ac106bf6SEd Tanous getCpuDataByService(asyncResp, processorId, serviceName, 861c951448aSJonathan Doman objectPath); 862c951448aSJonathan Doman } 8630fda0f12SGeorge Liu else if (interface == 8640fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Item.Accelerator") 865c951448aSJonathan Doman { 866ac106bf6SEd Tanous getAcceleratorDataByService(asyncResp, processorId, serviceName, 867c951448aSJonathan Doman objectPath); 868c951448aSJonathan Doman } 8690fda0f12SGeorge Liu else if ( 8700fda0f12SGeorge Liu interface == 8710fda0f12SGeorge Liu "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig") 872c951448aSJonathan Doman { 873ac106bf6SEd Tanous getCpuConfigData(asyncResp, processorId, serviceName, 874ac106bf6SEd Tanous objectPath); 875c951448aSJonathan Doman } 8760fda0f12SGeorge Liu else if (interface == 8770fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.LocationCode") 878c951448aSJonathan Doman { 879ac106bf6SEd Tanous getCpuLocationCode(asyncResp, serviceName, objectPath); 880c951448aSJonathan Doman } 88171b82f26SSharad Yadav else if (interface == "xyz.openbmc_project.Common.UUID") 88271b82f26SSharad Yadav { 883ac106bf6SEd Tanous getProcessorUUID(asyncResp, serviceName, objectPath); 88471b82f26SSharad Yadav } 8850fda0f12SGeorge Liu else if (interface == 8860fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.UniqueIdentifier") 88749e429caSJonathan Doman { 888ac106bf6SEd Tanous getCpuUniqueId(asyncResp, serviceName, objectPath); 88949e429caSJonathan Doman } 890dfbf7de5SChris Cain else if (interface == "xyz.openbmc_project.Control.Power.Throttle") 891dfbf7de5SChris Cain { 892ac106bf6SEd Tanous getThrottleProperties(asyncResp, serviceName, objectPath); 893dfbf7de5SChris Cain } 894c951448aSJonathan Doman } 895c951448aSJonathan Doman } 896c951448aSJonathan Doman } 897c951448aSJonathan Doman 898dba0c291SJonathan Doman /** 899dba0c291SJonathan Doman * Request all the properties for the given D-Bus object and fill out the 900dba0c291SJonathan Doman * related entries in the Redfish OperatingConfig response. 901dba0c291SJonathan Doman * 902ac106bf6SEd Tanous * @param[in,out] asyncResp Async HTTP response. 903dba0c291SJonathan Doman * @param[in] service D-Bus service name to query. 904dba0c291SJonathan Doman * @param[in] objPath D-Bus object to query. 905dba0c291SJonathan Doman */ 9068d1b46d7Szhanghch05 inline void 907ac106bf6SEd Tanous getOperatingConfigData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 908dba0c291SJonathan Doman const std::string& service, 909dba0c291SJonathan Doman const std::string& objPath) 910dba0c291SJonathan Doman { 911351053f2SKrzysztof Grobelny sdbusplus::asio::getAllProperties( 912351053f2SKrzysztof Grobelny *crow::connections::systemBus, service, objPath, 913351053f2SKrzysztof Grobelny "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig", 914ac106bf6SEd Tanous [asyncResp](const boost::system::error_code& ec, 915351053f2SKrzysztof Grobelny const dbus::utility::DBusPropertiesMap& properties) { 916dba0c291SJonathan Doman if (ec) 917dba0c291SJonathan Doman { 91862598e31SEd Tanous BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec, ec.message()); 919ac106bf6SEd Tanous messages::internalError(asyncResp->res); 920dba0c291SJonathan Doman return; 921dba0c291SJonathan Doman } 922dba0c291SJonathan Doman 923351053f2SKrzysztof Grobelny const size_t* availableCoreCount = nullptr; 924351053f2SKrzysztof Grobelny const uint32_t* baseSpeed = nullptr; 925351053f2SKrzysztof Grobelny const uint32_t* maxJunctionTemperature = nullptr; 926351053f2SKrzysztof Grobelny const uint32_t* maxSpeed = nullptr; 927351053f2SKrzysztof Grobelny const uint32_t* powerLimit = nullptr; 928351053f2SKrzysztof Grobelny const TurboProfileProperty* turboProfile = nullptr; 929351053f2SKrzysztof Grobelny const BaseSpeedPrioritySettingsProperty* baseSpeedPrioritySettings = 930351053f2SKrzysztof Grobelny nullptr; 931351053f2SKrzysztof Grobelny 932351053f2SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 933351053f2SKrzysztof Grobelny dbus_utils::UnpackErrorPrinter(), properties, "AvailableCoreCount", 934351053f2SKrzysztof Grobelny availableCoreCount, "BaseSpeed", baseSpeed, 935351053f2SKrzysztof Grobelny "MaxJunctionTemperature", maxJunctionTemperature, "MaxSpeed", 936351053f2SKrzysztof Grobelny maxSpeed, "PowerLimit", powerLimit, "TurboProfile", turboProfile, 937351053f2SKrzysztof Grobelny "BaseSpeedPrioritySettings", baseSpeedPrioritySettings); 938351053f2SKrzysztof Grobelny 939351053f2SKrzysztof Grobelny if (!success) 940dba0c291SJonathan Doman { 941ac106bf6SEd Tanous messages::internalError(asyncResp->res); 942351053f2SKrzysztof Grobelny return; 943dba0c291SJonathan Doman } 944dba0c291SJonathan Doman 945ac106bf6SEd Tanous nlohmann::json& json = asyncResp->res.jsonValue; 946351053f2SKrzysztof Grobelny 947351053f2SKrzysztof Grobelny if (availableCoreCount != nullptr) 948351053f2SKrzysztof Grobelny { 949351053f2SKrzysztof Grobelny json["TotalAvailableCoreCount"] = *availableCoreCount; 950351053f2SKrzysztof Grobelny } 951351053f2SKrzysztof Grobelny 952351053f2SKrzysztof Grobelny if (baseSpeed != nullptr) 953351053f2SKrzysztof Grobelny { 954351053f2SKrzysztof Grobelny json["BaseSpeedMHz"] = *baseSpeed; 955351053f2SKrzysztof Grobelny } 956351053f2SKrzysztof Grobelny 957351053f2SKrzysztof Grobelny if (maxJunctionTemperature != nullptr) 958351053f2SKrzysztof Grobelny { 959351053f2SKrzysztof Grobelny json["MaxJunctionTemperatureCelsius"] = *maxJunctionTemperature; 960351053f2SKrzysztof Grobelny } 961351053f2SKrzysztof Grobelny 962351053f2SKrzysztof Grobelny if (maxSpeed != nullptr) 963351053f2SKrzysztof Grobelny { 964351053f2SKrzysztof Grobelny json["MaxSpeedMHz"] = *maxSpeed; 965351053f2SKrzysztof Grobelny } 966351053f2SKrzysztof Grobelny 967351053f2SKrzysztof Grobelny if (powerLimit != nullptr) 968351053f2SKrzysztof Grobelny { 969351053f2SKrzysztof Grobelny json["TDPWatts"] = *powerLimit; 970351053f2SKrzysztof Grobelny } 971351053f2SKrzysztof Grobelny 972351053f2SKrzysztof Grobelny if (turboProfile != nullptr) 973351053f2SKrzysztof Grobelny { 974dba0c291SJonathan Doman nlohmann::json& turboArray = json["TurboProfile"]; 975dba0c291SJonathan Doman turboArray = nlohmann::json::array(); 976351053f2SKrzysztof Grobelny for (const auto& [turboSpeed, coreCount] : *turboProfile) 977dba0c291SJonathan Doman { 9781476687dSEd Tanous nlohmann::json::object_t turbo; 9791476687dSEd Tanous turbo["ActiveCoreCount"] = coreCount; 9801476687dSEd Tanous turbo["MaxSpeedMHz"] = turboSpeed; 981b2ba3072SPatrick Williams turboArray.emplace_back(std::move(turbo)); 982dba0c291SJonathan Doman } 983dba0c291SJonathan Doman } 984dba0c291SJonathan Doman 985351053f2SKrzysztof Grobelny if (baseSpeedPrioritySettings != nullptr) 986351053f2SKrzysztof Grobelny { 987351053f2SKrzysztof Grobelny nlohmann::json& baseSpeedArray = json["BaseSpeedPrioritySettings"]; 988dba0c291SJonathan Doman baseSpeedArray = nlohmann::json::array(); 989351053f2SKrzysztof Grobelny for (const auto& [baseSpeedMhz, coreList] : 990351053f2SKrzysztof Grobelny *baseSpeedPrioritySettings) 991dba0c291SJonathan Doman { 9921476687dSEd Tanous nlohmann::json::object_t speed; 9931476687dSEd Tanous speed["CoreCount"] = coreList.size(); 9941476687dSEd Tanous speed["CoreIDs"] = coreList; 995351053f2SKrzysztof Grobelny speed["BaseSpeedMHz"] = baseSpeedMhz; 996b2ba3072SPatrick Williams baseSpeedArray.emplace_back(std::move(speed)); 997dba0c291SJonathan Doman } 998dba0c291SJonathan Doman } 999351053f2SKrzysztof Grobelny }); 1000dba0c291SJonathan Doman } 1001dba0c291SJonathan Doman 10023cde86f1SJonathan Doman /** 10033cde86f1SJonathan Doman * Handle the PATCH operation of the AppliedOperatingConfig property. Do basic 10043cde86f1SJonathan Doman * validation of the input data, and then set the D-Bus property. 10053cde86f1SJonathan Doman * 10063cde86f1SJonathan Doman * @param[in,out] resp Async HTTP response. 10073cde86f1SJonathan Doman * @param[in] processorId Processor's Id. 10083cde86f1SJonathan Doman * @param[in] appliedConfigUri New property value to apply. 10093cde86f1SJonathan Doman * @param[in] cpuObjectPath Path of CPU object to modify. 10103cde86f1SJonathan Doman * @param[in] serviceMap Service map for CPU object. 10113cde86f1SJonathan Doman */ 10123cde86f1SJonathan Doman inline void patchAppliedOperatingConfig( 10133cde86f1SJonathan Doman const std::shared_ptr<bmcweb::AsyncResp>& resp, 10143cde86f1SJonathan Doman const std::string& processorId, const std::string& appliedConfigUri, 10155df6eda2SShantappa Teekappanavar const std::string& cpuObjectPath, 10165df6eda2SShantappa Teekappanavar const dbus::utility::MapperServiceMap& serviceMap) 10173cde86f1SJonathan Doman { 10183cde86f1SJonathan Doman // Check that the property even exists by checking for the interface 10193cde86f1SJonathan Doman const std::string* controlService = nullptr; 10203cde86f1SJonathan Doman for (const auto& [serviceName, interfaceList] : serviceMap) 10213cde86f1SJonathan Doman { 10223544d2a7SEd Tanous if (std::ranges::find(interfaceList, 10233cde86f1SJonathan Doman "xyz.openbmc_project.Control.Processor." 10243cde86f1SJonathan Doman "CurrentOperatingConfig") != interfaceList.end()) 10253cde86f1SJonathan Doman { 10263cde86f1SJonathan Doman controlService = &serviceName; 10273cde86f1SJonathan Doman break; 10283cde86f1SJonathan Doman } 10293cde86f1SJonathan Doman } 10303cde86f1SJonathan Doman 10313cde86f1SJonathan Doman if (controlService == nullptr) 10323cde86f1SJonathan Doman { 10333cde86f1SJonathan Doman messages::internalError(resp->res); 10343cde86f1SJonathan Doman return; 10353cde86f1SJonathan Doman } 10363cde86f1SJonathan Doman 10373cde86f1SJonathan Doman // Check that the config URI is a child of the cpu URI being patched. 1038253f11b8SEd Tanous std::string expectedPrefix(std::format("/redfish/v1/Systems/{}/Processors/", 1039253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME)); 10403cde86f1SJonathan Doman expectedPrefix += processorId; 10413cde86f1SJonathan Doman expectedPrefix += "/OperatingConfigs/"; 104211ba3979SEd Tanous if (!appliedConfigUri.starts_with(expectedPrefix) || 10433cde86f1SJonathan Doman expectedPrefix.size() == appliedConfigUri.size()) 10443cde86f1SJonathan Doman { 104587c44966SAsmitha Karunanithi messages::propertyValueIncorrect(resp->res, "AppliedOperatingConfig", 104687c44966SAsmitha Karunanithi appliedConfigUri); 10473cde86f1SJonathan Doman return; 10483cde86f1SJonathan Doman } 10493cde86f1SJonathan Doman 10503cde86f1SJonathan Doman // Generate the D-Bus path of the OperatingConfig object, by assuming it's a 10513cde86f1SJonathan Doman // direct child of the CPU object. 10523cde86f1SJonathan Doman // Strip the expectedPrefix from the config URI to get the "filename", and 10533cde86f1SJonathan Doman // append to the CPU's path. 10543cde86f1SJonathan Doman std::string configBaseName = appliedConfigUri.substr(expectedPrefix.size()); 10553cde86f1SJonathan Doman sdbusplus::message::object_path configPath(cpuObjectPath); 10563cde86f1SJonathan Doman configPath /= configBaseName; 10573cde86f1SJonathan Doman 105862598e31SEd Tanous BMCWEB_LOG_INFO("Setting config to {}", configPath.str); 10593cde86f1SJonathan Doman 10603cde86f1SJonathan Doman // Set the property, with handler to check error responses 106187c44966SAsmitha Karunanithi setDbusProperty( 1062*e93abac6SGinu George resp, "AppliedOperatingConfig", *controlService, cpuObjectPath, 10639ae226faSGeorge Liu "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig", 1064*e93abac6SGinu George "AppliedConfig", configPath); 10653cde86f1SJonathan Doman } 10663cde86f1SJonathan Doman 1067ac106bf6SEd Tanous inline void 1068ac106bf6SEd Tanous handleProcessorHead(crow::App& app, const crow::Request& req, 1069ac106bf6SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 107071a24ca4SNikhil Namjoshi const std::string& /* systemName */, 107171a24ca4SNikhil Namjoshi const std::string& /* processorId */) 107271a24ca4SNikhil Namjoshi { 1073ac106bf6SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 107471a24ca4SNikhil Namjoshi { 107571a24ca4SNikhil Namjoshi return; 107671a24ca4SNikhil Namjoshi } 1077ac106bf6SEd Tanous asyncResp->res.addHeader( 107871a24ca4SNikhil Namjoshi boost::beast::http::field::link, 107971a24ca4SNikhil Namjoshi "</redfish/v1/JsonSchemas/Processor/Processor.json>; rel=describedby"); 108071a24ca4SNikhil Namjoshi } 108171a24ca4SNikhil Namjoshi 108271a24ca4SNikhil Namjoshi inline void handleProcessorCollectionHead( 108371a24ca4SNikhil Namjoshi crow::App& app, const crow::Request& req, 1084ac106bf6SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 108571a24ca4SNikhil Namjoshi const std::string& /* systemName */) 108671a24ca4SNikhil Namjoshi { 1087ac106bf6SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 108871a24ca4SNikhil Namjoshi { 108971a24ca4SNikhil Namjoshi return; 109071a24ca4SNikhil Namjoshi } 1091ac106bf6SEd Tanous asyncResp->res.addHeader( 109271a24ca4SNikhil Namjoshi boost::beast::http::field::link, 109371a24ca4SNikhil Namjoshi "</redfish/v1/JsonSchemas/ProcessorCollection/ProcessorCollection.json>; rel=describedby"); 109471a24ca4SNikhil Namjoshi } 109571a24ca4SNikhil Namjoshi 10967e860f15SJohn Edward Broadbent inline void requestRoutesOperatingConfigCollection(App& app) 1097dba0c291SJonathan Doman { 10987f3e84a1SEd Tanous BMCWEB_ROUTE(app, 10997f3e84a1SEd Tanous "/redfish/v1/Systems/<str>/Processors/<str>/OperatingConfigs/") 1100ed398213SEd Tanous .privileges(redfish::privileges::getOperatingConfigCollection) 1101002d39b4SEd Tanous .methods(boost::beast::http::verb::get)( 1102002d39b4SEd Tanous [&app](const crow::Request& req, 110345ca1b86SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 11047f3e84a1SEd Tanous const std::string& systemName, const std::string& cpuName) { 11053ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 110645ca1b86SEd Tanous { 110745ca1b86SEd Tanous return; 110845ca1b86SEd Tanous } 11097f3e84a1SEd Tanous 111025b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 11117f3e84a1SEd Tanous { 11127f3e84a1SEd Tanous // Option currently returns no systems. TBD 11137f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 11147f3e84a1SEd Tanous systemName); 11157f3e84a1SEd Tanous return; 11167f3e84a1SEd Tanous } 11177f3e84a1SEd Tanous 1118253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 11197f3e84a1SEd Tanous { 11207f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 11217f3e84a1SEd Tanous systemName); 11227f3e84a1SEd Tanous return; 11237f3e84a1SEd Tanous } 11248d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.type"] = 1125dba0c291SJonathan Doman "#OperatingConfigCollection.OperatingConfigCollection"; 1126ef4c65b7SEd Tanous asyncResp->res.jsonValue["@odata.id"] = boost::urls::format( 1127253f11b8SEd Tanous "/redfish/v1/Systems/{}/Processors/{}/OperatingConfigs", 1128253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME, cpuName); 11290fda0f12SGeorge Liu asyncResp->res.jsonValue["Name"] = "Operating Config Collection"; 1130dba0c291SJonathan Doman 11317e860f15SJohn Edward Broadbent // First find the matching CPU object so we know how to 11327e860f15SJohn Edward Broadbent // constrain our search for related Config objects. 11337a1dbc48SGeorge Liu const std::array<std::string_view, 1> interfaces = { 11347a1dbc48SGeorge Liu "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig"}; 11357a1dbc48SGeorge Liu dbus::utility::getSubTreePaths( 11367a1dbc48SGeorge Liu "/xyz/openbmc_project/inventory", 0, interfaces, 1137002d39b4SEd Tanous [asyncResp, cpuName]( 11387a1dbc48SGeorge Liu const boost::system::error_code& ec, 1139002d39b4SEd Tanous const dbus::utility::MapperGetSubTreePathsResponse& objects) { 1140dba0c291SJonathan Doman if (ec) 1141dba0c291SJonathan Doman { 114262598e31SEd Tanous BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec, ec.message()); 1143dba0c291SJonathan Doman messages::internalError(asyncResp->res); 1144dba0c291SJonathan Doman return; 1145dba0c291SJonathan Doman } 1146dba0c291SJonathan Doman 1147dba0c291SJonathan Doman for (const std::string& object : objects) 1148dba0c291SJonathan Doman { 114911ba3979SEd Tanous if (!object.ends_with(cpuName)) 1150dba0c291SJonathan Doman { 1151dba0c291SJonathan Doman continue; 1152dba0c291SJonathan Doman } 1153dba0c291SJonathan Doman 11547e860f15SJohn Edward Broadbent // Not expected that there will be multiple matching 11557e860f15SJohn Edward Broadbent // CPU objects, but if there are just use the first 11567e860f15SJohn Edward Broadbent // one. 1157dba0c291SJonathan Doman 11587e860f15SJohn Edward Broadbent // Use the common search routine to construct the 11597e860f15SJohn Edward Broadbent // Collection of all Config objects under this CPU. 11607a1dbc48SGeorge Liu constexpr std::array<std::string_view, 1> interface{ 11615a39f77aSPatrick Williams "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig"}; 1162dba0c291SJonathan Doman collection_util::getCollectionMembers( 1163dba0c291SJonathan Doman asyncResp, 1164ef4c65b7SEd Tanous boost::urls::format( 1165253f11b8SEd Tanous "/redfish/v1/Systems/{}/Processors/{}/OperatingConfigs", 1166253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME, cpuName), 116736b5f1edSLakshmi Yadlapati interface, object); 1168dba0c291SJonathan Doman return; 1169dba0c291SJonathan Doman } 11707a1dbc48SGeorge Liu }); 11717e860f15SJohn Edward Broadbent }); 1172dba0c291SJonathan Doman } 1173dba0c291SJonathan Doman 11747e860f15SJohn Edward Broadbent inline void requestRoutesOperatingConfig(App& app) 1175dba0c291SJonathan Doman { 11767e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 11777e860f15SJohn Edward Broadbent app, 11787f3e84a1SEd Tanous "/redfish/v1/Systems/<str>/Processors/<str>/OperatingConfigs/<str>/") 1179ed398213SEd Tanous .privileges(redfish::privileges::getOperatingConfig) 1180002d39b4SEd Tanous .methods(boost::beast::http::verb::get)( 1181002d39b4SEd Tanous [&app](const crow::Request& req, 118245ca1b86SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 11837f3e84a1SEd Tanous const std::string& systemName, const std::string& cpuName, 11847f3e84a1SEd Tanous const std::string& configName) { 11853ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 118645ca1b86SEd Tanous { 118745ca1b86SEd Tanous return; 118845ca1b86SEd Tanous } 118925b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 11907f3e84a1SEd Tanous { 11917f3e84a1SEd Tanous // Option currently returns no systems. TBD 11927f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 11937f3e84a1SEd Tanous systemName); 11947f3e84a1SEd Tanous return; 11957f3e84a1SEd Tanous } 11967f3e84a1SEd Tanous 1197253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 11987f3e84a1SEd Tanous { 11997f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 12007f3e84a1SEd Tanous systemName); 12017f3e84a1SEd Tanous return; 12027f3e84a1SEd Tanous } 12037e860f15SJohn Edward Broadbent // Ask for all objects implementing OperatingConfig so we can search 12047e860f15SJohn Edward Broadbent // for one with a matching name 1205e99073f5SGeorge Liu constexpr std::array<std::string_view, 1> interfaces = { 1206e99073f5SGeorge Liu "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig"}; 1207e99073f5SGeorge Liu dbus::utility::getSubTree( 1208e99073f5SGeorge Liu "/xyz/openbmc_project/inventory", 0, interfaces, 120939662a3bSEd Tanous [asyncResp, cpuName, configName]( 1210e99073f5SGeorge Liu const boost::system::error_code& ec, 12115df6eda2SShantappa Teekappanavar const dbus::utility::MapperGetSubTreeResponse& subtree) { 1212dba0c291SJonathan Doman if (ec) 1213dba0c291SJonathan Doman { 121462598e31SEd Tanous BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec, ec.message()); 1215dba0c291SJonathan Doman messages::internalError(asyncResp->res); 1216dba0c291SJonathan Doman return; 1217dba0c291SJonathan Doman } 1218002d39b4SEd Tanous const std::string expectedEnding = cpuName + '/' + configName; 1219dba0c291SJonathan Doman for (const auto& [objectPath, serviceMap] : subtree) 1220dba0c291SJonathan Doman { 1221dba0c291SJonathan Doman // Ignore any configs without matching cpuX/configY 122211ba3979SEd Tanous if (!objectPath.ends_with(expectedEnding) || serviceMap.empty()) 1223dba0c291SJonathan Doman { 1224dba0c291SJonathan Doman continue; 1225dba0c291SJonathan Doman } 1226dba0c291SJonathan Doman 1227dba0c291SJonathan Doman nlohmann::json& json = asyncResp->res.jsonValue; 1228002d39b4SEd Tanous json["@odata.type"] = "#OperatingConfig.v1_0_0.OperatingConfig"; 1229ef4c65b7SEd Tanous json["@odata.id"] = boost::urls::format( 1230253f11b8SEd Tanous "/redfish/v1/Systems/{}/Processors/{}/OperatingConfigs/{}", 1231253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME, cpuName, configName); 1232dba0c291SJonathan Doman json["Name"] = "Processor Profile"; 1233dba0c291SJonathan Doman json["Id"] = configName; 1234dba0c291SJonathan Doman 1235dba0c291SJonathan Doman // Just use the first implementation of the object - not 12367e860f15SJohn Edward Broadbent // expected that there would be multiple matching 12377e860f15SJohn Edward Broadbent // services 1238002d39b4SEd Tanous getOperatingConfigData(asyncResp, serviceMap.begin()->first, 1239002d39b4SEd Tanous objectPath); 1240dba0c291SJonathan Doman return; 1241dba0c291SJonathan Doman } 1242002d39b4SEd Tanous messages::resourceNotFound(asyncResp->res, "OperatingConfig", 1243002d39b4SEd Tanous configName); 1244e99073f5SGeorge Liu }); 12457e860f15SJohn Edward Broadbent }); 1246ac6a4445SGunnar Mills } 1247ac6a4445SGunnar Mills 12487e860f15SJohn Edward Broadbent inline void requestRoutesProcessorCollection(App& app) 12497e860f15SJohn Edward Broadbent { 1250ac6a4445SGunnar Mills /** 1251ac6a4445SGunnar Mills * Functions triggers appropriate requests on DBus 1252ac6a4445SGunnar Mills */ 125322d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/") 125471a24ca4SNikhil Namjoshi .privileges(redfish::privileges::headProcessorCollection) 125571a24ca4SNikhil Namjoshi .methods(boost::beast::http::verb::head)( 125671a24ca4SNikhil Namjoshi std::bind_front(handleProcessorCollectionHead, std::ref(app))); 125771a24ca4SNikhil Namjoshi 125871a24ca4SNikhil Namjoshi BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/") 1259ed398213SEd Tanous .privileges(redfish::privileges::getProcessorCollection) 12607e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 126145ca1b86SEd Tanous [&app](const crow::Request& req, 126222d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 126322d268cbSEd Tanous const std::string& systemName) { 12643ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 126545ca1b86SEd Tanous { 126645ca1b86SEd Tanous return; 126745ca1b86SEd Tanous } 126825b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 12697f3e84a1SEd Tanous { 12707f3e84a1SEd Tanous // Option currently returns no systems. TBD 12717f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 12727f3e84a1SEd Tanous systemName); 12737f3e84a1SEd Tanous return; 12747f3e84a1SEd Tanous } 12757f3e84a1SEd Tanous 1276253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 127722d268cbSEd Tanous { 127822d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 127922d268cbSEd Tanous systemName); 128022d268cbSEd Tanous return; 128122d268cbSEd Tanous } 128222d268cbSEd Tanous 128371a24ca4SNikhil Namjoshi asyncResp->res.addHeader( 128471a24ca4SNikhil Namjoshi boost::beast::http::field::link, 128571a24ca4SNikhil Namjoshi "</redfish/v1/JsonSchemas/ProcessorCollection/ProcessorCollection.json>; rel=describedby"); 128671a24ca4SNikhil Namjoshi 12878d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.type"] = 1288ac6a4445SGunnar Mills "#ProcessorCollection.ProcessorCollection"; 12898d1b46d7Szhanghch05 asyncResp->res.jsonValue["Name"] = "Processor Collection"; 1290ac6a4445SGunnar Mills 12918d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.id"] = 1292253f11b8SEd Tanous std::format("/redfish/v1/Systems/{}/Processors", 1293253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 1294ac6a4445SGunnar Mills 129505030b8eSGunnar Mills collection_util::getCollectionMembers( 1296ae9031f0SWilly Tu asyncResp, 1297253f11b8SEd Tanous boost::urls::format("/redfish/v1/Systems/{}/Processors", 1298253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME), 129936b5f1edSLakshmi Yadlapati processorInterfaces, "/xyz/openbmc_project/inventory"); 13007e860f15SJohn Edward Broadbent }); 1301ac6a4445SGunnar Mills } 1302ac6a4445SGunnar Mills 13037e860f15SJohn Edward Broadbent inline void requestRoutesProcessor(App& app) 13047e860f15SJohn Edward Broadbent { 1305ac6a4445SGunnar Mills /** 1306ac6a4445SGunnar Mills * Functions triggers appropriate requests on DBus 1307ac6a4445SGunnar Mills */ 13087e860f15SJohn Edward Broadbent 130922d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/<str>/") 131071a24ca4SNikhil Namjoshi .privileges(redfish::privileges::headProcessor) 131171a24ca4SNikhil Namjoshi .methods(boost::beast::http::verb::head)( 131271a24ca4SNikhil Namjoshi std::bind_front(handleProcessorHead, std::ref(app))); 131371a24ca4SNikhil Namjoshi 131471a24ca4SNikhil Namjoshi BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/<str>/") 1315ed398213SEd Tanous .privileges(redfish::privileges::getProcessor) 13167e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 131745ca1b86SEd Tanous [&app](const crow::Request& req, 13187e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 131922d268cbSEd Tanous const std::string& systemName, 13207e860f15SJohn Edward Broadbent const std::string& processorId) { 13213ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 132245ca1b86SEd Tanous { 132345ca1b86SEd Tanous return; 132445ca1b86SEd Tanous } 132525b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 13267f3e84a1SEd Tanous { 13277f3e84a1SEd Tanous // Option currently returns no systems. TBD 13287f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 13297f3e84a1SEd Tanous systemName); 13307f3e84a1SEd Tanous return; 13317f3e84a1SEd Tanous } 1332253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 133322d268cbSEd Tanous { 133422d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 133522d268cbSEd Tanous systemName); 133622d268cbSEd Tanous return; 133722d268cbSEd Tanous } 133822d268cbSEd Tanous 133971a24ca4SNikhil Namjoshi asyncResp->res.addHeader( 134071a24ca4SNikhil Namjoshi boost::beast::http::field::link, 134171a24ca4SNikhil Namjoshi "</redfish/v1/JsonSchemas/Processor/Processor.json>; rel=describedby"); 13428d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.type"] = 1343dfbf7de5SChris Cain "#Processor.v1_18_0.Processor"; 1344253f11b8SEd Tanous asyncResp->res.jsonValue["@odata.id"] = 1345253f11b8SEd Tanous boost::urls::format("/redfish/v1/Systems/{}/Processors/{}", 1346253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME, processorId); 1347ac6a4445SGunnar Mills 13488a592810SEd Tanous getProcessorObject( 13498a592810SEd Tanous asyncResp, processorId, 13508a592810SEd Tanous std::bind_front(getProcessorData, asyncResp, processorId)); 13517e860f15SJohn Edward Broadbent }); 13523cde86f1SJonathan Doman 135322d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/<str>/") 1354ed398213SEd Tanous .privileges(redfish::privileges::patchProcessor) 13557e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::patch)( 135645ca1b86SEd Tanous [&app](const crow::Request& req, 13577e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 135822d268cbSEd Tanous const std::string& systemName, 13597e860f15SJohn Edward Broadbent const std::string& processorId) { 13603ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 136145ca1b86SEd Tanous { 136245ca1b86SEd Tanous return; 136345ca1b86SEd Tanous } 136425b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 13657f3e84a1SEd Tanous { 13667f3e84a1SEd Tanous // Option currently returns no systems. TBD 13677f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 13687f3e84a1SEd Tanous systemName); 13697f3e84a1SEd Tanous return; 13707f3e84a1SEd Tanous } 1371253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 137222d268cbSEd Tanous { 137322d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 137422d268cbSEd Tanous systemName); 137522d268cbSEd Tanous return; 137622d268cbSEd Tanous } 137722d268cbSEd Tanous 13783c569218SEd Tanous std::optional<std::string> appliedConfigUri; 137915ed6780SWilly Tu if (!json_util::readJsonPatch(req, asyncResp->res, 13803c569218SEd Tanous "AppliedOperatingConfig/@odata.id", 13813c569218SEd Tanous appliedConfigUri)) 13823cde86f1SJonathan Doman { 13833cde86f1SJonathan Doman return; 13843cde86f1SJonathan Doman } 13853cde86f1SJonathan Doman 13863c569218SEd Tanous if (appliedConfigUri) 13873cde86f1SJonathan Doman { 13887e860f15SJohn Edward Broadbent // Check for 404 and find matching D-Bus object, then run 13897e860f15SJohn Edward Broadbent // property patch handlers if that all succeeds. 13908a592810SEd Tanous getProcessorObject(asyncResp, processorId, 13918a592810SEd Tanous std::bind_front(patchAppliedOperatingConfig, 13927e860f15SJohn Edward Broadbent asyncResp, processorId, 13933c569218SEd Tanous *appliedConfigUri)); 13943cde86f1SJonathan Doman } 13957e860f15SJohn Edward Broadbent }); 13963cde86f1SJonathan Doman } 1397ac6a4445SGunnar Mills 1398ac6a4445SGunnar Mills } // namespace redfish 1399