1ac6a4445SGunnar Mills /* 26be832e2SEd Tanous Copyright (c) 2018 Intel Corporation 36be832e2SEd Tanous 46be832e2SEd Tanous Licensed under the Apache License, Version 2.0 (the "License"); 56be832e2SEd Tanous you may not use this file except in compliance with the License. 66be832e2SEd Tanous You may obtain a copy of the License at 76be832e2SEd Tanous 86be832e2SEd Tanous http://www.apache.org/licenses/LICENSE-2.0 96be832e2SEd Tanous 106be832e2SEd Tanous Unless required by applicable law or agreed to in writing, software 116be832e2SEd Tanous distributed under the License is distributed on an "AS IS" BASIS, 126be832e2SEd Tanous WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136be832e2SEd Tanous See the License for the specific language governing permissions and 146be832e2SEd Tanous limitations under the License. 15ac6a4445SGunnar Mills */ 16ac6a4445SGunnar Mills #pragma once 17ac6a4445SGunnar Mills 183ccb3adbSEd Tanous #include "app.hpp" 191e1e598dSJonathan Doman #include "dbus_singleton.hpp" 207a1dbc48SGeorge Liu #include "dbus_utility.hpp" 211e1e598dSJonathan Doman #include "error_messages.hpp" 22dfbf7de5SChris Cain #include "generated/enums/processor.hpp" 23539d8c6bSEd Tanous #include "generated/enums/resource.hpp" 243ccb3adbSEd Tanous #include "query.hpp" 253ccb3adbSEd Tanous #include "registries/privilege_registry.hpp" 263ccb3adbSEd Tanous #include "utils/collection.hpp" 273ccb3adbSEd Tanous #include "utils/dbus_utils.hpp" 283ccb3adbSEd Tanous #include "utils/json_utils.hpp" 29ac6a4445SGunnar Mills 30ac6a4445SGunnar Mills #include <boost/container/flat_map.hpp> 31e99073f5SGeorge Liu #include <boost/system/error_code.hpp> 32ef4c65b7SEd Tanous #include <boost/url/format.hpp> 331e1e598dSJonathan Doman #include <sdbusplus/asio/property.hpp> 34dba0c291SJonathan Doman #include <sdbusplus/message/native_types.hpp> 35351053f2SKrzysztof Grobelny #include <sdbusplus/unpack_properties.hpp> 36dba0c291SJonathan Doman #include <sdbusplus/utility/dedup_variant.hpp> 37ac6a4445SGunnar Mills 387a1dbc48SGeorge Liu #include <array> 39b9d679d1SMichael Shen #include <limits> 403544d2a7SEd Tanous #include <ranges> 413c569218SEd Tanous #include <string> 427a1dbc48SGeorge Liu #include <string_view> 437a1dbc48SGeorge Liu 44ac6a4445SGunnar Mills namespace redfish 45ac6a4445SGunnar Mills { 46ac6a4445SGunnar Mills 47c951448aSJonathan Doman // Interfaces which imply a D-Bus object represents a Processor 487a1dbc48SGeorge Liu constexpr std::array<std::string_view, 2> processorInterfaces = { 49c951448aSJonathan Doman "xyz.openbmc_project.Inventory.Item.Cpu", 50c951448aSJonathan Doman "xyz.openbmc_project.Inventory.Item.Accelerator"}; 512bab9831SJonathan Doman 5271b82f26SSharad Yadav /** 5371b82f26SSharad Yadav * @brief Fill out uuid info of a processor by 5471b82f26SSharad Yadav * requesting data from the given D-Bus object. 5571b82f26SSharad Yadav * 56ac106bf6SEd Tanous * @param[in,out] asyncResp Async HTTP response. 5771b82f26SSharad Yadav * @param[in] service D-Bus service to query. 5871b82f26SSharad Yadav * @param[in] objPath D-Bus object to query. 5971b82f26SSharad Yadav */ 60ac106bf6SEd Tanous inline void getProcessorUUID(std::shared_ptr<bmcweb::AsyncResp> asyncResp, 6171b82f26SSharad Yadav const std::string& service, 6271b82f26SSharad Yadav const std::string& objPath) 6371b82f26SSharad Yadav { 6462598e31SEd Tanous BMCWEB_LOG_DEBUG("Get Processor UUID"); 65*deae6a78SEd Tanous dbus::utility::getProperty<std::string>( 66*deae6a78SEd Tanous service, objPath, "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 86539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled; 87539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["Health"] = resource::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 105539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["State"] = 106539d8c6bSEd Tanous resource::State::Absent; 107a1649ec6SChicago Duan } 108a1649ec6SChicago Duan } 109a1649ec6SChicago Duan else if (property.first == "Functional") 110a1649ec6SChicago Duan { 111a1649ec6SChicago Duan const bool* cpuFunctional = std::get_if<bool>(&property.second); 112a1649ec6SChicago Duan if (cpuFunctional == nullptr) 113a1649ec6SChicago Duan { 114ac106bf6SEd Tanous messages::internalError(asyncResp->res); 115ac6a4445SGunnar Mills return; 116ac6a4445SGunnar Mills } 117e05aec50SEd Tanous if (!*cpuFunctional) 118a1649ec6SChicago Duan { 119539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["Health"] = 120539d8c6bSEd Tanous resource::Health::Critical; 121a1649ec6SChicago Duan } 122a1649ec6SChicago Duan } 123a1649ec6SChicago Duan else if (property.first == "CoreCount") 124a1649ec6SChicago Duan { 125a1649ec6SChicago Duan const uint16_t* coresCount = 126a1649ec6SChicago Duan std::get_if<uint16_t>(&property.second); 127a1649ec6SChicago Duan if (coresCount == nullptr) 128a1649ec6SChicago Duan { 129ac106bf6SEd Tanous messages::internalError(asyncResp->res); 130a1649ec6SChicago Duan return; 131a1649ec6SChicago Duan } 132ac106bf6SEd Tanous asyncResp->res.jsonValue["TotalCores"] = *coresCount; 133ac6a4445SGunnar Mills } 134dc3fa667SJonathan Doman else if (property.first == "MaxSpeedInMhz") 135dc3fa667SJonathan Doman { 136dc3fa667SJonathan Doman const uint32_t* value = std::get_if<uint32_t>(&property.second); 137dc3fa667SJonathan Doman if (value != nullptr) 138dc3fa667SJonathan Doman { 139ac106bf6SEd Tanous asyncResp->res.jsonValue["MaxSpeedMHz"] = *value; 140dc3fa667SJonathan Doman } 141dc3fa667SJonathan Doman } 142ac6a4445SGunnar Mills else if (property.first == "Socket") 143ac6a4445SGunnar Mills { 144ac6a4445SGunnar Mills const std::string* value = 145ac6a4445SGunnar Mills std::get_if<std::string>(&property.second); 146ac6a4445SGunnar Mills if (value != nullptr) 147ac6a4445SGunnar Mills { 148ac106bf6SEd Tanous asyncResp->res.jsonValue["Socket"] = *value; 149ac6a4445SGunnar Mills } 150ac6a4445SGunnar Mills } 151ac6a4445SGunnar Mills else if (property.first == "ThreadCount") 152ac6a4445SGunnar Mills { 153dc3fa667SJonathan Doman const uint16_t* value = std::get_if<uint16_t>(&property.second); 154ac6a4445SGunnar Mills if (value != nullptr) 155ac6a4445SGunnar Mills { 156ac106bf6SEd Tanous asyncResp->res.jsonValue["TotalThreads"] = *value; 157ac6a4445SGunnar Mills } 158ac6a4445SGunnar Mills } 1591930fbd4SBrandon Kim else if (property.first == "EffectiveFamily") 160ac6a4445SGunnar Mills { 1611930fbd4SBrandon Kim const uint16_t* value = std::get_if<uint16_t>(&property.second); 1626169de2cSBrad Bishop if (value != nullptr && *value != 2) 163ac6a4445SGunnar Mills { 164ac106bf6SEd Tanous asyncResp->res.jsonValue["ProcessorId"]["EffectiveFamily"] = 165866e4862SEd Tanous "0x" + intToHexString(*value, 4); 166ac6a4445SGunnar Mills } 167ac6a4445SGunnar Mills } 1681930fbd4SBrandon Kim else if (property.first == "EffectiveModel") 1691930fbd4SBrandon Kim { 1701930fbd4SBrandon Kim const uint16_t* value = std::get_if<uint16_t>(&property.second); 1711930fbd4SBrandon Kim if (value == nullptr) 1721930fbd4SBrandon Kim { 173ac106bf6SEd Tanous messages::internalError(asyncResp->res); 1741930fbd4SBrandon Kim return; 1751930fbd4SBrandon Kim } 1766169de2cSBrad Bishop if (*value != 0) 1776169de2cSBrad Bishop { 178ac106bf6SEd Tanous asyncResp->res.jsonValue["ProcessorId"]["EffectiveModel"] = 179866e4862SEd Tanous "0x" + intToHexString(*value, 4); 1801930fbd4SBrandon Kim } 1816169de2cSBrad Bishop } 182ac6a4445SGunnar Mills else if (property.first == "Id") 183ac6a4445SGunnar Mills { 184ac6a4445SGunnar Mills const uint64_t* value = std::get_if<uint64_t>(&property.second); 185ac6a4445SGunnar Mills if (value != nullptr && *value != 0) 186ac6a4445SGunnar Mills { 187ac106bf6SEd Tanous asyncResp->res 188ac6a4445SGunnar Mills .jsonValue["ProcessorId"]["IdentificationRegisters"] = 189866e4862SEd Tanous "0x" + intToHexString(*value, 16); 190ac6a4445SGunnar Mills } 191ac6a4445SGunnar Mills } 1921930fbd4SBrandon Kim else if (property.first == "Microcode") 1931930fbd4SBrandon Kim { 1941930fbd4SBrandon Kim const uint32_t* value = std::get_if<uint32_t>(&property.second); 1951930fbd4SBrandon Kim if (value == nullptr) 1961930fbd4SBrandon Kim { 197ac106bf6SEd Tanous messages::internalError(asyncResp->res); 1981930fbd4SBrandon Kim return; 1991930fbd4SBrandon Kim } 2006169de2cSBrad Bishop if (*value != 0) 2016169de2cSBrad Bishop { 202ac106bf6SEd Tanous asyncResp->res.jsonValue["ProcessorId"]["MicrocodeInfo"] = 203866e4862SEd Tanous "0x" + intToHexString(*value, 8); 2041930fbd4SBrandon Kim } 2056169de2cSBrad Bishop } 2061930fbd4SBrandon Kim else if (property.first == "Step") 2071930fbd4SBrandon Kim { 2081930fbd4SBrandon Kim const uint16_t* value = std::get_if<uint16_t>(&property.second); 2091930fbd4SBrandon Kim if (value == nullptr) 2101930fbd4SBrandon Kim { 211ac106bf6SEd Tanous messages::internalError(asyncResp->res); 2121930fbd4SBrandon Kim return; 2131930fbd4SBrandon Kim } 214b9d679d1SMichael Shen if (*value != std::numeric_limits<uint16_t>::max()) 2156169de2cSBrad Bishop { 216ac106bf6SEd Tanous asyncResp->res.jsonValue["ProcessorId"]["Step"] = 217866e4862SEd Tanous "0x" + intToHexString(*value, 4); 2181930fbd4SBrandon Kim } 219ac6a4445SGunnar Mills } 220ac6a4445SGunnar Mills } 221ac6a4445SGunnar Mills } 2226169de2cSBrad Bishop } 223ac6a4445SGunnar Mills 224bd79bce8SPatrick Williams inline void getCpuDataByService( 225bd79bce8SPatrick Williams std::shared_ptr<bmcweb::AsyncResp> asyncResp, const std::string& cpuId, 226bd79bce8SPatrick Williams const std::string& service, const std::string& objPath) 227ac6a4445SGunnar Mills { 22862598e31SEd Tanous BMCWEB_LOG_DEBUG("Get available system cpu resources by service."); 229ac6a4445SGunnar Mills 2305eb468daSGeorge Liu sdbusplus::message::object_path path("/xyz/openbmc_project/inventory"); 2315eb468daSGeorge Liu dbus::utility::getManagedObjects( 2325eb468daSGeorge Liu service, path, 233ac106bf6SEd Tanous [cpuId, service, objPath, asyncResp{std::move(asyncResp)}]( 2345e7e2dc5SEd Tanous const boost::system::error_code& ec, 235ac6a4445SGunnar Mills const dbus::utility::ManagedObjectType& dbusData) { 236ac6a4445SGunnar Mills if (ec) 237ac6a4445SGunnar Mills { 23862598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error"); 239ac106bf6SEd Tanous messages::internalError(asyncResp->res); 240ac6a4445SGunnar Mills return; 241ac6a4445SGunnar Mills } 242ac106bf6SEd Tanous asyncResp->res.jsonValue["Id"] = cpuId; 243ac106bf6SEd Tanous asyncResp->res.jsonValue["Name"] = "Processor"; 244539d8c6bSEd Tanous asyncResp->res.jsonValue["ProcessorType"] = 245539d8c6bSEd Tanous processor::ProcessorType::CPU; 246ac6a4445SGunnar Mills 247ac6a4445SGunnar Mills for (const auto& object : dbusData) 248ac6a4445SGunnar Mills { 249ac6a4445SGunnar Mills if (object.first.str == objPath) 250ac6a4445SGunnar Mills { 251ac106bf6SEd Tanous getCpuDataByInterface(asyncResp, object.second); 252ac6a4445SGunnar Mills } 253ac6a4445SGunnar Mills } 254ac6a4445SGunnar Mills return; 2555eb468daSGeorge Liu }); 256ac6a4445SGunnar Mills } 257ac6a4445SGunnar Mills 258dfbf7de5SChris Cain /** 259dfbf7de5SChris Cain * @brief Translates throttle cause DBUS property to redfish. 260dfbf7de5SChris Cain * 261dfbf7de5SChris Cain * @param[in] dbusSource The throttle cause from DBUS 262dfbf7de5SChris Cain * 263dfbf7de5SChris Cain * @return Returns as a string, the throttle cause in Redfish terms. If 264dfbf7de5SChris Cain * translation cannot be done, returns "Unknown" throttle reason. 265dfbf7de5SChris Cain */ 266dfbf7de5SChris Cain inline processor::ThrottleCause 267dfbf7de5SChris Cain dbusToRfThrottleCause(const std::string& dbusSource) 268dfbf7de5SChris Cain { 269dfbf7de5SChris Cain if (dbusSource == 270dfbf7de5SChris Cain "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.ClockLimit") 271dfbf7de5SChris Cain { 272dfbf7de5SChris Cain return processor::ThrottleCause::ClockLimit; 273dfbf7de5SChris Cain } 274dfbf7de5SChris Cain if (dbusSource == 275dfbf7de5SChris Cain "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.ManagementDetectedFault") 276dfbf7de5SChris Cain { 277dfbf7de5SChris Cain return processor::ThrottleCause::ManagementDetectedFault; 278dfbf7de5SChris Cain } 279dfbf7de5SChris Cain if (dbusSource == 280dfbf7de5SChris Cain "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.PowerLimit") 281dfbf7de5SChris Cain { 282dfbf7de5SChris Cain return processor::ThrottleCause::PowerLimit; 283dfbf7de5SChris Cain } 284dfbf7de5SChris Cain if (dbusSource == 285dfbf7de5SChris Cain "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.ThermalLimit") 286dfbf7de5SChris Cain { 287dfbf7de5SChris Cain return processor::ThrottleCause::ThermalLimit; 288dfbf7de5SChris Cain } 289dfbf7de5SChris Cain if (dbusSource == 290dfbf7de5SChris Cain "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.Unknown") 291dfbf7de5SChris Cain { 292dfbf7de5SChris Cain return processor::ThrottleCause::Unknown; 293dfbf7de5SChris Cain } 294dfbf7de5SChris Cain return processor::ThrottleCause::Invalid; 295dfbf7de5SChris Cain } 296dfbf7de5SChris Cain 297dfbf7de5SChris Cain inline void 298ac106bf6SEd Tanous readThrottleProperties(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 299dfbf7de5SChris Cain const boost::system::error_code& ec, 300dfbf7de5SChris Cain const dbus::utility::DBusPropertiesMap& properties) 301dfbf7de5SChris Cain { 302dfbf7de5SChris Cain if (ec) 303dfbf7de5SChris Cain { 30462598e31SEd Tanous BMCWEB_LOG_ERROR("Processor Throttle getAllProperties error {}", ec); 305ac106bf6SEd Tanous messages::internalError(asyncResp->res); 306dfbf7de5SChris Cain return; 307dfbf7de5SChris Cain } 308dfbf7de5SChris Cain 309dfbf7de5SChris Cain const bool* status = nullptr; 310dfbf7de5SChris Cain const std::vector<std::string>* causes = nullptr; 311dfbf7de5SChris Cain 312dfbf7de5SChris Cain if (!sdbusplus::unpackPropertiesNoThrow(dbus_utils::UnpackErrorPrinter(), 313dfbf7de5SChris Cain properties, "Throttled", status, 314dfbf7de5SChris Cain "ThrottleCauses", causes)) 315dfbf7de5SChris Cain { 316ac106bf6SEd Tanous messages::internalError(asyncResp->res); 317dfbf7de5SChris Cain return; 318dfbf7de5SChris Cain } 319dfbf7de5SChris Cain 320ac106bf6SEd Tanous asyncResp->res.jsonValue["Throttled"] = *status; 321dfbf7de5SChris Cain nlohmann::json::array_t rCauses; 322dfbf7de5SChris Cain for (const std::string& cause : *causes) 323dfbf7de5SChris Cain { 324dfbf7de5SChris Cain processor::ThrottleCause rfCause = dbusToRfThrottleCause(cause); 325dfbf7de5SChris Cain if (rfCause == processor::ThrottleCause::Invalid) 326dfbf7de5SChris Cain { 327ac106bf6SEd Tanous messages::internalError(asyncResp->res); 328dfbf7de5SChris Cain return; 329dfbf7de5SChris Cain } 330dfbf7de5SChris Cain 331dfbf7de5SChris Cain rCauses.emplace_back(rfCause); 332dfbf7de5SChris Cain } 333ac106bf6SEd Tanous asyncResp->res.jsonValue["ThrottleCauses"] = std::move(rCauses); 334dfbf7de5SChris Cain } 335dfbf7de5SChris Cain 336bd79bce8SPatrick Williams inline void getThrottleProperties( 337bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 338bd79bce8SPatrick Williams const std::string& service, const std::string& objectPath) 339dfbf7de5SChris Cain { 34062598e31SEd Tanous BMCWEB_LOG_DEBUG("Get processor throttle resources"); 341dfbf7de5SChris Cain 342*deae6a78SEd Tanous dbus::utility::getAllProperties( 343*deae6a78SEd Tanous service, objectPath, "xyz.openbmc_project.Control.Power.Throttle", 344ac106bf6SEd Tanous [asyncResp](const boost::system::error_code& ec, 345dfbf7de5SChris Cain const dbus::utility::DBusPropertiesMap& properties) { 346ac106bf6SEd Tanous readThrottleProperties(asyncResp, ec, properties); 347dfbf7de5SChris Cain }); 348dfbf7de5SChris Cain } 349dfbf7de5SChris Cain 350ac106bf6SEd Tanous inline void getCpuAssetData(std::shared_ptr<bmcweb::AsyncResp> asyncResp, 351ac6a4445SGunnar Mills const std::string& service, 352ac6a4445SGunnar Mills const std::string& objPath) 353ac6a4445SGunnar Mills { 35462598e31SEd Tanous BMCWEB_LOG_DEBUG("Get Cpu Asset Data"); 355*deae6a78SEd Tanous dbus::utility::getAllProperties( 356*deae6a78SEd Tanous service, objPath, "xyz.openbmc_project.Inventory.Decorator.Asset", 357ac106bf6SEd Tanous [objPath, asyncResp{std::move(asyncResp)}]( 3585e7e2dc5SEd Tanous const boost::system::error_code& ec, 359351053f2SKrzysztof Grobelny const dbus::utility::DBusPropertiesMap& properties) { 360ac6a4445SGunnar Mills if (ec) 361ac6a4445SGunnar Mills { 36262598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error"); 363ac106bf6SEd Tanous messages::internalError(asyncResp->res); 364ac6a4445SGunnar Mills return; 365ac6a4445SGunnar Mills } 366ac6a4445SGunnar Mills 367351053f2SKrzysztof Grobelny const std::string* serialNumber = nullptr; 368351053f2SKrzysztof Grobelny const std::string* model = nullptr; 369351053f2SKrzysztof Grobelny const std::string* manufacturer = nullptr; 370351053f2SKrzysztof Grobelny const std::string* partNumber = nullptr; 371351053f2SKrzysztof Grobelny const std::string* sparePartNumber = nullptr; 372351053f2SKrzysztof Grobelny 373351053f2SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 374351053f2SKrzysztof Grobelny dbus_utils::UnpackErrorPrinter(), properties, "SerialNumber", 375351053f2SKrzysztof Grobelny serialNumber, "Model", model, "Manufacturer", manufacturer, 376351053f2SKrzysztof Grobelny "PartNumber", partNumber, "SparePartNumber", sparePartNumber); 377351053f2SKrzysztof Grobelny 378351053f2SKrzysztof Grobelny if (!success) 379ac6a4445SGunnar Mills { 380ac106bf6SEd Tanous messages::internalError(asyncResp->res); 381351053f2SKrzysztof Grobelny return; 382ac6a4445SGunnar Mills } 383351053f2SKrzysztof Grobelny 384351053f2SKrzysztof Grobelny if (serialNumber != nullptr && !serialNumber->empty()) 385ac6a4445SGunnar Mills { 386ac106bf6SEd Tanous asyncResp->res.jsonValue["SerialNumber"] = *serialNumber; 387351053f2SKrzysztof Grobelny } 388351053f2SKrzysztof Grobelny 389351053f2SKrzysztof Grobelny if ((model != nullptr) && !model->empty()) 390ac6a4445SGunnar Mills { 391ac106bf6SEd Tanous asyncResp->res.jsonValue["Model"] = *model; 392ac6a4445SGunnar Mills } 393ac6a4445SGunnar Mills 394351053f2SKrzysztof Grobelny if (manufacturer != nullptr) 395ac6a4445SGunnar Mills { 396ac106bf6SEd Tanous asyncResp->res.jsonValue["Manufacturer"] = *manufacturer; 397ac6a4445SGunnar Mills 398ac6a4445SGunnar Mills // Otherwise would be unexpected. 399351053f2SKrzysztof Grobelny if (manufacturer->find("Intel") != std::string::npos) 400ac6a4445SGunnar Mills { 401ac106bf6SEd Tanous asyncResp->res.jsonValue["ProcessorArchitecture"] = "x86"; 402ac106bf6SEd Tanous asyncResp->res.jsonValue["InstructionSet"] = "x86-64"; 403ac6a4445SGunnar Mills } 404351053f2SKrzysztof Grobelny else if (manufacturer->find("IBM") != std::string::npos) 405ac6a4445SGunnar Mills { 406ac106bf6SEd Tanous asyncResp->res.jsonValue["ProcessorArchitecture"] = "Power"; 407ac106bf6SEd Tanous asyncResp->res.jsonValue["InstructionSet"] = "PowerISA"; 408ac6a4445SGunnar Mills } 409ac6a4445SGunnar Mills } 410cba4f448SSunnySrivastava1984 411351053f2SKrzysztof Grobelny if (partNumber != nullptr) 412cba4f448SSunnySrivastava1984 { 413ac106bf6SEd Tanous asyncResp->res.jsonValue["PartNumber"] = *partNumber; 414cba4f448SSunnySrivastava1984 } 415cba4f448SSunnySrivastava1984 4166169de2cSBrad Bishop if (sparePartNumber != nullptr && !sparePartNumber->empty()) 417cba4f448SSunnySrivastava1984 { 418ac106bf6SEd Tanous asyncResp->res.jsonValue["SparePartNumber"] = *sparePartNumber; 419cba4f448SSunnySrivastava1984 } 420351053f2SKrzysztof Grobelny }); 421ac6a4445SGunnar Mills } 422ac6a4445SGunnar Mills 423ac106bf6SEd Tanous inline void getCpuRevisionData(std::shared_ptr<bmcweb::AsyncResp> asyncResp, 424ac6a4445SGunnar Mills const std::string& service, 425ac6a4445SGunnar Mills const std::string& objPath) 426ac6a4445SGunnar Mills { 42762598e31SEd Tanous BMCWEB_LOG_DEBUG("Get Cpu Revision Data"); 428*deae6a78SEd Tanous dbus::utility::getAllProperties( 429*deae6a78SEd Tanous service, objPath, "xyz.openbmc_project.Inventory.Decorator.Revision", 430ac106bf6SEd Tanous [objPath, asyncResp{std::move(asyncResp)}]( 4315e7e2dc5SEd Tanous const boost::system::error_code& ec, 432351053f2SKrzysztof Grobelny const dbus::utility::DBusPropertiesMap& properties) { 433ac6a4445SGunnar Mills if (ec) 434ac6a4445SGunnar Mills { 43562598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error"); 436ac106bf6SEd Tanous messages::internalError(asyncResp->res); 437ac6a4445SGunnar Mills return; 438ac6a4445SGunnar Mills } 439ac6a4445SGunnar Mills 440351053f2SKrzysztof Grobelny const std::string* version = nullptr; 441351053f2SKrzysztof Grobelny 442351053f2SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 443bd79bce8SPatrick Williams dbus_utils::UnpackErrorPrinter(), properties, "Version", 444bd79bce8SPatrick Williams version); 445351053f2SKrzysztof Grobelny 446351053f2SKrzysztof Grobelny if (!success) 447ac6a4445SGunnar Mills { 448ac106bf6SEd Tanous messages::internalError(asyncResp->res); 449351053f2SKrzysztof Grobelny return; 450351053f2SKrzysztof Grobelny } 451351053f2SKrzysztof Grobelny 452351053f2SKrzysztof Grobelny if (version != nullptr) 453ac6a4445SGunnar Mills { 454ac106bf6SEd Tanous asyncResp->res.jsonValue["Version"] = *version; 455ac6a4445SGunnar Mills } 456351053f2SKrzysztof Grobelny }); 457ac6a4445SGunnar Mills } 458ac6a4445SGunnar Mills 4598d1b46d7Szhanghch05 inline void getAcceleratorDataByService( 460ac106bf6SEd Tanous std::shared_ptr<bmcweb::AsyncResp> asyncResp, const std::string& acclrtrId, 4618d1b46d7Szhanghch05 const std::string& service, const std::string& objPath) 462ac6a4445SGunnar Mills { 46362598e31SEd Tanous BMCWEB_LOG_DEBUG("Get available system Accelerator resources by service."); 464*deae6a78SEd Tanous dbus::utility::getAllProperties( 465*deae6a78SEd Tanous service, objPath, "", 466ac106bf6SEd Tanous [acclrtrId, asyncResp{std::move(asyncResp)}]( 4675e7e2dc5SEd Tanous const boost::system::error_code& ec, 468351053f2SKrzysztof Grobelny const dbus::utility::DBusPropertiesMap& properties) { 469ac6a4445SGunnar Mills if (ec) 470ac6a4445SGunnar Mills { 47162598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error"); 472ac106bf6SEd Tanous messages::internalError(asyncResp->res); 473ac6a4445SGunnar Mills return; 474ac6a4445SGunnar Mills } 475ac6a4445SGunnar Mills 476351053f2SKrzysztof Grobelny const bool* functional = nullptr; 477351053f2SKrzysztof Grobelny const bool* present = nullptr; 478351053f2SKrzysztof Grobelny 479351053f2SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 480351053f2SKrzysztof Grobelny dbus_utils::UnpackErrorPrinter(), properties, "Functional", 481351053f2SKrzysztof Grobelny functional, "Present", present); 482351053f2SKrzysztof Grobelny 483351053f2SKrzysztof Grobelny if (!success) 484ac6a4445SGunnar Mills { 485ac106bf6SEd Tanous messages::internalError(asyncResp->res); 486351053f2SKrzysztof Grobelny return; 487ac6a4445SGunnar Mills } 488ac6a4445SGunnar Mills 489ac6a4445SGunnar Mills std::string state = "Enabled"; 490ac6a4445SGunnar Mills std::string health = "OK"; 491ac6a4445SGunnar Mills 492351053f2SKrzysztof Grobelny if (present != nullptr && !*present) 493ac6a4445SGunnar Mills { 494ac6a4445SGunnar Mills state = "Absent"; 495ac6a4445SGunnar Mills } 496ac6a4445SGunnar Mills 497351053f2SKrzysztof Grobelny if (functional != nullptr && !*functional) 498ac6a4445SGunnar Mills { 499ac6a4445SGunnar Mills if (state == "Enabled") 500ac6a4445SGunnar Mills { 501ac6a4445SGunnar Mills health = "Critical"; 502ac6a4445SGunnar Mills } 503ac6a4445SGunnar Mills } 504ac6a4445SGunnar Mills 505ac106bf6SEd Tanous asyncResp->res.jsonValue["Id"] = acclrtrId; 506ac106bf6SEd Tanous asyncResp->res.jsonValue["Name"] = "Processor"; 507ac106bf6SEd Tanous asyncResp->res.jsonValue["Status"]["State"] = state; 508ac106bf6SEd Tanous asyncResp->res.jsonValue["Status"]["Health"] = health; 509539d8c6bSEd Tanous asyncResp->res.jsonValue["ProcessorType"] = 510539d8c6bSEd Tanous processor::ProcessorType::Accelerator; 511351053f2SKrzysztof Grobelny }); 512ac6a4445SGunnar Mills } 513ac6a4445SGunnar Mills 514dba0c291SJonathan Doman // OperatingConfig D-Bus Types 515dba0c291SJonathan Doman using TurboProfileProperty = std::vector<std::tuple<uint32_t, size_t>>; 516dba0c291SJonathan Doman using BaseSpeedPrioritySettingsProperty = 517dba0c291SJonathan Doman std::vector<std::tuple<uint32_t, std::vector<uint32_t>>>; 518dba0c291SJonathan Doman // uint32_t and size_t may or may not be the same type, requiring a dedup'd 519dba0c291SJonathan Doman // variant 520dba0c291SJonathan Doman 521dba0c291SJonathan Doman /** 522dba0c291SJonathan Doman * Fill out the HighSpeedCoreIDs in a Processor resource from the given 523dba0c291SJonathan Doman * OperatingConfig D-Bus property. 524dba0c291SJonathan Doman * 525ac106bf6SEd Tanous * @param[in,out] asyncResp Async HTTP response. 526dba0c291SJonathan Doman * @param[in] baseSpeedSettings Full list of base speed priority groups, 527dba0c291SJonathan Doman * to use to determine the list of high 528dba0c291SJonathan Doman * speed cores. 529dba0c291SJonathan Doman */ 530dba0c291SJonathan Doman inline void highSpeedCoreIdsHandler( 531ac106bf6SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 532dba0c291SJonathan Doman const BaseSpeedPrioritySettingsProperty& baseSpeedSettings) 533dba0c291SJonathan Doman { 534dba0c291SJonathan Doman // The D-Bus property does not indicate which bucket is the "high 535dba0c291SJonathan Doman // priority" group, so let's discern that by looking for the one with 536dba0c291SJonathan Doman // highest base frequency. 537dba0c291SJonathan Doman auto highPriorityGroup = baseSpeedSettings.cend(); 538dba0c291SJonathan Doman uint32_t highestBaseSpeed = 0; 539dba0c291SJonathan Doman for (auto it = baseSpeedSettings.cbegin(); it != baseSpeedSettings.cend(); 540dba0c291SJonathan Doman ++it) 541dba0c291SJonathan Doman { 542dba0c291SJonathan Doman const uint32_t baseFreq = std::get<uint32_t>(*it); 543dba0c291SJonathan Doman if (baseFreq > highestBaseSpeed) 544dba0c291SJonathan Doman { 545dba0c291SJonathan Doman highestBaseSpeed = baseFreq; 546dba0c291SJonathan Doman highPriorityGroup = it; 547dba0c291SJonathan Doman } 548dba0c291SJonathan Doman } 549dba0c291SJonathan Doman 550ac106bf6SEd Tanous nlohmann::json& jsonCoreIds = asyncResp->res.jsonValue["HighSpeedCoreIDs"]; 551dba0c291SJonathan Doman jsonCoreIds = nlohmann::json::array(); 552dba0c291SJonathan Doman 553dba0c291SJonathan Doman // There may not be any entries in the D-Bus property, so only populate 554dba0c291SJonathan Doman // if there was actually something there. 555dba0c291SJonathan Doman if (highPriorityGroup != baseSpeedSettings.cend()) 556dba0c291SJonathan Doman { 557dba0c291SJonathan Doman jsonCoreIds = std::get<std::vector<uint32_t>>(*highPriorityGroup); 558dba0c291SJonathan Doman } 559dba0c291SJonathan Doman } 560dba0c291SJonathan Doman 561dba0c291SJonathan Doman /** 562dba0c291SJonathan Doman * Fill out OperatingConfig related items in a Processor resource by requesting 563dba0c291SJonathan Doman * data from the given D-Bus object. 564dba0c291SJonathan Doman * 565ac106bf6SEd Tanous * @param[in,out] asyncResp Async HTTP response. 566dba0c291SJonathan Doman * @param[in] cpuId CPU D-Bus name. 567dba0c291SJonathan Doman * @param[in] service D-Bus service to query. 568dba0c291SJonathan Doman * @param[in] objPath D-Bus object to query. 569dba0c291SJonathan Doman */ 570ac106bf6SEd Tanous inline void 571ac106bf6SEd Tanous getCpuConfigData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 572ac106bf6SEd Tanous const std::string& cpuId, const std::string& service, 573dba0c291SJonathan Doman const std::string& objPath) 574dba0c291SJonathan Doman { 57562598e31SEd Tanous BMCWEB_LOG_INFO("Getting CPU operating configs for {}", cpuId); 576dba0c291SJonathan Doman 577dba0c291SJonathan Doman // First, GetAll CurrentOperatingConfig properties on the object 578*deae6a78SEd Tanous dbus::utility::getAllProperties( 579*deae6a78SEd Tanous service, objPath, 580351053f2SKrzysztof Grobelny "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig", 581ac106bf6SEd Tanous [asyncResp, cpuId, 5825e7e2dc5SEd Tanous service](const boost::system::error_code& ec, 583351053f2SKrzysztof Grobelny const dbus::utility::DBusPropertiesMap& properties) { 584dba0c291SJonathan Doman if (ec) 585dba0c291SJonathan Doman { 58662598e31SEd Tanous BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec, ec.message()); 587ac106bf6SEd Tanous messages::internalError(asyncResp->res); 588dba0c291SJonathan Doman return; 589dba0c291SJonathan Doman } 590dba0c291SJonathan Doman 591ac106bf6SEd Tanous nlohmann::json& json = asyncResp->res.jsonValue; 592dba0c291SJonathan Doman 593351053f2SKrzysztof Grobelny const sdbusplus::message::object_path* appliedConfig = nullptr; 594351053f2SKrzysztof Grobelny const bool* baseSpeedPriorityEnabled = nullptr; 595351053f2SKrzysztof Grobelny 596351053f2SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 597351053f2SKrzysztof Grobelny dbus_utils::UnpackErrorPrinter(), properties, "AppliedConfig", 598351053f2SKrzysztof Grobelny appliedConfig, "BaseSpeedPriorityEnabled", 599351053f2SKrzysztof Grobelny baseSpeedPriorityEnabled); 600351053f2SKrzysztof Grobelny 601351053f2SKrzysztof Grobelny if (!success) 602dba0c291SJonathan Doman { 603ac106bf6SEd Tanous messages::internalError(asyncResp->res); 604351053f2SKrzysztof Grobelny return; 605dba0c291SJonathan Doman } 606dba0c291SJonathan Doman 607351053f2SKrzysztof Grobelny if (appliedConfig != nullptr) 608351053f2SKrzysztof Grobelny { 609351053f2SKrzysztof Grobelny const std::string& dbusPath = appliedConfig->str; 6101476687dSEd Tanous nlohmann::json::object_t operatingConfig; 611ef4c65b7SEd Tanous operatingConfig["@odata.id"] = boost::urls::format( 612253f11b8SEd Tanous "/redfish/v1/Systems/{}/Processors/{}/OperatingConfigs", 613253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME, cpuId); 6141476687dSEd Tanous json["OperatingConfigs"] = std::move(operatingConfig); 615dba0c291SJonathan Doman 616dba0c291SJonathan Doman // Reuse the D-Bus config object name for the Redfish 617dba0c291SJonathan Doman // URI 618dba0c291SJonathan Doman size_t baseNamePos = dbusPath.rfind('/'); 619dba0c291SJonathan Doman if (baseNamePos == std::string::npos || 620dba0c291SJonathan Doman baseNamePos == (dbusPath.size() - 1)) 621dba0c291SJonathan Doman { 622dba0c291SJonathan Doman // If the AppliedConfig was somehow not a valid path, 623dba0c291SJonathan Doman // skip adding any more properties, since everything 624dba0c291SJonathan Doman // else is tied to this applied config. 625ac106bf6SEd Tanous messages::internalError(asyncResp->res); 626351053f2SKrzysztof Grobelny return; 627dba0c291SJonathan Doman } 6281476687dSEd Tanous nlohmann::json::object_t appliedOperatingConfig; 629ef4c65b7SEd Tanous appliedOperatingConfig["@odata.id"] = boost::urls::format( 630253f11b8SEd Tanous "/redfish/v1/Systems/{}/Processors/{}/OperatingConfigs/{}", 631253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME, cpuId, 632253f11b8SEd Tanous dbusPath.substr(baseNamePos + 1)); 633bd79bce8SPatrick Williams json["AppliedOperatingConfig"] = 634bd79bce8SPatrick Williams std::move(appliedOperatingConfig); 635dba0c291SJonathan Doman 636dba0c291SJonathan Doman // Once we found the current applied config, queue another 637dba0c291SJonathan Doman // request to read the base freq core ids out of that 638dba0c291SJonathan Doman // config. 639*deae6a78SEd Tanous dbus::utility::getProperty<BaseSpeedPrioritySettingsProperty>( 640*deae6a78SEd Tanous service, dbusPath, 6411e1e598dSJonathan Doman "xyz.openbmc_project.Inventory.Item.Cpu." 6421e1e598dSJonathan Doman "OperatingConfig", 6431e1e598dSJonathan Doman "BaseSpeedPrioritySettings", 644bd79bce8SPatrick Williams [asyncResp](const boost::system::error_code& ec2, 645bd79bce8SPatrick Williams const BaseSpeedPrioritySettingsProperty& 646bd79bce8SPatrick Williams baseSpeedList) { 6478a592810SEd Tanous if (ec2) 648dba0c291SJonathan Doman { 649bd79bce8SPatrick Williams BMCWEB_LOG_WARNING("D-Bus Property Get error: {}", 650bd79bce8SPatrick Williams ec2); 651ac106bf6SEd Tanous messages::internalError(asyncResp->res); 652dba0c291SJonathan Doman return; 653dba0c291SJonathan Doman } 6541e1e598dSJonathan Doman 655ac106bf6SEd Tanous highSpeedCoreIdsHandler(asyncResp, baseSpeedList); 6561e1e598dSJonathan Doman }); 657dba0c291SJonathan Doman } 658351053f2SKrzysztof Grobelny 659351053f2SKrzysztof Grobelny if (baseSpeedPriorityEnabled != nullptr) 660dba0c291SJonathan Doman { 661dba0c291SJonathan Doman json["BaseSpeedPriorityState"] = 662351053f2SKrzysztof Grobelny *baseSpeedPriorityEnabled ? "Enabled" : "Disabled"; 663dba0c291SJonathan Doman } 664351053f2SKrzysztof Grobelny }); 665dba0c291SJonathan Doman } 666dba0c291SJonathan Doman 667cba4f448SSunnySrivastava1984 /** 668cba4f448SSunnySrivastava1984 * @brief Fill out location info of a processor by 669cba4f448SSunnySrivastava1984 * requesting data from the given D-Bus object. 670cba4f448SSunnySrivastava1984 * 671ac106bf6SEd Tanous * @param[in,out] asyncResp Async HTTP response. 672cba4f448SSunnySrivastava1984 * @param[in] service D-Bus service to query. 673cba4f448SSunnySrivastava1984 * @param[in] objPath D-Bus object to query. 674cba4f448SSunnySrivastava1984 */ 675ac106bf6SEd Tanous inline void getCpuLocationCode(std::shared_ptr<bmcweb::AsyncResp> asyncResp, 676cba4f448SSunnySrivastava1984 const std::string& service, 677cba4f448SSunnySrivastava1984 const std::string& objPath) 678cba4f448SSunnySrivastava1984 { 67962598e31SEd Tanous BMCWEB_LOG_DEBUG("Get Cpu Location Data"); 680*deae6a78SEd Tanous dbus::utility::getProperty<std::string>( 681*deae6a78SEd Tanous service, objPath, 6821e1e598dSJonathan Doman "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode", 683ac106bf6SEd Tanous [objPath, asyncResp{std::move(asyncResp)}]( 684ac106bf6SEd Tanous const boost::system::error_code& ec, const std::string& property) { 685cba4f448SSunnySrivastava1984 if (ec) 686cba4f448SSunnySrivastava1984 { 68762598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error"); 688ac106bf6SEd Tanous messages::internalError(asyncResp->res); 689cba4f448SSunnySrivastava1984 return; 690cba4f448SSunnySrivastava1984 } 691cba4f448SSunnySrivastava1984 692bd79bce8SPatrick Williams asyncResp->res 693bd79bce8SPatrick Williams .jsonValue["Location"]["PartLocation"]["ServiceLabel"] = 6941e1e598dSJonathan Doman property; 6951e1e598dSJonathan Doman }); 696cba4f448SSunnySrivastava1984 } 697cba4f448SSunnySrivastava1984 698c951448aSJonathan Doman /** 69949e429caSJonathan Doman * Populate the unique identifier in a Processor resource by requesting data 70049e429caSJonathan Doman * from the given D-Bus object. 70149e429caSJonathan Doman * 702ac106bf6SEd Tanous * @param[in,out] asyncResp Async HTTP response. 70349e429caSJonathan Doman * @param[in] service D-Bus service to query. 70449e429caSJonathan Doman * @param[in] objPath D-Bus object to query. 70549e429caSJonathan Doman */ 706ac106bf6SEd Tanous inline void getCpuUniqueId(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 70749e429caSJonathan Doman const std::string& service, 70849e429caSJonathan Doman const std::string& objectPath) 70949e429caSJonathan Doman { 71062598e31SEd Tanous BMCWEB_LOG_DEBUG("Get CPU UniqueIdentifier"); 711*deae6a78SEd Tanous dbus::utility::getProperty<std::string>( 712*deae6a78SEd Tanous service, objectPath, 7131e1e598dSJonathan Doman "xyz.openbmc_project.Inventory.Decorator.UniqueIdentifier", 7141e1e598dSJonathan Doman "UniqueIdentifier", 715ac106bf6SEd Tanous [asyncResp](const boost::system::error_code& ec, 716ac106bf6SEd Tanous const std::string& id) { 7171e1e598dSJonathan Doman if (ec) 71849e429caSJonathan Doman { 71962598e31SEd Tanous BMCWEB_LOG_ERROR("Failed to read cpu unique id: {}", ec); 720ac106bf6SEd Tanous messages::internalError(asyncResp->res); 72149e429caSJonathan Doman return; 72249e429caSJonathan Doman } 723ac106bf6SEd Tanous asyncResp->res 724ac106bf6SEd Tanous .jsonValue["ProcessorId"]["ProtectedIdentificationNumber"] = id; 7251e1e598dSJonathan Doman }); 72649e429caSJonathan Doman } 72749e429caSJonathan Doman 72849e429caSJonathan Doman /** 729c951448aSJonathan Doman * Find the D-Bus object representing the requested Processor, and call the 730c951448aSJonathan Doman * handler with the results. If matching object is not found, add 404 error to 731c951448aSJonathan Doman * response and don't call the handler. 732c951448aSJonathan Doman * 733c951448aSJonathan Doman * @param[in,out] resp Async HTTP response. 734c951448aSJonathan Doman * @param[in] processorId Redfish Processor Id. 735c951448aSJonathan Doman * @param[in] handler Callback to continue processing request upon 736c951448aSJonathan Doman * successfully finding object. 737c951448aSJonathan Doman */ 738c951448aSJonathan Doman template <typename Handler> 7398d1b46d7Szhanghch05 inline void getProcessorObject(const std::shared_ptr<bmcweb::AsyncResp>& resp, 740c951448aSJonathan Doman const std::string& processorId, 741c951448aSJonathan Doman Handler&& handler) 742ac6a4445SGunnar Mills { 74362598e31SEd Tanous BMCWEB_LOG_DEBUG("Get available system processor resources."); 744ac6a4445SGunnar Mills 745c951448aSJonathan Doman // GetSubTree on all interfaces which provide info about a Processor 746dfbf7de5SChris Cain constexpr std::array<std::string_view, 9> interfaces = { 747e99073f5SGeorge Liu "xyz.openbmc_project.Common.UUID", 748e99073f5SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.Asset", 749e99073f5SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.Revision", 750e99073f5SGeorge Liu "xyz.openbmc_project.Inventory.Item.Cpu", 751e99073f5SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.LocationCode", 752e99073f5SGeorge Liu "xyz.openbmc_project.Inventory.Item.Accelerator", 753e99073f5SGeorge Liu "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig", 754dfbf7de5SChris Cain "xyz.openbmc_project.Inventory.Decorator.UniqueIdentifier", 755dfbf7de5SChris Cain "xyz.openbmc_project.Control.Power.Throttle"}; 756e99073f5SGeorge Liu dbus::utility::getSubTree( 757e99073f5SGeorge Liu "/xyz/openbmc_project/inventory", 0, interfaces, 758c951448aSJonathan Doman [resp, processorId, handler = std::forward<Handler>(handler)]( 759e99073f5SGeorge Liu const boost::system::error_code& ec, 760e99073f5SGeorge Liu const dbus::utility::MapperGetSubTreeResponse& subtree) { 761ac6a4445SGunnar Mills if (ec) 762ac6a4445SGunnar Mills { 76362598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error: {}", ec); 764c951448aSJonathan Doman messages::internalError(resp->res); 765ac6a4445SGunnar Mills return; 766ac6a4445SGunnar Mills } 7672bab9831SJonathan Doman for (const auto& [objectPath, serviceMap] : subtree) 768ac6a4445SGunnar Mills { 7692bab9831SJonathan Doman // Ignore any objects which don't end with our desired cpu name 77011ba3979SEd Tanous if (!objectPath.ends_with(processorId)) 771ac6a4445SGunnar Mills { 7722bab9831SJonathan Doman continue; 773ac6a4445SGunnar Mills } 7742bab9831SJonathan Doman 775c951448aSJonathan Doman bool found = false; 776c951448aSJonathan Doman // Filter out objects that don't have the CPU-specific 777c951448aSJonathan Doman // interfaces to make sure we can return 404 on non-CPUs 778c951448aSJonathan Doman // (e.g. /redfish/../Processors/dimm0) 7792bab9831SJonathan Doman for (const auto& [serviceName, interfaceList] : serviceMap) 780ac6a4445SGunnar Mills { 7813544d2a7SEd Tanous if (std::ranges::find_first_of(interfaceList, 7823544d2a7SEd Tanous processorInterfaces) != 7833544d2a7SEd Tanous std::end(interfaceList)) 7842bab9831SJonathan Doman { 785c951448aSJonathan Doman found = true; 786c951448aSJonathan Doman break; 787c951448aSJonathan Doman } 788c951448aSJonathan Doman } 789c951448aSJonathan Doman 790c951448aSJonathan Doman if (!found) 7912bab9831SJonathan Doman { 792c951448aSJonathan Doman continue; 793ac6a4445SGunnar Mills } 794c951448aSJonathan Doman 795c951448aSJonathan Doman // Process the first object which does match our cpu name and 796c951448aSJonathan Doman // required interfaces, and potentially ignore any other 797c951448aSJonathan Doman // matching objects. Assume all interfaces we want to process 798c951448aSJonathan Doman // must be on the same object path. 799c951448aSJonathan Doman 8008a592810SEd Tanous handler(objectPath, serviceMap); 801ac6a4445SGunnar Mills return; 802ac6a4445SGunnar Mills } 803c951448aSJonathan Doman messages::resourceNotFound(resp->res, "Processor", processorId); 804e99073f5SGeorge Liu }); 805ac6a4445SGunnar Mills } 806ac6a4445SGunnar Mills 807bd79bce8SPatrick Williams inline void getProcessorData( 808bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 809bd79bce8SPatrick Williams const std::string& processorId, const std::string& objectPath, 8105df6eda2SShantappa Teekappanavar const dbus::utility::MapperServiceMap& serviceMap) 811c951448aSJonathan Doman { 812c951448aSJonathan Doman for (const auto& [serviceName, interfaceList] : serviceMap) 813c951448aSJonathan Doman { 814c951448aSJonathan Doman for (const auto& interface : interfaceList) 815c951448aSJonathan Doman { 816c951448aSJonathan Doman if (interface == "xyz.openbmc_project.Inventory.Decorator.Asset") 817c951448aSJonathan Doman { 818ac106bf6SEd Tanous getCpuAssetData(asyncResp, serviceName, objectPath); 819c951448aSJonathan Doman } 8200fda0f12SGeorge Liu else if (interface == 8210fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.Revision") 822c951448aSJonathan Doman { 823ac106bf6SEd Tanous getCpuRevisionData(asyncResp, serviceName, objectPath); 824c951448aSJonathan Doman } 825c951448aSJonathan Doman else if (interface == "xyz.openbmc_project.Inventory.Item.Cpu") 826c951448aSJonathan Doman { 827ac106bf6SEd Tanous getCpuDataByService(asyncResp, processorId, serviceName, 828c951448aSJonathan Doman objectPath); 829c951448aSJonathan Doman } 8300fda0f12SGeorge Liu else if (interface == 8310fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Item.Accelerator") 832c951448aSJonathan Doman { 833ac106bf6SEd Tanous getAcceleratorDataByService(asyncResp, processorId, serviceName, 834c951448aSJonathan Doman objectPath); 835c951448aSJonathan Doman } 8360fda0f12SGeorge Liu else if ( 8370fda0f12SGeorge Liu interface == 8380fda0f12SGeorge Liu "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig") 839c951448aSJonathan Doman { 840ac106bf6SEd Tanous getCpuConfigData(asyncResp, processorId, serviceName, 841ac106bf6SEd Tanous objectPath); 842c951448aSJonathan Doman } 8430fda0f12SGeorge Liu else if (interface == 8440fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.LocationCode") 845c951448aSJonathan Doman { 846ac106bf6SEd Tanous getCpuLocationCode(asyncResp, serviceName, objectPath); 847c951448aSJonathan Doman } 84871b82f26SSharad Yadav else if (interface == "xyz.openbmc_project.Common.UUID") 84971b82f26SSharad Yadav { 850ac106bf6SEd Tanous getProcessorUUID(asyncResp, serviceName, objectPath); 85171b82f26SSharad Yadav } 8520fda0f12SGeorge Liu else if (interface == 8530fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.UniqueIdentifier") 85449e429caSJonathan Doman { 855ac106bf6SEd Tanous getCpuUniqueId(asyncResp, serviceName, objectPath); 85649e429caSJonathan Doman } 857dfbf7de5SChris Cain else if (interface == "xyz.openbmc_project.Control.Power.Throttle") 858dfbf7de5SChris Cain { 859ac106bf6SEd Tanous getThrottleProperties(asyncResp, serviceName, objectPath); 860dfbf7de5SChris Cain } 861c951448aSJonathan Doman } 862c951448aSJonathan Doman } 863c951448aSJonathan Doman } 864c951448aSJonathan Doman 865dba0c291SJonathan Doman /** 866dba0c291SJonathan Doman * Request all the properties for the given D-Bus object and fill out the 867dba0c291SJonathan Doman * related entries in the Redfish OperatingConfig response. 868dba0c291SJonathan Doman * 869ac106bf6SEd Tanous * @param[in,out] asyncResp Async HTTP response. 870dba0c291SJonathan Doman * @param[in] service D-Bus service name to query. 871dba0c291SJonathan Doman * @param[in] objPath D-Bus object to query. 872dba0c291SJonathan Doman */ 873bd79bce8SPatrick Williams inline void getOperatingConfigData( 874bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 875bd79bce8SPatrick Williams const std::string& service, const std::string& objPath) 876dba0c291SJonathan Doman { 877*deae6a78SEd Tanous dbus::utility::getAllProperties( 878*deae6a78SEd Tanous service, objPath, 879351053f2SKrzysztof Grobelny "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig", 880ac106bf6SEd Tanous [asyncResp](const boost::system::error_code& ec, 881351053f2SKrzysztof Grobelny const dbus::utility::DBusPropertiesMap& properties) { 882dba0c291SJonathan Doman if (ec) 883dba0c291SJonathan Doman { 88462598e31SEd Tanous BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec, ec.message()); 885ac106bf6SEd Tanous messages::internalError(asyncResp->res); 886dba0c291SJonathan Doman return; 887dba0c291SJonathan Doman } 888dba0c291SJonathan Doman 889351053f2SKrzysztof Grobelny const size_t* availableCoreCount = nullptr; 890351053f2SKrzysztof Grobelny const uint32_t* baseSpeed = nullptr; 891351053f2SKrzysztof Grobelny const uint32_t* maxJunctionTemperature = nullptr; 892351053f2SKrzysztof Grobelny const uint32_t* maxSpeed = nullptr; 893351053f2SKrzysztof Grobelny const uint32_t* powerLimit = nullptr; 894351053f2SKrzysztof Grobelny const TurboProfileProperty* turboProfile = nullptr; 895351053f2SKrzysztof Grobelny const BaseSpeedPrioritySettingsProperty* baseSpeedPrioritySettings = 896351053f2SKrzysztof Grobelny nullptr; 897351053f2SKrzysztof Grobelny 898351053f2SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 899bd79bce8SPatrick Williams dbus_utils::UnpackErrorPrinter(), properties, 900bd79bce8SPatrick Williams "AvailableCoreCount", availableCoreCount, "BaseSpeed", 901bd79bce8SPatrick Williams baseSpeed, "MaxJunctionTemperature", maxJunctionTemperature, 902bd79bce8SPatrick Williams "MaxSpeed", maxSpeed, "PowerLimit", powerLimit, "TurboProfile", 903bd79bce8SPatrick Williams turboProfile, "BaseSpeedPrioritySettings", 904bd79bce8SPatrick Williams baseSpeedPrioritySettings); 905351053f2SKrzysztof Grobelny 906351053f2SKrzysztof Grobelny if (!success) 907dba0c291SJonathan Doman { 908ac106bf6SEd Tanous messages::internalError(asyncResp->res); 909351053f2SKrzysztof Grobelny return; 910dba0c291SJonathan Doman } 911dba0c291SJonathan Doman 912ac106bf6SEd Tanous nlohmann::json& json = asyncResp->res.jsonValue; 913351053f2SKrzysztof Grobelny 914351053f2SKrzysztof Grobelny if (availableCoreCount != nullptr) 915351053f2SKrzysztof Grobelny { 916351053f2SKrzysztof Grobelny json["TotalAvailableCoreCount"] = *availableCoreCount; 917351053f2SKrzysztof Grobelny } 918351053f2SKrzysztof Grobelny 919351053f2SKrzysztof Grobelny if (baseSpeed != nullptr) 920351053f2SKrzysztof Grobelny { 921351053f2SKrzysztof Grobelny json["BaseSpeedMHz"] = *baseSpeed; 922351053f2SKrzysztof Grobelny } 923351053f2SKrzysztof Grobelny 924351053f2SKrzysztof Grobelny if (maxJunctionTemperature != nullptr) 925351053f2SKrzysztof Grobelny { 926351053f2SKrzysztof Grobelny json["MaxJunctionTemperatureCelsius"] = *maxJunctionTemperature; 927351053f2SKrzysztof Grobelny } 928351053f2SKrzysztof Grobelny 929351053f2SKrzysztof Grobelny if (maxSpeed != nullptr) 930351053f2SKrzysztof Grobelny { 931351053f2SKrzysztof Grobelny json["MaxSpeedMHz"] = *maxSpeed; 932351053f2SKrzysztof Grobelny } 933351053f2SKrzysztof Grobelny 934351053f2SKrzysztof Grobelny if (powerLimit != nullptr) 935351053f2SKrzysztof Grobelny { 936351053f2SKrzysztof Grobelny json["TDPWatts"] = *powerLimit; 937351053f2SKrzysztof Grobelny } 938351053f2SKrzysztof Grobelny 939351053f2SKrzysztof Grobelny if (turboProfile != nullptr) 940351053f2SKrzysztof Grobelny { 941dba0c291SJonathan Doman nlohmann::json& turboArray = json["TurboProfile"]; 942dba0c291SJonathan Doman turboArray = nlohmann::json::array(); 943351053f2SKrzysztof Grobelny for (const auto& [turboSpeed, coreCount] : *turboProfile) 944dba0c291SJonathan Doman { 9451476687dSEd Tanous nlohmann::json::object_t turbo; 9461476687dSEd Tanous turbo["ActiveCoreCount"] = coreCount; 9471476687dSEd Tanous turbo["MaxSpeedMHz"] = turboSpeed; 948b2ba3072SPatrick Williams turboArray.emplace_back(std::move(turbo)); 949dba0c291SJonathan Doman } 950dba0c291SJonathan Doman } 951dba0c291SJonathan Doman 952351053f2SKrzysztof Grobelny if (baseSpeedPrioritySettings != nullptr) 953351053f2SKrzysztof Grobelny { 954bd79bce8SPatrick Williams nlohmann::json& baseSpeedArray = 955bd79bce8SPatrick Williams json["BaseSpeedPrioritySettings"]; 956dba0c291SJonathan Doman baseSpeedArray = nlohmann::json::array(); 957351053f2SKrzysztof Grobelny for (const auto& [baseSpeedMhz, coreList] : 958351053f2SKrzysztof Grobelny *baseSpeedPrioritySettings) 959dba0c291SJonathan Doman { 9601476687dSEd Tanous nlohmann::json::object_t speed; 9611476687dSEd Tanous speed["CoreCount"] = coreList.size(); 9621476687dSEd Tanous speed["CoreIDs"] = coreList; 963351053f2SKrzysztof Grobelny speed["BaseSpeedMHz"] = baseSpeedMhz; 964b2ba3072SPatrick Williams baseSpeedArray.emplace_back(std::move(speed)); 965dba0c291SJonathan Doman } 966dba0c291SJonathan Doman } 967351053f2SKrzysztof Grobelny }); 968dba0c291SJonathan Doman } 969dba0c291SJonathan Doman 9703cde86f1SJonathan Doman /** 9713cde86f1SJonathan Doman * Handle the PATCH operation of the AppliedOperatingConfig property. Do basic 9723cde86f1SJonathan Doman * validation of the input data, and then set the D-Bus property. 9733cde86f1SJonathan Doman * 9743cde86f1SJonathan Doman * @param[in,out] resp Async HTTP response. 9753cde86f1SJonathan Doman * @param[in] processorId Processor's Id. 9763cde86f1SJonathan Doman * @param[in] appliedConfigUri New property value to apply. 9773cde86f1SJonathan Doman * @param[in] cpuObjectPath Path of CPU object to modify. 9783cde86f1SJonathan Doman * @param[in] serviceMap Service map for CPU object. 9793cde86f1SJonathan Doman */ 9803cde86f1SJonathan Doman inline void patchAppliedOperatingConfig( 9813cde86f1SJonathan Doman const std::shared_ptr<bmcweb::AsyncResp>& resp, 9823cde86f1SJonathan Doman const std::string& processorId, const std::string& appliedConfigUri, 9835df6eda2SShantappa Teekappanavar const std::string& cpuObjectPath, 9845df6eda2SShantappa Teekappanavar const dbus::utility::MapperServiceMap& serviceMap) 9853cde86f1SJonathan Doman { 9863cde86f1SJonathan Doman // Check that the property even exists by checking for the interface 9873cde86f1SJonathan Doman const std::string* controlService = nullptr; 9883cde86f1SJonathan Doman for (const auto& [serviceName, interfaceList] : serviceMap) 9893cde86f1SJonathan Doman { 9903544d2a7SEd Tanous if (std::ranges::find(interfaceList, 9913cde86f1SJonathan Doman "xyz.openbmc_project.Control.Processor." 9923cde86f1SJonathan Doman "CurrentOperatingConfig") != interfaceList.end()) 9933cde86f1SJonathan Doman { 9943cde86f1SJonathan Doman controlService = &serviceName; 9953cde86f1SJonathan Doman break; 9963cde86f1SJonathan Doman } 9973cde86f1SJonathan Doman } 9983cde86f1SJonathan Doman 9993cde86f1SJonathan Doman if (controlService == nullptr) 10003cde86f1SJonathan Doman { 10013cde86f1SJonathan Doman messages::internalError(resp->res); 10023cde86f1SJonathan Doman return; 10033cde86f1SJonathan Doman } 10043cde86f1SJonathan Doman 10053cde86f1SJonathan Doman // Check that the config URI is a child of the cpu URI being patched. 1006253f11b8SEd Tanous std::string expectedPrefix(std::format("/redfish/v1/Systems/{}/Processors/", 1007253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME)); 10083cde86f1SJonathan Doman expectedPrefix += processorId; 10093cde86f1SJonathan Doman expectedPrefix += "/OperatingConfigs/"; 101011ba3979SEd Tanous if (!appliedConfigUri.starts_with(expectedPrefix) || 10113cde86f1SJonathan Doman expectedPrefix.size() == appliedConfigUri.size()) 10123cde86f1SJonathan Doman { 101387c44966SAsmitha Karunanithi messages::propertyValueIncorrect(resp->res, "AppliedOperatingConfig", 101487c44966SAsmitha Karunanithi appliedConfigUri); 10153cde86f1SJonathan Doman return; 10163cde86f1SJonathan Doman } 10173cde86f1SJonathan Doman 10183cde86f1SJonathan Doman // Generate the D-Bus path of the OperatingConfig object, by assuming it's a 10193cde86f1SJonathan Doman // direct child of the CPU object. 10203cde86f1SJonathan Doman // Strip the expectedPrefix from the config URI to get the "filename", and 10213cde86f1SJonathan Doman // append to the CPU's path. 10223cde86f1SJonathan Doman std::string configBaseName = appliedConfigUri.substr(expectedPrefix.size()); 10233cde86f1SJonathan Doman sdbusplus::message::object_path configPath(cpuObjectPath); 10243cde86f1SJonathan Doman configPath /= configBaseName; 10253cde86f1SJonathan Doman 102662598e31SEd Tanous BMCWEB_LOG_INFO("Setting config to {}", configPath.str); 10273cde86f1SJonathan Doman 10283cde86f1SJonathan Doman // Set the property, with handler to check error responses 102987c44966SAsmitha Karunanithi setDbusProperty( 1030e93abac6SGinu George resp, "AppliedOperatingConfig", *controlService, cpuObjectPath, 10319ae226faSGeorge Liu "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig", 1032e93abac6SGinu George "AppliedConfig", configPath); 10333cde86f1SJonathan Doman } 10343cde86f1SJonathan Doman 1035bd79bce8SPatrick Williams inline void handleProcessorHead( 1036bd79bce8SPatrick Williams crow::App& app, const crow::Request& req, 1037ac106bf6SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1038bd79bce8SPatrick Williams const std::string& /* systemName */, const std::string& /* processorId */) 103971a24ca4SNikhil Namjoshi { 1040ac106bf6SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 104171a24ca4SNikhil Namjoshi { 104271a24ca4SNikhil Namjoshi return; 104371a24ca4SNikhil Namjoshi } 1044ac106bf6SEd Tanous asyncResp->res.addHeader( 104571a24ca4SNikhil Namjoshi boost::beast::http::field::link, 104671a24ca4SNikhil Namjoshi "</redfish/v1/JsonSchemas/Processor/Processor.json>; rel=describedby"); 104771a24ca4SNikhil Namjoshi } 104871a24ca4SNikhil Namjoshi 104971a24ca4SNikhil Namjoshi inline void handleProcessorCollectionHead( 105071a24ca4SNikhil Namjoshi crow::App& app, const crow::Request& req, 1051ac106bf6SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 105271a24ca4SNikhil Namjoshi const std::string& /* systemName */) 105371a24ca4SNikhil Namjoshi { 1054ac106bf6SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 105571a24ca4SNikhil Namjoshi { 105671a24ca4SNikhil Namjoshi return; 105771a24ca4SNikhil Namjoshi } 1058ac106bf6SEd Tanous asyncResp->res.addHeader( 105971a24ca4SNikhil Namjoshi boost::beast::http::field::link, 106071a24ca4SNikhil Namjoshi "</redfish/v1/JsonSchemas/ProcessorCollection/ProcessorCollection.json>; rel=describedby"); 106171a24ca4SNikhil Namjoshi } 106271a24ca4SNikhil Namjoshi 10637e860f15SJohn Edward Broadbent inline void requestRoutesOperatingConfigCollection(App& app) 1064dba0c291SJonathan Doman { 10657f3e84a1SEd Tanous BMCWEB_ROUTE(app, 10667f3e84a1SEd Tanous "/redfish/v1/Systems/<str>/Processors/<str>/OperatingConfigs/") 1067ed398213SEd Tanous .privileges(redfish::privileges::getOperatingConfigCollection) 1068bd79bce8SPatrick Williams .methods( 1069bd79bce8SPatrick Williams boost::beast::http::verb:: 1070bd79bce8SPatrick Williams get)([&app](const crow::Request& req, 107145ca1b86SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1072bd79bce8SPatrick Williams const std::string& systemName, 1073bd79bce8SPatrick Williams const std::string& cpuName) { 10743ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 107545ca1b86SEd Tanous { 107645ca1b86SEd Tanous return; 107745ca1b86SEd Tanous } 10787f3e84a1SEd Tanous 107925b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 10807f3e84a1SEd Tanous { 10817f3e84a1SEd Tanous // Option currently returns no systems. TBD 10827f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 10837f3e84a1SEd Tanous systemName); 10847f3e84a1SEd Tanous return; 10857f3e84a1SEd Tanous } 10867f3e84a1SEd Tanous 1087253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 10887f3e84a1SEd Tanous { 10897f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 10907f3e84a1SEd Tanous systemName); 10917f3e84a1SEd Tanous return; 10927f3e84a1SEd Tanous } 10938d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.type"] = 1094dba0c291SJonathan Doman "#OperatingConfigCollection.OperatingConfigCollection"; 1095ef4c65b7SEd Tanous asyncResp->res.jsonValue["@odata.id"] = boost::urls::format( 1096253f11b8SEd Tanous "/redfish/v1/Systems/{}/Processors/{}/OperatingConfigs", 1097253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME, cpuName); 10980fda0f12SGeorge Liu asyncResp->res.jsonValue["Name"] = "Operating Config Collection"; 1099dba0c291SJonathan Doman 11007e860f15SJohn Edward Broadbent // First find the matching CPU object so we know how to 11017e860f15SJohn Edward Broadbent // constrain our search for related Config objects. 11027a1dbc48SGeorge Liu const std::array<std::string_view, 1> interfaces = { 11037a1dbc48SGeorge Liu "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig"}; 11047a1dbc48SGeorge Liu dbus::utility::getSubTreePaths( 11057a1dbc48SGeorge Liu "/xyz/openbmc_project/inventory", 0, interfaces, 1106bd79bce8SPatrick Williams [asyncResp, 1107bd79bce8SPatrick Williams cpuName](const boost::system::error_code& ec, 1108bd79bce8SPatrick Williams const dbus::utility::MapperGetSubTreePathsResponse& 1109bd79bce8SPatrick Williams objects) { 1110dba0c291SJonathan Doman if (ec) 1111dba0c291SJonathan Doman { 1112bd79bce8SPatrick Williams BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec, 1113bd79bce8SPatrick Williams ec.message()); 1114dba0c291SJonathan Doman messages::internalError(asyncResp->res); 1115dba0c291SJonathan Doman return; 1116dba0c291SJonathan Doman } 1117dba0c291SJonathan Doman 1118dba0c291SJonathan Doman for (const std::string& object : objects) 1119dba0c291SJonathan Doman { 112011ba3979SEd Tanous if (!object.ends_with(cpuName)) 1121dba0c291SJonathan Doman { 1122dba0c291SJonathan Doman continue; 1123dba0c291SJonathan Doman } 1124dba0c291SJonathan Doman 11257e860f15SJohn Edward Broadbent // Not expected that there will be multiple matching 11267e860f15SJohn Edward Broadbent // CPU objects, but if there are just use the first 11277e860f15SJohn Edward Broadbent // one. 1128dba0c291SJonathan Doman 11297e860f15SJohn Edward Broadbent // Use the common search routine to construct the 11307e860f15SJohn Edward Broadbent // Collection of all Config objects under this CPU. 11317a1dbc48SGeorge Liu constexpr std::array<std::string_view, 1> interface{ 11325a39f77aSPatrick Williams "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig"}; 1133dba0c291SJonathan Doman collection_util::getCollectionMembers( 1134dba0c291SJonathan Doman asyncResp, 1135ef4c65b7SEd Tanous boost::urls::format( 1136253f11b8SEd Tanous "/redfish/v1/Systems/{}/Processors/{}/OperatingConfigs", 1137253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME, cpuName), 113836b5f1edSLakshmi Yadlapati interface, object); 1139dba0c291SJonathan Doman return; 1140dba0c291SJonathan Doman } 11417a1dbc48SGeorge Liu }); 11427e860f15SJohn Edward Broadbent }); 1143dba0c291SJonathan Doman } 1144dba0c291SJonathan Doman 11457e860f15SJohn Edward Broadbent inline void requestRoutesOperatingConfig(App& app) 1146dba0c291SJonathan Doman { 11477e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 11487e860f15SJohn Edward Broadbent app, 11497f3e84a1SEd Tanous "/redfish/v1/Systems/<str>/Processors/<str>/OperatingConfigs/<str>/") 1150ed398213SEd Tanous .privileges(redfish::privileges::getOperatingConfig) 1151bd79bce8SPatrick Williams .methods( 1152bd79bce8SPatrick Williams boost::beast::http::verb:: 1153bd79bce8SPatrick Williams get)([&app](const crow::Request& req, 115445ca1b86SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1155bd79bce8SPatrick Williams const std::string& systemName, 1156bd79bce8SPatrick Williams const std::string& cpuName, 11577f3e84a1SEd Tanous const std::string& configName) { 11583ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 115945ca1b86SEd Tanous { 116045ca1b86SEd Tanous return; 116145ca1b86SEd Tanous } 116225b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 11637f3e84a1SEd Tanous { 11647f3e84a1SEd Tanous // Option currently returns no systems. TBD 11657f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 11667f3e84a1SEd Tanous systemName); 11677f3e84a1SEd Tanous return; 11687f3e84a1SEd Tanous } 11697f3e84a1SEd Tanous 1170253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 11717f3e84a1SEd Tanous { 11727f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 11737f3e84a1SEd Tanous systemName); 11747f3e84a1SEd Tanous return; 11757f3e84a1SEd Tanous } 11767e860f15SJohn Edward Broadbent // Ask for all objects implementing OperatingConfig so we can search 11777e860f15SJohn Edward Broadbent // for one with a matching name 1178e99073f5SGeorge Liu constexpr std::array<std::string_view, 1> interfaces = { 1179e99073f5SGeorge Liu "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig"}; 1180e99073f5SGeorge Liu dbus::utility::getSubTree( 1181e99073f5SGeorge Liu "/xyz/openbmc_project/inventory", 0, interfaces, 118239662a3bSEd Tanous [asyncResp, cpuName, configName]( 1183e99073f5SGeorge Liu const boost::system::error_code& ec, 11845df6eda2SShantappa Teekappanavar const dbus::utility::MapperGetSubTreeResponse& subtree) { 1185dba0c291SJonathan Doman if (ec) 1186dba0c291SJonathan Doman { 1187bd79bce8SPatrick Williams BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec, 1188bd79bce8SPatrick Williams ec.message()); 1189dba0c291SJonathan Doman messages::internalError(asyncResp->res); 1190dba0c291SJonathan Doman return; 1191dba0c291SJonathan Doman } 1192bd79bce8SPatrick Williams const std::string expectedEnding = 1193bd79bce8SPatrick Williams cpuName + '/' + configName; 1194dba0c291SJonathan Doman for (const auto& [objectPath, serviceMap] : subtree) 1195dba0c291SJonathan Doman { 1196dba0c291SJonathan Doman // Ignore any configs without matching cpuX/configY 1197bd79bce8SPatrick Williams if (!objectPath.ends_with(expectedEnding) || 1198bd79bce8SPatrick Williams serviceMap.empty()) 1199dba0c291SJonathan Doman { 1200dba0c291SJonathan Doman continue; 1201dba0c291SJonathan Doman } 1202dba0c291SJonathan Doman 1203dba0c291SJonathan Doman nlohmann::json& json = asyncResp->res.jsonValue; 1204bd79bce8SPatrick Williams json["@odata.type"] = 1205bd79bce8SPatrick Williams "#OperatingConfig.v1_0_0.OperatingConfig"; 1206ef4c65b7SEd Tanous json["@odata.id"] = boost::urls::format( 1207253f11b8SEd Tanous "/redfish/v1/Systems/{}/Processors/{}/OperatingConfigs/{}", 1208bd79bce8SPatrick Williams BMCWEB_REDFISH_SYSTEM_URI_NAME, cpuName, 1209bd79bce8SPatrick Williams configName); 1210dba0c291SJonathan Doman json["Name"] = "Processor Profile"; 1211dba0c291SJonathan Doman json["Id"] = configName; 1212dba0c291SJonathan Doman 1213dba0c291SJonathan Doman // Just use the first implementation of the object - not 12147e860f15SJohn Edward Broadbent // expected that there would be multiple matching 12157e860f15SJohn Edward Broadbent // services 1216bd79bce8SPatrick Williams getOperatingConfigData( 1217bd79bce8SPatrick Williams asyncResp, serviceMap.begin()->first, objectPath); 1218dba0c291SJonathan Doman return; 1219dba0c291SJonathan Doman } 1220bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, 1221bd79bce8SPatrick Williams "OperatingConfig", configName); 1222e99073f5SGeorge Liu }); 12237e860f15SJohn Edward Broadbent }); 1224ac6a4445SGunnar Mills } 1225ac6a4445SGunnar Mills 12267e860f15SJohn Edward Broadbent inline void requestRoutesProcessorCollection(App& app) 12277e860f15SJohn Edward Broadbent { 1228ac6a4445SGunnar Mills /** 1229ac6a4445SGunnar Mills * Functions triggers appropriate requests on DBus 1230ac6a4445SGunnar Mills */ 123122d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/") 123271a24ca4SNikhil Namjoshi .privileges(redfish::privileges::headProcessorCollection) 123371a24ca4SNikhil Namjoshi .methods(boost::beast::http::verb::head)( 123471a24ca4SNikhil Namjoshi std::bind_front(handleProcessorCollectionHead, std::ref(app))); 123571a24ca4SNikhil Namjoshi 123671a24ca4SNikhil Namjoshi BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/") 1237ed398213SEd Tanous .privileges(redfish::privileges::getProcessorCollection) 1238bd79bce8SPatrick Williams .methods( 1239bd79bce8SPatrick Williams boost::beast::http::verb:: 1240bd79bce8SPatrick Williams get)([&app](const crow::Request& req, 124122d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 124222d268cbSEd Tanous const std::string& systemName) { 12433ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 124445ca1b86SEd Tanous { 124545ca1b86SEd Tanous return; 124645ca1b86SEd Tanous } 124725b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 12487f3e84a1SEd Tanous { 12497f3e84a1SEd Tanous // Option currently returns no systems. TBD 12507f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 12517f3e84a1SEd Tanous systemName); 12527f3e84a1SEd Tanous return; 12537f3e84a1SEd Tanous } 12547f3e84a1SEd Tanous 1255253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 125622d268cbSEd Tanous { 125722d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 125822d268cbSEd Tanous systemName); 125922d268cbSEd Tanous return; 126022d268cbSEd Tanous } 126122d268cbSEd Tanous 126271a24ca4SNikhil Namjoshi asyncResp->res.addHeader( 126371a24ca4SNikhil Namjoshi boost::beast::http::field::link, 126471a24ca4SNikhil Namjoshi "</redfish/v1/JsonSchemas/ProcessorCollection/ProcessorCollection.json>; rel=describedby"); 126571a24ca4SNikhil Namjoshi 12668d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.type"] = 1267ac6a4445SGunnar Mills "#ProcessorCollection.ProcessorCollection"; 12688d1b46d7Szhanghch05 asyncResp->res.jsonValue["Name"] = "Processor Collection"; 1269ac6a4445SGunnar Mills 12708d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.id"] = 1271253f11b8SEd Tanous std::format("/redfish/v1/Systems/{}/Processors", 1272253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 1273ac6a4445SGunnar Mills 127405030b8eSGunnar Mills collection_util::getCollectionMembers( 1275ae9031f0SWilly Tu asyncResp, 1276253f11b8SEd Tanous boost::urls::format("/redfish/v1/Systems/{}/Processors", 1277253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME), 127836b5f1edSLakshmi Yadlapati processorInterfaces, "/xyz/openbmc_project/inventory"); 12797e860f15SJohn Edward Broadbent }); 1280ac6a4445SGunnar Mills } 1281ac6a4445SGunnar Mills 12827e860f15SJohn Edward Broadbent inline void requestRoutesProcessor(App& app) 12837e860f15SJohn Edward Broadbent { 1284ac6a4445SGunnar Mills /** 1285ac6a4445SGunnar Mills * Functions triggers appropriate requests on DBus 1286ac6a4445SGunnar Mills */ 12877e860f15SJohn Edward Broadbent 128822d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/<str>/") 128971a24ca4SNikhil Namjoshi .privileges(redfish::privileges::headProcessor) 129071a24ca4SNikhil Namjoshi .methods(boost::beast::http::verb::head)( 129171a24ca4SNikhil Namjoshi std::bind_front(handleProcessorHead, std::ref(app))); 129271a24ca4SNikhil Namjoshi 129371a24ca4SNikhil Namjoshi BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/<str>/") 1294ed398213SEd Tanous .privileges(redfish::privileges::getProcessor) 1295bd79bce8SPatrick Williams .methods( 1296bd79bce8SPatrick Williams boost::beast::http::verb:: 1297bd79bce8SPatrick Williams get)([&app](const crow::Request& req, 12987e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 129922d268cbSEd Tanous const std::string& systemName, 13007e860f15SJohn Edward Broadbent const std::string& processorId) { 13013ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 130245ca1b86SEd Tanous { 130345ca1b86SEd Tanous return; 130445ca1b86SEd Tanous } 130525b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 13067f3e84a1SEd Tanous { 13077f3e84a1SEd Tanous // Option currently returns no systems. TBD 13087f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 13097f3e84a1SEd Tanous systemName); 13107f3e84a1SEd Tanous return; 13117f3e84a1SEd Tanous } 1312253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 131322d268cbSEd Tanous { 131422d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 131522d268cbSEd Tanous systemName); 131622d268cbSEd Tanous return; 131722d268cbSEd Tanous } 131822d268cbSEd Tanous 131971a24ca4SNikhil Namjoshi asyncResp->res.addHeader( 132071a24ca4SNikhil Namjoshi boost::beast::http::field::link, 132171a24ca4SNikhil Namjoshi "</redfish/v1/JsonSchemas/Processor/Processor.json>; rel=describedby"); 13228d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.type"] = 1323dfbf7de5SChris Cain "#Processor.v1_18_0.Processor"; 1324bd79bce8SPatrick Williams asyncResp->res.jsonValue["@odata.id"] = boost::urls::format( 1325bd79bce8SPatrick Williams "/redfish/v1/Systems/{}/Processors/{}", 1326253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME, processorId); 1327ac6a4445SGunnar Mills 13288a592810SEd Tanous getProcessorObject( 13298a592810SEd Tanous asyncResp, processorId, 13308a592810SEd Tanous std::bind_front(getProcessorData, asyncResp, processorId)); 13317e860f15SJohn Edward Broadbent }); 13323cde86f1SJonathan Doman 133322d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/<str>/") 1334ed398213SEd Tanous .privileges(redfish::privileges::patchProcessor) 13357e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::patch)( 133645ca1b86SEd Tanous [&app](const crow::Request& req, 13377e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 133822d268cbSEd Tanous const std::string& systemName, 13397e860f15SJohn Edward Broadbent const std::string& processorId) { 13403ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 134145ca1b86SEd Tanous { 134245ca1b86SEd Tanous return; 134345ca1b86SEd Tanous } 134425b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 13457f3e84a1SEd Tanous { 13467f3e84a1SEd Tanous // Option currently returns no systems. TBD 13477f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 13487f3e84a1SEd Tanous systemName); 13497f3e84a1SEd Tanous return; 13507f3e84a1SEd Tanous } 1351253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 135222d268cbSEd Tanous { 135322d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 135422d268cbSEd Tanous systemName); 135522d268cbSEd Tanous return; 135622d268cbSEd Tanous } 135722d268cbSEd Tanous 13583c569218SEd Tanous std::optional<std::string> appliedConfigUri; 1359bd79bce8SPatrick Williams if (!json_util::readJsonPatch( 1360afc474aeSMyung Bae req, asyncResp->res, // 1361afc474aeSMyung Bae "AppliedOperatingConfig/@odata.id", appliedConfigUri // 1362afc474aeSMyung Bae )) 13633cde86f1SJonathan Doman { 13643cde86f1SJonathan Doman return; 13653cde86f1SJonathan Doman } 13663cde86f1SJonathan Doman 13673c569218SEd Tanous if (appliedConfigUri) 13683cde86f1SJonathan Doman { 13697e860f15SJohn Edward Broadbent // Check for 404 and find matching D-Bus object, then run 13707e860f15SJohn Edward Broadbent // property patch handlers if that all succeeds. 1371bd79bce8SPatrick Williams getProcessorObject( 13727e860f15SJohn Edward Broadbent asyncResp, processorId, 1373bd79bce8SPatrick Williams std::bind_front(patchAppliedOperatingConfig, asyncResp, 1374bd79bce8SPatrick Williams processorId, *appliedConfigUri)); 13753cde86f1SJonathan Doman } 13767e860f15SJohn Edward Broadbent }); 13773cde86f1SJonathan Doman } 1378ac6a4445SGunnar Mills 1379ac6a4445SGunnar Mills } // namespace redfish 1380