140e9b92eSEd Tanous // SPDX-License-Identifier: Apache-2.0 240e9b92eSEd Tanous // SPDX-FileCopyrightText: Copyright OpenBMC Authors 340e9b92eSEd Tanous // SPDX-FileCopyrightText: Copyright 2018 Intel Corporation 4ac6a4445SGunnar Mills #pragma once 5ac6a4445SGunnar Mills 6d7857201SEd Tanous #include "bmcweb_config.h" 7d7857201SEd Tanous 83ccb3adbSEd Tanous #include "app.hpp" 9d7857201SEd Tanous #include "async_resp.hpp" 10*98eafce5SGeorge Liu #include "dbus_singleton.hpp" 117a1dbc48SGeorge Liu #include "dbus_utility.hpp" 121e1e598dSJonathan Doman #include "error_messages.hpp" 13dfbf7de5SChris Cain #include "generated/enums/processor.hpp" 14539d8c6bSEd Tanous #include "generated/enums/resource.hpp" 15d7857201SEd Tanous #include "http_request.hpp" 16*98eafce5SGeorge Liu #include "led.hpp" 17d7857201SEd Tanous #include "logging.hpp" 183ccb3adbSEd Tanous #include "query.hpp" 193ccb3adbSEd Tanous #include "registries/privilege_registry.hpp" 203ccb3adbSEd Tanous #include "utils/collection.hpp" 213ccb3adbSEd Tanous #include "utils/dbus_utils.hpp" 22d7857201SEd Tanous #include "utils/hex_utils.hpp" 233ccb3adbSEd Tanous #include "utils/json_utils.hpp" 24ac6a4445SGunnar Mills 25d7857201SEd Tanous #include <boost/beast/http/field.hpp> 26d7857201SEd Tanous #include <boost/beast/http/verb.hpp> 27e99073f5SGeorge Liu #include <boost/system/error_code.hpp> 28ef4c65b7SEd Tanous #include <boost/url/format.hpp> 29dba0c291SJonathan Doman #include <sdbusplus/message/native_types.hpp> 30351053f2SKrzysztof Grobelny #include <sdbusplus/unpack_properties.hpp> 31ac6a4445SGunnar Mills 32d7857201SEd Tanous #include <algorithm> 337a1dbc48SGeorge Liu #include <array> 34d7857201SEd Tanous #include <cstddef> 35d7857201SEd Tanous #include <cstdint> 36d7857201SEd Tanous #include <format> 37d7857201SEd Tanous #include <functional> 38b9d679d1SMichael Shen #include <limits> 39d7857201SEd Tanous #include <memory> 40d7857201SEd Tanous #include <optional> 413544d2a7SEd Tanous #include <ranges> 423c569218SEd Tanous #include <string> 437a1dbc48SGeorge Liu #include <string_view> 44d7857201SEd Tanous #include <tuple> 45d7857201SEd Tanous #include <utility> 46d7857201SEd Tanous #include <variant> 47d7857201SEd Tanous #include <vector> 487a1dbc48SGeorge Liu 49ac6a4445SGunnar Mills namespace redfish 50ac6a4445SGunnar Mills { 51ac6a4445SGunnar Mills 52c951448aSJonathan Doman // Interfaces which imply a D-Bus object represents a Processor 537a1dbc48SGeorge Liu constexpr std::array<std::string_view, 2> processorInterfaces = { 54c951448aSJonathan Doman "xyz.openbmc_project.Inventory.Item.Cpu", 55c951448aSJonathan Doman "xyz.openbmc_project.Inventory.Item.Accelerator"}; 562bab9831SJonathan Doman 5771b82f26SSharad Yadav /** 5871b82f26SSharad Yadav * @brief Fill out uuid info of a processor by 5971b82f26SSharad Yadav * requesting data from the given D-Bus object. 6071b82f26SSharad Yadav * 61ac106bf6SEd Tanous * @param[in,out] asyncResp Async HTTP response. 6271b82f26SSharad Yadav * @param[in] service D-Bus service to query. 6371b82f26SSharad Yadav * @param[in] objPath D-Bus object to query. 6471b82f26SSharad Yadav */ 65ac106bf6SEd Tanous inline void getProcessorUUID(std::shared_ptr<bmcweb::AsyncResp> asyncResp, 6671b82f26SSharad Yadav const std::string& service, 6771b82f26SSharad Yadav const std::string& objPath) 6871b82f26SSharad Yadav { 6962598e31SEd Tanous BMCWEB_LOG_DEBUG("Get Processor UUID"); 70deae6a78SEd Tanous dbus::utility::getProperty<std::string>( 71deae6a78SEd Tanous service, objPath, "xyz.openbmc_project.Common.UUID", "UUID", 72ac106bf6SEd Tanous [objPath, asyncResp{std::move(asyncResp)}]( 73ac106bf6SEd Tanous const boost::system::error_code& ec, const std::string& property) { 7471b82f26SSharad Yadav if (ec) 7571b82f26SSharad Yadav { 7662598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error"); 77ac106bf6SEd Tanous messages::internalError(asyncResp->res); 7871b82f26SSharad Yadav return; 7971b82f26SSharad Yadav } 80ac106bf6SEd Tanous asyncResp->res.jsonValue["UUID"] = property; 811e1e598dSJonathan Doman }); 8271b82f26SSharad Yadav } 8371b82f26SSharad Yadav 84711ac7a9SEd Tanous inline void getCpuDataByInterface( 85ac106bf6SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 8680f79a40SMichael Shen const dbus::utility::DBusInterfacesMap& cpuInterfacesProperties) 87ac6a4445SGunnar Mills { 8862598e31SEd Tanous BMCWEB_LOG_DEBUG("Get CPU resources by interface."); 89ac6a4445SGunnar Mills 90a1649ec6SChicago Duan // Set the default value of state 91539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled; 92539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["Health"] = resource::Health::OK; 93ac6a4445SGunnar Mills 94ac6a4445SGunnar Mills for (const auto& interface : cpuInterfacesProperties) 95ac6a4445SGunnar Mills { 96ac6a4445SGunnar Mills for (const auto& property : interface.second) 97ac6a4445SGunnar Mills { 98a1649ec6SChicago Duan if (property.first == "Present") 99ac6a4445SGunnar Mills { 100a1649ec6SChicago Duan const bool* cpuPresent = std::get_if<bool>(&property.second); 101a1649ec6SChicago Duan if (cpuPresent == nullptr) 102ac6a4445SGunnar Mills { 103ac6a4445SGunnar Mills // Important property not in desired type 104ac106bf6SEd Tanous messages::internalError(asyncResp->res); 105ac6a4445SGunnar Mills return; 106ac6a4445SGunnar Mills } 107e05aec50SEd Tanous if (!*cpuPresent) 108ac6a4445SGunnar Mills { 109a1649ec6SChicago Duan // Slot is not populated 110539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["State"] = 111539d8c6bSEd Tanous resource::State::Absent; 112a1649ec6SChicago Duan } 113a1649ec6SChicago Duan } 114a1649ec6SChicago Duan else if (property.first == "Functional") 115a1649ec6SChicago Duan { 116a1649ec6SChicago Duan const bool* cpuFunctional = std::get_if<bool>(&property.second); 117a1649ec6SChicago Duan if (cpuFunctional == nullptr) 118a1649ec6SChicago Duan { 119ac106bf6SEd Tanous messages::internalError(asyncResp->res); 120ac6a4445SGunnar Mills return; 121ac6a4445SGunnar Mills } 122e05aec50SEd Tanous if (!*cpuFunctional) 123a1649ec6SChicago Duan { 124539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["Health"] = 125539d8c6bSEd Tanous resource::Health::Critical; 126a1649ec6SChicago Duan } 127a1649ec6SChicago Duan } 128a1649ec6SChicago Duan else if (property.first == "CoreCount") 129a1649ec6SChicago Duan { 130a1649ec6SChicago Duan const uint16_t* coresCount = 131a1649ec6SChicago Duan std::get_if<uint16_t>(&property.second); 132a1649ec6SChicago Duan if (coresCount == nullptr) 133a1649ec6SChicago Duan { 134ac106bf6SEd Tanous messages::internalError(asyncResp->res); 135a1649ec6SChicago Duan return; 136a1649ec6SChicago Duan } 137ac106bf6SEd Tanous asyncResp->res.jsonValue["TotalCores"] = *coresCount; 138ac6a4445SGunnar Mills } 139dc3fa667SJonathan Doman else if (property.first == "MaxSpeedInMhz") 140dc3fa667SJonathan Doman { 141dc3fa667SJonathan Doman const uint32_t* value = std::get_if<uint32_t>(&property.second); 142dc3fa667SJonathan Doman if (value != nullptr) 143dc3fa667SJonathan Doman { 144ac106bf6SEd Tanous asyncResp->res.jsonValue["MaxSpeedMHz"] = *value; 145dc3fa667SJonathan Doman } 146dc3fa667SJonathan Doman } 147ac6a4445SGunnar Mills else if (property.first == "Socket") 148ac6a4445SGunnar Mills { 149ac6a4445SGunnar Mills const std::string* value = 150ac6a4445SGunnar Mills std::get_if<std::string>(&property.second); 151ac6a4445SGunnar Mills if (value != nullptr) 152ac6a4445SGunnar Mills { 153ac106bf6SEd Tanous asyncResp->res.jsonValue["Socket"] = *value; 154ac6a4445SGunnar Mills } 155ac6a4445SGunnar Mills } 156ac6a4445SGunnar Mills else if (property.first == "ThreadCount") 157ac6a4445SGunnar Mills { 158dc3fa667SJonathan Doman const uint16_t* value = std::get_if<uint16_t>(&property.second); 159ac6a4445SGunnar Mills if (value != nullptr) 160ac6a4445SGunnar Mills { 161ac106bf6SEd Tanous asyncResp->res.jsonValue["TotalThreads"] = *value; 162ac6a4445SGunnar Mills } 163ac6a4445SGunnar Mills } 1641930fbd4SBrandon Kim else if (property.first == "EffectiveFamily") 165ac6a4445SGunnar Mills { 1661930fbd4SBrandon Kim const uint16_t* value = std::get_if<uint16_t>(&property.second); 1676169de2cSBrad Bishop if (value != nullptr && *value != 2) 168ac6a4445SGunnar Mills { 169ac106bf6SEd Tanous asyncResp->res.jsonValue["ProcessorId"]["EffectiveFamily"] = 170866e4862SEd Tanous "0x" + intToHexString(*value, 4); 171ac6a4445SGunnar Mills } 172ac6a4445SGunnar Mills } 1731930fbd4SBrandon Kim else if (property.first == "EffectiveModel") 1741930fbd4SBrandon Kim { 1751930fbd4SBrandon Kim const uint16_t* value = std::get_if<uint16_t>(&property.second); 1761930fbd4SBrandon Kim if (value == nullptr) 1771930fbd4SBrandon Kim { 178ac106bf6SEd Tanous messages::internalError(asyncResp->res); 1791930fbd4SBrandon Kim return; 1801930fbd4SBrandon Kim } 1816169de2cSBrad Bishop if (*value != 0) 1826169de2cSBrad Bishop { 183ac106bf6SEd Tanous asyncResp->res.jsonValue["ProcessorId"]["EffectiveModel"] = 184866e4862SEd Tanous "0x" + intToHexString(*value, 4); 1851930fbd4SBrandon Kim } 1866169de2cSBrad Bishop } 187ac6a4445SGunnar Mills else if (property.first == "Id") 188ac6a4445SGunnar Mills { 189ac6a4445SGunnar Mills const uint64_t* value = std::get_if<uint64_t>(&property.second); 190ac6a4445SGunnar Mills if (value != nullptr && *value != 0) 191ac6a4445SGunnar Mills { 192ac106bf6SEd Tanous asyncResp->res 193ac6a4445SGunnar Mills .jsonValue["ProcessorId"]["IdentificationRegisters"] = 194866e4862SEd Tanous "0x" + intToHexString(*value, 16); 195ac6a4445SGunnar Mills } 196ac6a4445SGunnar Mills } 1971930fbd4SBrandon Kim else if (property.first == "Microcode") 1981930fbd4SBrandon Kim { 1991930fbd4SBrandon Kim const uint32_t* value = std::get_if<uint32_t>(&property.second); 2001930fbd4SBrandon Kim if (value == nullptr) 2011930fbd4SBrandon Kim { 202ac106bf6SEd Tanous messages::internalError(asyncResp->res); 2031930fbd4SBrandon Kim return; 2041930fbd4SBrandon Kim } 2056169de2cSBrad Bishop if (*value != 0) 2066169de2cSBrad Bishop { 207ac106bf6SEd Tanous asyncResp->res.jsonValue["ProcessorId"]["MicrocodeInfo"] = 208866e4862SEd Tanous "0x" + intToHexString(*value, 8); 2091930fbd4SBrandon Kim } 2106169de2cSBrad Bishop } 2111930fbd4SBrandon Kim else if (property.first == "Step") 2121930fbd4SBrandon Kim { 2131930fbd4SBrandon Kim const uint16_t* value = std::get_if<uint16_t>(&property.second); 2141930fbd4SBrandon Kim if (value == nullptr) 2151930fbd4SBrandon Kim { 216ac106bf6SEd Tanous messages::internalError(asyncResp->res); 2171930fbd4SBrandon Kim return; 2181930fbd4SBrandon Kim } 219b9d679d1SMichael Shen if (*value != std::numeric_limits<uint16_t>::max()) 2206169de2cSBrad Bishop { 221ac106bf6SEd Tanous asyncResp->res.jsonValue["ProcessorId"]["Step"] = 222866e4862SEd Tanous "0x" + intToHexString(*value, 4); 2231930fbd4SBrandon Kim } 224ac6a4445SGunnar Mills } 225ac6a4445SGunnar Mills } 226ac6a4445SGunnar Mills } 2276169de2cSBrad Bishop } 228ac6a4445SGunnar Mills 229bd79bce8SPatrick Williams inline void getCpuDataByService( 230bd79bce8SPatrick Williams std::shared_ptr<bmcweb::AsyncResp> asyncResp, const std::string& cpuId, 231bd79bce8SPatrick Williams const std::string& service, const std::string& objPath) 232ac6a4445SGunnar Mills { 23362598e31SEd Tanous BMCWEB_LOG_DEBUG("Get available system cpu resources by service."); 234ac6a4445SGunnar Mills 2355eb468daSGeorge Liu sdbusplus::message::object_path path("/xyz/openbmc_project/inventory"); 2365eb468daSGeorge Liu dbus::utility::getManagedObjects( 2375eb468daSGeorge Liu service, path, 238ac106bf6SEd Tanous [cpuId, service, objPath, asyncResp{std::move(asyncResp)}]( 2395e7e2dc5SEd Tanous const boost::system::error_code& ec, 240ac6a4445SGunnar Mills const dbus::utility::ManagedObjectType& dbusData) { 241ac6a4445SGunnar Mills if (ec) 242ac6a4445SGunnar Mills { 24362598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error"); 244ac106bf6SEd Tanous messages::internalError(asyncResp->res); 245ac6a4445SGunnar Mills return; 246ac6a4445SGunnar Mills } 247ac106bf6SEd Tanous asyncResp->res.jsonValue["Id"] = cpuId; 248ac106bf6SEd Tanous asyncResp->res.jsonValue["Name"] = "Processor"; 249539d8c6bSEd Tanous asyncResp->res.jsonValue["ProcessorType"] = 250539d8c6bSEd Tanous processor::ProcessorType::CPU; 251ac6a4445SGunnar Mills 252ac6a4445SGunnar Mills for (const auto& object : dbusData) 253ac6a4445SGunnar Mills { 254ac6a4445SGunnar Mills if (object.first.str == objPath) 255ac6a4445SGunnar Mills { 256ac106bf6SEd Tanous getCpuDataByInterface(asyncResp, object.second); 257ac6a4445SGunnar Mills } 258ac6a4445SGunnar Mills } 259ac6a4445SGunnar Mills return; 2605eb468daSGeorge Liu }); 261ac6a4445SGunnar Mills } 262ac6a4445SGunnar Mills 263dfbf7de5SChris Cain /** 264dfbf7de5SChris Cain * @brief Translates throttle cause DBUS property to redfish. 265dfbf7de5SChris Cain * 266dfbf7de5SChris Cain * @param[in] dbusSource The throttle cause from DBUS 267dfbf7de5SChris Cain * 268dfbf7de5SChris Cain * @return Returns as a string, the throttle cause in Redfish terms. If 269dfbf7de5SChris Cain * translation cannot be done, returns "Unknown" throttle reason. 270dfbf7de5SChris Cain */ 271504af5a0SPatrick Williams inline processor::ThrottleCause dbusToRfThrottleCause( 272504af5a0SPatrick Williams const std::string& dbusSource) 273dfbf7de5SChris Cain { 274dfbf7de5SChris Cain if (dbusSource == 275dfbf7de5SChris Cain "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.ClockLimit") 276dfbf7de5SChris Cain { 277dfbf7de5SChris Cain return processor::ThrottleCause::ClockLimit; 278dfbf7de5SChris Cain } 279dfbf7de5SChris Cain if (dbusSource == 280dfbf7de5SChris Cain "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.ManagementDetectedFault") 281dfbf7de5SChris Cain { 282dfbf7de5SChris Cain return processor::ThrottleCause::ManagementDetectedFault; 283dfbf7de5SChris Cain } 284dfbf7de5SChris Cain if (dbusSource == 285dfbf7de5SChris Cain "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.PowerLimit") 286dfbf7de5SChris Cain { 287dfbf7de5SChris Cain return processor::ThrottleCause::PowerLimit; 288dfbf7de5SChris Cain } 289dfbf7de5SChris Cain if (dbusSource == 290dfbf7de5SChris Cain "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.ThermalLimit") 291dfbf7de5SChris Cain { 292dfbf7de5SChris Cain return processor::ThrottleCause::ThermalLimit; 293dfbf7de5SChris Cain } 294dfbf7de5SChris Cain if (dbusSource == 295dfbf7de5SChris Cain "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.Unknown") 296dfbf7de5SChris Cain { 297dfbf7de5SChris Cain return processor::ThrottleCause::Unknown; 298dfbf7de5SChris Cain } 299dfbf7de5SChris Cain return processor::ThrottleCause::Invalid; 300dfbf7de5SChris Cain } 301dfbf7de5SChris Cain 302504af5a0SPatrick Williams inline void readThrottleProperties( 303504af5a0SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 304dfbf7de5SChris Cain const boost::system::error_code& ec, 305dfbf7de5SChris Cain const dbus::utility::DBusPropertiesMap& properties) 306dfbf7de5SChris Cain { 307dfbf7de5SChris Cain if (ec) 308dfbf7de5SChris Cain { 30962598e31SEd Tanous BMCWEB_LOG_ERROR("Processor Throttle getAllProperties error {}", ec); 310ac106bf6SEd Tanous messages::internalError(asyncResp->res); 311dfbf7de5SChris Cain return; 312dfbf7de5SChris Cain } 313dfbf7de5SChris Cain 314dfbf7de5SChris Cain const bool* status = nullptr; 315dfbf7de5SChris Cain const std::vector<std::string>* causes = nullptr; 316dfbf7de5SChris Cain 317dfbf7de5SChris Cain if (!sdbusplus::unpackPropertiesNoThrow(dbus_utils::UnpackErrorPrinter(), 318dfbf7de5SChris Cain properties, "Throttled", status, 319dfbf7de5SChris Cain "ThrottleCauses", causes)) 320dfbf7de5SChris Cain { 321ac106bf6SEd Tanous messages::internalError(asyncResp->res); 322dfbf7de5SChris Cain return; 323dfbf7de5SChris Cain } 324dfbf7de5SChris Cain 325ac106bf6SEd Tanous asyncResp->res.jsonValue["Throttled"] = *status; 326dfbf7de5SChris Cain nlohmann::json::array_t rCauses; 327dfbf7de5SChris Cain for (const std::string& cause : *causes) 328dfbf7de5SChris Cain { 329dfbf7de5SChris Cain processor::ThrottleCause rfCause = dbusToRfThrottleCause(cause); 330dfbf7de5SChris Cain if (rfCause == processor::ThrottleCause::Invalid) 331dfbf7de5SChris Cain { 332ac106bf6SEd Tanous messages::internalError(asyncResp->res); 333dfbf7de5SChris Cain return; 334dfbf7de5SChris Cain } 335dfbf7de5SChris Cain 336dfbf7de5SChris Cain rCauses.emplace_back(rfCause); 337dfbf7de5SChris Cain } 338ac106bf6SEd Tanous asyncResp->res.jsonValue["ThrottleCauses"] = std::move(rCauses); 339dfbf7de5SChris Cain } 340dfbf7de5SChris Cain 341bd79bce8SPatrick Williams inline void getThrottleProperties( 342bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 343bd79bce8SPatrick Williams const std::string& service, const std::string& objectPath) 344dfbf7de5SChris Cain { 34562598e31SEd Tanous BMCWEB_LOG_DEBUG("Get processor throttle resources"); 346dfbf7de5SChris Cain 347deae6a78SEd Tanous dbus::utility::getAllProperties( 348deae6a78SEd Tanous service, objectPath, "xyz.openbmc_project.Control.Power.Throttle", 349ac106bf6SEd Tanous [asyncResp](const boost::system::error_code& ec, 350dfbf7de5SChris Cain const dbus::utility::DBusPropertiesMap& properties) { 351ac106bf6SEd Tanous readThrottleProperties(asyncResp, ec, properties); 352dfbf7de5SChris Cain }); 353dfbf7de5SChris Cain } 354dfbf7de5SChris Cain 355ac106bf6SEd Tanous inline void getCpuAssetData(std::shared_ptr<bmcweb::AsyncResp> asyncResp, 356ac6a4445SGunnar Mills const std::string& service, 357ac6a4445SGunnar Mills const std::string& objPath) 358ac6a4445SGunnar Mills { 35962598e31SEd Tanous BMCWEB_LOG_DEBUG("Get Cpu Asset Data"); 360deae6a78SEd Tanous dbus::utility::getAllProperties( 361deae6a78SEd Tanous service, objPath, "xyz.openbmc_project.Inventory.Decorator.Asset", 362ac106bf6SEd Tanous [objPath, asyncResp{std::move(asyncResp)}]( 3635e7e2dc5SEd Tanous const boost::system::error_code& ec, 364351053f2SKrzysztof Grobelny const dbus::utility::DBusPropertiesMap& properties) { 365ac6a4445SGunnar Mills if (ec) 366ac6a4445SGunnar Mills { 36762598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error"); 368ac106bf6SEd Tanous messages::internalError(asyncResp->res); 369ac6a4445SGunnar Mills return; 370ac6a4445SGunnar Mills } 371ac6a4445SGunnar Mills 372351053f2SKrzysztof Grobelny const std::string* serialNumber = nullptr; 373351053f2SKrzysztof Grobelny const std::string* model = nullptr; 374351053f2SKrzysztof Grobelny const std::string* manufacturer = nullptr; 375351053f2SKrzysztof Grobelny const std::string* partNumber = nullptr; 376351053f2SKrzysztof Grobelny const std::string* sparePartNumber = nullptr; 377351053f2SKrzysztof Grobelny 378351053f2SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 379351053f2SKrzysztof Grobelny dbus_utils::UnpackErrorPrinter(), properties, "SerialNumber", 380351053f2SKrzysztof Grobelny serialNumber, "Model", model, "Manufacturer", manufacturer, 381351053f2SKrzysztof Grobelny "PartNumber", partNumber, "SparePartNumber", sparePartNumber); 382351053f2SKrzysztof Grobelny 383351053f2SKrzysztof Grobelny if (!success) 384ac6a4445SGunnar Mills { 385ac106bf6SEd Tanous messages::internalError(asyncResp->res); 386351053f2SKrzysztof Grobelny return; 387ac6a4445SGunnar Mills } 388351053f2SKrzysztof Grobelny 389351053f2SKrzysztof Grobelny if (serialNumber != nullptr && !serialNumber->empty()) 390ac6a4445SGunnar Mills { 391ac106bf6SEd Tanous asyncResp->res.jsonValue["SerialNumber"] = *serialNumber; 392351053f2SKrzysztof Grobelny } 393351053f2SKrzysztof Grobelny 394351053f2SKrzysztof Grobelny if ((model != nullptr) && !model->empty()) 395ac6a4445SGunnar Mills { 396ac106bf6SEd Tanous asyncResp->res.jsonValue["Model"] = *model; 397ac6a4445SGunnar Mills } 398ac6a4445SGunnar Mills 399351053f2SKrzysztof Grobelny if (manufacturer != nullptr) 400ac6a4445SGunnar Mills { 401ac106bf6SEd Tanous asyncResp->res.jsonValue["Manufacturer"] = *manufacturer; 402ac6a4445SGunnar Mills 403ac6a4445SGunnar Mills // Otherwise would be unexpected. 404351053f2SKrzysztof Grobelny if (manufacturer->find("Intel") != std::string::npos) 405ac6a4445SGunnar Mills { 406ac106bf6SEd Tanous asyncResp->res.jsonValue["ProcessorArchitecture"] = "x86"; 407ac106bf6SEd Tanous asyncResp->res.jsonValue["InstructionSet"] = "x86-64"; 408ac6a4445SGunnar Mills } 409351053f2SKrzysztof Grobelny else if (manufacturer->find("IBM") != std::string::npos) 410ac6a4445SGunnar Mills { 411ac106bf6SEd Tanous asyncResp->res.jsonValue["ProcessorArchitecture"] = "Power"; 412ac106bf6SEd Tanous asyncResp->res.jsonValue["InstructionSet"] = "PowerISA"; 413ac6a4445SGunnar Mills } 414ac6a4445SGunnar Mills } 415cba4f448SSunnySrivastava1984 416351053f2SKrzysztof Grobelny if (partNumber != nullptr) 417cba4f448SSunnySrivastava1984 { 418ac106bf6SEd Tanous asyncResp->res.jsonValue["PartNumber"] = *partNumber; 419cba4f448SSunnySrivastava1984 } 420cba4f448SSunnySrivastava1984 4216169de2cSBrad Bishop if (sparePartNumber != nullptr && !sparePartNumber->empty()) 422cba4f448SSunnySrivastava1984 { 423ac106bf6SEd Tanous asyncResp->res.jsonValue["SparePartNumber"] = *sparePartNumber; 424cba4f448SSunnySrivastava1984 } 425351053f2SKrzysztof Grobelny }); 426ac6a4445SGunnar Mills } 427ac6a4445SGunnar Mills 428ac106bf6SEd Tanous inline void getCpuRevisionData(std::shared_ptr<bmcweb::AsyncResp> asyncResp, 429ac6a4445SGunnar Mills const std::string& service, 430ac6a4445SGunnar Mills const std::string& objPath) 431ac6a4445SGunnar Mills { 43262598e31SEd Tanous BMCWEB_LOG_DEBUG("Get Cpu Revision Data"); 433deae6a78SEd Tanous dbus::utility::getAllProperties( 434deae6a78SEd Tanous service, objPath, "xyz.openbmc_project.Inventory.Decorator.Revision", 435ac106bf6SEd Tanous [objPath, asyncResp{std::move(asyncResp)}]( 4365e7e2dc5SEd Tanous const boost::system::error_code& ec, 437351053f2SKrzysztof Grobelny const dbus::utility::DBusPropertiesMap& properties) { 438ac6a4445SGunnar Mills if (ec) 439ac6a4445SGunnar Mills { 44062598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error"); 441ac106bf6SEd Tanous messages::internalError(asyncResp->res); 442ac6a4445SGunnar Mills return; 443ac6a4445SGunnar Mills } 444ac6a4445SGunnar Mills 445351053f2SKrzysztof Grobelny const std::string* version = nullptr; 446351053f2SKrzysztof Grobelny 447351053f2SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 448bd79bce8SPatrick Williams dbus_utils::UnpackErrorPrinter(), properties, "Version", 449bd79bce8SPatrick Williams version); 450351053f2SKrzysztof Grobelny 451351053f2SKrzysztof Grobelny if (!success) 452ac6a4445SGunnar Mills { 453ac106bf6SEd Tanous messages::internalError(asyncResp->res); 454351053f2SKrzysztof Grobelny return; 455351053f2SKrzysztof Grobelny } 456351053f2SKrzysztof Grobelny 457351053f2SKrzysztof Grobelny if (version != nullptr) 458ac6a4445SGunnar Mills { 459ac106bf6SEd Tanous asyncResp->res.jsonValue["Version"] = *version; 460ac6a4445SGunnar Mills } 461351053f2SKrzysztof Grobelny }); 462ac6a4445SGunnar Mills } 463ac6a4445SGunnar Mills 4648d1b46d7Szhanghch05 inline void getAcceleratorDataByService( 465ac106bf6SEd Tanous std::shared_ptr<bmcweb::AsyncResp> asyncResp, const std::string& acclrtrId, 4668d1b46d7Szhanghch05 const std::string& service, const std::string& objPath) 467ac6a4445SGunnar Mills { 46862598e31SEd Tanous BMCWEB_LOG_DEBUG("Get available system Accelerator resources by service."); 469deae6a78SEd Tanous dbus::utility::getAllProperties( 470deae6a78SEd Tanous service, objPath, "", 471ac106bf6SEd Tanous [acclrtrId, asyncResp{std::move(asyncResp)}]( 4725e7e2dc5SEd Tanous const boost::system::error_code& ec, 473351053f2SKrzysztof Grobelny const dbus::utility::DBusPropertiesMap& properties) { 474ac6a4445SGunnar Mills if (ec) 475ac6a4445SGunnar Mills { 47662598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error"); 477ac106bf6SEd Tanous messages::internalError(asyncResp->res); 478ac6a4445SGunnar Mills return; 479ac6a4445SGunnar Mills } 480ac6a4445SGunnar Mills 481351053f2SKrzysztof Grobelny const bool* functional = nullptr; 482351053f2SKrzysztof Grobelny const bool* present = nullptr; 483351053f2SKrzysztof Grobelny 484351053f2SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 485351053f2SKrzysztof Grobelny dbus_utils::UnpackErrorPrinter(), properties, "Functional", 486351053f2SKrzysztof Grobelny functional, "Present", present); 487351053f2SKrzysztof Grobelny 488351053f2SKrzysztof Grobelny if (!success) 489ac6a4445SGunnar Mills { 490ac106bf6SEd Tanous messages::internalError(asyncResp->res); 491351053f2SKrzysztof Grobelny return; 492ac6a4445SGunnar Mills } 493ac6a4445SGunnar Mills 494ac6a4445SGunnar Mills std::string state = "Enabled"; 495ac6a4445SGunnar Mills std::string health = "OK"; 496ac6a4445SGunnar Mills 497351053f2SKrzysztof Grobelny if (present != nullptr && !*present) 498ac6a4445SGunnar Mills { 499ac6a4445SGunnar Mills state = "Absent"; 500ac6a4445SGunnar Mills } 501ac6a4445SGunnar Mills 502351053f2SKrzysztof Grobelny if (functional != nullptr && !*functional) 503ac6a4445SGunnar Mills { 504ac6a4445SGunnar Mills if (state == "Enabled") 505ac6a4445SGunnar Mills { 506ac6a4445SGunnar Mills health = "Critical"; 507ac6a4445SGunnar Mills } 508ac6a4445SGunnar Mills } 509ac6a4445SGunnar Mills 510ac106bf6SEd Tanous asyncResp->res.jsonValue["Id"] = acclrtrId; 511ac106bf6SEd Tanous asyncResp->res.jsonValue["Name"] = "Processor"; 512ac106bf6SEd Tanous asyncResp->res.jsonValue["Status"]["State"] = state; 513ac106bf6SEd Tanous asyncResp->res.jsonValue["Status"]["Health"] = health; 514539d8c6bSEd Tanous asyncResp->res.jsonValue["ProcessorType"] = 515539d8c6bSEd Tanous processor::ProcessorType::Accelerator; 516351053f2SKrzysztof Grobelny }); 517ac6a4445SGunnar Mills } 518ac6a4445SGunnar Mills 519dba0c291SJonathan Doman // OperatingConfig D-Bus Types 520dba0c291SJonathan Doman using TurboProfileProperty = std::vector<std::tuple<uint32_t, size_t>>; 521dba0c291SJonathan Doman using BaseSpeedPrioritySettingsProperty = 522dba0c291SJonathan Doman std::vector<std::tuple<uint32_t, std::vector<uint32_t>>>; 523dba0c291SJonathan Doman // uint32_t and size_t may or may not be the same type, requiring a dedup'd 524dba0c291SJonathan Doman // variant 525dba0c291SJonathan Doman 526dba0c291SJonathan Doman /** 527dba0c291SJonathan Doman * Fill out the HighSpeedCoreIDs in a Processor resource from the given 528dba0c291SJonathan Doman * OperatingConfig D-Bus property. 529dba0c291SJonathan Doman * 530ac106bf6SEd Tanous * @param[in,out] asyncResp Async HTTP response. 531dba0c291SJonathan Doman * @param[in] baseSpeedSettings Full list of base speed priority groups, 532dba0c291SJonathan Doman * to use to determine the list of high 533dba0c291SJonathan Doman * speed cores. 534dba0c291SJonathan Doman */ 535dba0c291SJonathan Doman inline void highSpeedCoreIdsHandler( 536ac106bf6SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 537dba0c291SJonathan Doman const BaseSpeedPrioritySettingsProperty& baseSpeedSettings) 538dba0c291SJonathan Doman { 539dba0c291SJonathan Doman // The D-Bus property does not indicate which bucket is the "high 540dba0c291SJonathan Doman // priority" group, so let's discern that by looking for the one with 541dba0c291SJonathan Doman // highest base frequency. 542dba0c291SJonathan Doman auto highPriorityGroup = baseSpeedSettings.cend(); 543dba0c291SJonathan Doman uint32_t highestBaseSpeed = 0; 544dba0c291SJonathan Doman for (auto it = baseSpeedSettings.cbegin(); it != baseSpeedSettings.cend(); 545dba0c291SJonathan Doman ++it) 546dba0c291SJonathan Doman { 547dba0c291SJonathan Doman const uint32_t baseFreq = std::get<uint32_t>(*it); 548dba0c291SJonathan Doman if (baseFreq > highestBaseSpeed) 549dba0c291SJonathan Doman { 550dba0c291SJonathan Doman highestBaseSpeed = baseFreq; 551dba0c291SJonathan Doman highPriorityGroup = it; 552dba0c291SJonathan Doman } 553dba0c291SJonathan Doman } 554dba0c291SJonathan Doman 555ac106bf6SEd Tanous nlohmann::json& jsonCoreIds = asyncResp->res.jsonValue["HighSpeedCoreIDs"]; 556dba0c291SJonathan Doman jsonCoreIds = nlohmann::json::array(); 557dba0c291SJonathan Doman 558dba0c291SJonathan Doman // There may not be any entries in the D-Bus property, so only populate 559dba0c291SJonathan Doman // if there was actually something there. 560dba0c291SJonathan Doman if (highPriorityGroup != baseSpeedSettings.cend()) 561dba0c291SJonathan Doman { 562dba0c291SJonathan Doman jsonCoreIds = std::get<std::vector<uint32_t>>(*highPriorityGroup); 563dba0c291SJonathan Doman } 564dba0c291SJonathan Doman } 565dba0c291SJonathan Doman 566dba0c291SJonathan Doman /** 567dba0c291SJonathan Doman * Fill out OperatingConfig related items in a Processor resource by requesting 568dba0c291SJonathan Doman * data from the given D-Bus object. 569dba0c291SJonathan Doman * 570ac106bf6SEd Tanous * @param[in,out] asyncResp Async HTTP response. 571dba0c291SJonathan Doman * @param[in] cpuId CPU D-Bus name. 572dba0c291SJonathan Doman * @param[in] service D-Bus service to query. 573dba0c291SJonathan Doman * @param[in] objPath D-Bus object to query. 574dba0c291SJonathan Doman */ 575504af5a0SPatrick Williams inline void getCpuConfigData( 576504af5a0SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 577ac106bf6SEd Tanous const std::string& cpuId, const std::string& service, 578dba0c291SJonathan Doman const std::string& objPath) 579dba0c291SJonathan Doman { 58062598e31SEd Tanous BMCWEB_LOG_INFO("Getting CPU operating configs for {}", cpuId); 581dba0c291SJonathan Doman 582dba0c291SJonathan Doman // First, GetAll CurrentOperatingConfig properties on the object 583deae6a78SEd Tanous dbus::utility::getAllProperties( 584deae6a78SEd Tanous service, objPath, 585351053f2SKrzysztof Grobelny "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig", 586ac106bf6SEd Tanous [asyncResp, cpuId, 5875e7e2dc5SEd Tanous service](const boost::system::error_code& ec, 588351053f2SKrzysztof Grobelny const dbus::utility::DBusPropertiesMap& properties) { 589dba0c291SJonathan Doman if (ec) 590dba0c291SJonathan Doman { 59162598e31SEd Tanous BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec, ec.message()); 592ac106bf6SEd Tanous messages::internalError(asyncResp->res); 593dba0c291SJonathan Doman return; 594dba0c291SJonathan Doman } 595dba0c291SJonathan Doman 596ac106bf6SEd Tanous nlohmann::json& json = asyncResp->res.jsonValue; 597dba0c291SJonathan Doman 598351053f2SKrzysztof Grobelny const sdbusplus::message::object_path* appliedConfig = nullptr; 599351053f2SKrzysztof Grobelny const bool* baseSpeedPriorityEnabled = nullptr; 600351053f2SKrzysztof Grobelny 601351053f2SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 602351053f2SKrzysztof Grobelny dbus_utils::UnpackErrorPrinter(), properties, "AppliedConfig", 603351053f2SKrzysztof Grobelny appliedConfig, "BaseSpeedPriorityEnabled", 604351053f2SKrzysztof Grobelny baseSpeedPriorityEnabled); 605351053f2SKrzysztof Grobelny 606351053f2SKrzysztof Grobelny if (!success) 607dba0c291SJonathan Doman { 608ac106bf6SEd Tanous messages::internalError(asyncResp->res); 609351053f2SKrzysztof Grobelny return; 610dba0c291SJonathan Doman } 611dba0c291SJonathan Doman 612351053f2SKrzysztof Grobelny if (appliedConfig != nullptr) 613351053f2SKrzysztof Grobelny { 614351053f2SKrzysztof Grobelny const std::string& dbusPath = appliedConfig->str; 6151476687dSEd Tanous nlohmann::json::object_t operatingConfig; 616ef4c65b7SEd Tanous operatingConfig["@odata.id"] = boost::urls::format( 617253f11b8SEd Tanous "/redfish/v1/Systems/{}/Processors/{}/OperatingConfigs", 618253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME, cpuId); 6191476687dSEd Tanous json["OperatingConfigs"] = std::move(operatingConfig); 620dba0c291SJonathan Doman 621dba0c291SJonathan Doman // Reuse the D-Bus config object name for the Redfish 622dba0c291SJonathan Doman // URI 623dba0c291SJonathan Doman size_t baseNamePos = dbusPath.rfind('/'); 624dba0c291SJonathan Doman if (baseNamePos == std::string::npos || 625dba0c291SJonathan Doman baseNamePos == (dbusPath.size() - 1)) 626dba0c291SJonathan Doman { 627dba0c291SJonathan Doman // If the AppliedConfig was somehow not a valid path, 628dba0c291SJonathan Doman // skip adding any more properties, since everything 629dba0c291SJonathan Doman // else is tied to this applied config. 630ac106bf6SEd Tanous messages::internalError(asyncResp->res); 631351053f2SKrzysztof Grobelny return; 632dba0c291SJonathan Doman } 6331476687dSEd Tanous nlohmann::json::object_t appliedOperatingConfig; 634ef4c65b7SEd Tanous appliedOperatingConfig["@odata.id"] = boost::urls::format( 635253f11b8SEd Tanous "/redfish/v1/Systems/{}/Processors/{}/OperatingConfigs/{}", 636253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME, cpuId, 637253f11b8SEd Tanous dbusPath.substr(baseNamePos + 1)); 638bd79bce8SPatrick Williams json["AppliedOperatingConfig"] = 639bd79bce8SPatrick Williams std::move(appliedOperatingConfig); 640dba0c291SJonathan Doman 641dba0c291SJonathan Doman // Once we found the current applied config, queue another 642dba0c291SJonathan Doman // request to read the base freq core ids out of that 643dba0c291SJonathan Doman // config. 644deae6a78SEd Tanous dbus::utility::getProperty<BaseSpeedPrioritySettingsProperty>( 645deae6a78SEd Tanous service, dbusPath, 6461e1e598dSJonathan Doman "xyz.openbmc_project.Inventory.Item.Cpu." 6471e1e598dSJonathan Doman "OperatingConfig", 6481e1e598dSJonathan Doman "BaseSpeedPrioritySettings", 649bd79bce8SPatrick Williams [asyncResp](const boost::system::error_code& ec2, 650bd79bce8SPatrick Williams const BaseSpeedPrioritySettingsProperty& 651bd79bce8SPatrick Williams baseSpeedList) { 6528a592810SEd Tanous if (ec2) 653dba0c291SJonathan Doman { 654bd79bce8SPatrick Williams BMCWEB_LOG_WARNING("D-Bus Property Get error: {}", 655bd79bce8SPatrick Williams ec2); 656ac106bf6SEd Tanous messages::internalError(asyncResp->res); 657dba0c291SJonathan Doman return; 658dba0c291SJonathan Doman } 6591e1e598dSJonathan Doman 660ac106bf6SEd Tanous highSpeedCoreIdsHandler(asyncResp, baseSpeedList); 6611e1e598dSJonathan Doman }); 662dba0c291SJonathan Doman } 663351053f2SKrzysztof Grobelny 664351053f2SKrzysztof Grobelny if (baseSpeedPriorityEnabled != nullptr) 665dba0c291SJonathan Doman { 666dba0c291SJonathan Doman json["BaseSpeedPriorityState"] = 667351053f2SKrzysztof Grobelny *baseSpeedPriorityEnabled ? "Enabled" : "Disabled"; 668dba0c291SJonathan Doman } 669351053f2SKrzysztof Grobelny }); 670dba0c291SJonathan Doman } 671dba0c291SJonathan Doman 672cba4f448SSunnySrivastava1984 /** 673cba4f448SSunnySrivastava1984 * @brief Fill out location info of a processor by 674cba4f448SSunnySrivastava1984 * requesting data from the given D-Bus object. 675cba4f448SSunnySrivastava1984 * 676ac106bf6SEd Tanous * @param[in,out] asyncResp Async HTTP response. 677cba4f448SSunnySrivastava1984 * @param[in] service D-Bus service to query. 678cba4f448SSunnySrivastava1984 * @param[in] objPath D-Bus object to query. 679cba4f448SSunnySrivastava1984 */ 680ac106bf6SEd Tanous inline void getCpuLocationCode(std::shared_ptr<bmcweb::AsyncResp> asyncResp, 681cba4f448SSunnySrivastava1984 const std::string& service, 682cba4f448SSunnySrivastava1984 const std::string& objPath) 683cba4f448SSunnySrivastava1984 { 68462598e31SEd Tanous BMCWEB_LOG_DEBUG("Get Cpu Location Data"); 685deae6a78SEd Tanous dbus::utility::getProperty<std::string>( 686deae6a78SEd Tanous service, objPath, 6871e1e598dSJonathan Doman "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode", 688ac106bf6SEd Tanous [objPath, asyncResp{std::move(asyncResp)}]( 689ac106bf6SEd Tanous const boost::system::error_code& ec, const std::string& property) { 690cba4f448SSunnySrivastava1984 if (ec) 691cba4f448SSunnySrivastava1984 { 69262598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error"); 693ac106bf6SEd Tanous messages::internalError(asyncResp->res); 694cba4f448SSunnySrivastava1984 return; 695cba4f448SSunnySrivastava1984 } 696cba4f448SSunnySrivastava1984 697bd79bce8SPatrick Williams asyncResp->res 698bd79bce8SPatrick Williams .jsonValue["Location"]["PartLocation"]["ServiceLabel"] = 6991e1e598dSJonathan Doman property; 7001e1e598dSJonathan Doman }); 701cba4f448SSunnySrivastava1984 } 702cba4f448SSunnySrivastava1984 703c951448aSJonathan Doman /** 70449e429caSJonathan Doman * Populate the unique identifier in a Processor resource by requesting data 70549e429caSJonathan Doman * from the given D-Bus object. 70649e429caSJonathan Doman * 707ac106bf6SEd Tanous * @param[in,out] asyncResp Async HTTP response. 70849e429caSJonathan Doman * @param[in] service D-Bus service to query. 70949e429caSJonathan Doman * @param[in] objPath D-Bus object to query. 71049e429caSJonathan Doman */ 711ac106bf6SEd Tanous inline void getCpuUniqueId(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 71249e429caSJonathan Doman const std::string& service, 71349e429caSJonathan Doman const std::string& objectPath) 71449e429caSJonathan Doman { 71562598e31SEd Tanous BMCWEB_LOG_DEBUG("Get CPU UniqueIdentifier"); 716deae6a78SEd Tanous dbus::utility::getProperty<std::string>( 717deae6a78SEd Tanous service, objectPath, 7181e1e598dSJonathan Doman "xyz.openbmc_project.Inventory.Decorator.UniqueIdentifier", 7191e1e598dSJonathan Doman "UniqueIdentifier", 720ac106bf6SEd Tanous [asyncResp](const boost::system::error_code& ec, 721ac106bf6SEd Tanous const std::string& id) { 7221e1e598dSJonathan Doman if (ec) 72349e429caSJonathan Doman { 72462598e31SEd Tanous BMCWEB_LOG_ERROR("Failed to read cpu unique id: {}", ec); 725ac106bf6SEd Tanous messages::internalError(asyncResp->res); 72649e429caSJonathan Doman return; 72749e429caSJonathan Doman } 728ac106bf6SEd Tanous asyncResp->res 729ac106bf6SEd Tanous .jsonValue["ProcessorId"]["ProtectedIdentificationNumber"] = id; 7301e1e598dSJonathan Doman }); 73149e429caSJonathan Doman } 73249e429caSJonathan Doman 733*98eafce5SGeorge Liu inline void handleProcessorSubtree( 734*98eafce5SGeorge Liu const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 735*98eafce5SGeorge Liu const std::string& processorId, 736*98eafce5SGeorge Liu const std::function< 737*98eafce5SGeorge Liu void(const std::string& objectPath, 738*98eafce5SGeorge Liu const dbus::utility::MapperServiceMap& serviceMap)>& callback, 739*98eafce5SGeorge Liu const boost::system::error_code& ec, 740*98eafce5SGeorge Liu const dbus::utility::MapperGetSubTreeResponse& subtree) 741*98eafce5SGeorge Liu { 742*98eafce5SGeorge Liu if (ec) 743*98eafce5SGeorge Liu { 744*98eafce5SGeorge Liu BMCWEB_LOG_ERROR("DBUS response error: {}", ec); 745*98eafce5SGeorge Liu messages::internalError(asyncResp->res); 746*98eafce5SGeorge Liu return; 747*98eafce5SGeorge Liu } 748*98eafce5SGeorge Liu for (const auto& [objectPath, serviceMap] : subtree) 749*98eafce5SGeorge Liu { 750*98eafce5SGeorge Liu // Ignore any objects which don't end with our desired cpu name 751*98eafce5SGeorge Liu sdbusplus::message::object_path path(objectPath); 752*98eafce5SGeorge Liu if (path.filename() == processorId) 753*98eafce5SGeorge Liu { 754*98eafce5SGeorge Liu // Filter out objects that don't have the CPU-specific 755*98eafce5SGeorge Liu // interfaces to make sure we can return 404 on non-CPUs 756*98eafce5SGeorge Liu // (e.g. /redfish/../Processors/dimm0) 757*98eafce5SGeorge Liu for (const auto& [serviceName, interfaceList] : serviceMap) 758*98eafce5SGeorge Liu { 759*98eafce5SGeorge Liu if (std::ranges::find_first_of(interfaceList, 760*98eafce5SGeorge Liu processorInterfaces) != 761*98eafce5SGeorge Liu interfaceList.end()) 762*98eafce5SGeorge Liu { 763*98eafce5SGeorge Liu // Process the first object which matches cpu name and 764*98eafce5SGeorge Liu // required interfaces, and potentially ignore any other 765*98eafce5SGeorge Liu // matching objects. Assume all interfaces we want to 766*98eafce5SGeorge Liu // process must be on the same object path. 767*98eafce5SGeorge Liu 768*98eafce5SGeorge Liu callback(objectPath, serviceMap); 769*98eafce5SGeorge Liu return; 770*98eafce5SGeorge Liu } 771*98eafce5SGeorge Liu } 772*98eafce5SGeorge Liu } 773*98eafce5SGeorge Liu } 774*98eafce5SGeorge Liu messages::resourceNotFound(asyncResp->res, "Processor", processorId); 775*98eafce5SGeorge Liu } 776*98eafce5SGeorge Liu 77749e429caSJonathan Doman /** 778c951448aSJonathan Doman * Find the D-Bus object representing the requested Processor, and call the 779c951448aSJonathan Doman * handler with the results. If matching object is not found, add 404 error to 780c951448aSJonathan Doman * response and don't call the handler. 781c951448aSJonathan Doman * 782*98eafce5SGeorge Liu * @param[in,out] asyncResp Async HTTP response. 783c951448aSJonathan Doman * @param[in] processorId Redfish Processor Id. 784*98eafce5SGeorge Liu * @param[in] callback Callback to continue processing request upon 785c951448aSJonathan Doman * successfully finding object. 786c951448aSJonathan Doman */ 787*98eafce5SGeorge Liu inline void getProcessorObject( 788*98eafce5SGeorge Liu const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 789c951448aSJonathan Doman const std::string& processorId, 790*98eafce5SGeorge Liu std::function<void(const std::string& objectPath, 791*98eafce5SGeorge Liu const dbus::utility::MapperServiceMap& serviceMap)>&& 792*98eafce5SGeorge Liu callback) 793ac6a4445SGunnar Mills { 79462598e31SEd Tanous BMCWEB_LOG_DEBUG("Get available system processor resources."); 795ac6a4445SGunnar Mills 796c951448aSJonathan Doman // GetSubTree on all interfaces which provide info about a Processor 797dfbf7de5SChris Cain constexpr std::array<std::string_view, 9> interfaces = { 798e99073f5SGeorge Liu "xyz.openbmc_project.Common.UUID", 799e99073f5SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.Asset", 800e99073f5SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.Revision", 801e99073f5SGeorge Liu "xyz.openbmc_project.Inventory.Item.Cpu", 802e99073f5SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.LocationCode", 803e99073f5SGeorge Liu "xyz.openbmc_project.Inventory.Item.Accelerator", 804e99073f5SGeorge Liu "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig", 805dfbf7de5SChris Cain "xyz.openbmc_project.Inventory.Decorator.UniqueIdentifier", 806dfbf7de5SChris Cain "xyz.openbmc_project.Control.Power.Throttle"}; 807e99073f5SGeorge Liu dbus::utility::getSubTree( 808e99073f5SGeorge Liu "/xyz/openbmc_project/inventory", 0, interfaces, 809*98eafce5SGeorge Liu [asyncResp, processorId, callback{std::move(callback)}]( 810e99073f5SGeorge Liu const boost::system::error_code& ec, 811e99073f5SGeorge Liu const dbus::utility::MapperGetSubTreeResponse& subtree) { 812*98eafce5SGeorge Liu handleProcessorSubtree(asyncResp, processorId, callback, ec, 813*98eafce5SGeorge Liu subtree); 814e99073f5SGeorge Liu }); 815ac6a4445SGunnar Mills } 816ac6a4445SGunnar Mills 817bd79bce8SPatrick Williams inline void getProcessorData( 818bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 819bd79bce8SPatrick Williams const std::string& processorId, const std::string& objectPath, 8205df6eda2SShantappa Teekappanavar const dbus::utility::MapperServiceMap& serviceMap) 821c951448aSJonathan Doman { 822*98eafce5SGeorge Liu asyncResp->res.addHeader( 823*98eafce5SGeorge Liu boost::beast::http::field::link, 824*98eafce5SGeorge Liu "</redfish/v1/JsonSchemas/Processor/Processor.json>; rel=describedby"); 825*98eafce5SGeorge Liu asyncResp->res.jsonValue["@odata.type"] = "#Processor.v1_18_0.Processor"; 826*98eafce5SGeorge Liu asyncResp->res.jsonValue["@odata.id"] = 827*98eafce5SGeorge Liu boost::urls::format("/redfish/v1/Systems/{}/Processors/{}", 828*98eafce5SGeorge Liu BMCWEB_REDFISH_SYSTEM_URI_NAME, processorId); 829*98eafce5SGeorge Liu 830c951448aSJonathan Doman for (const auto& [serviceName, interfaceList] : serviceMap) 831c951448aSJonathan Doman { 832c951448aSJonathan Doman for (const auto& interface : interfaceList) 833c951448aSJonathan Doman { 834c951448aSJonathan Doman if (interface == "xyz.openbmc_project.Inventory.Decorator.Asset") 835c951448aSJonathan Doman { 836ac106bf6SEd Tanous getCpuAssetData(asyncResp, serviceName, objectPath); 837c951448aSJonathan Doman } 8380fda0f12SGeorge Liu else if (interface == 8390fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.Revision") 840c951448aSJonathan Doman { 841ac106bf6SEd Tanous getCpuRevisionData(asyncResp, serviceName, objectPath); 842c951448aSJonathan Doman } 843c951448aSJonathan Doman else if (interface == "xyz.openbmc_project.Inventory.Item.Cpu") 844c951448aSJonathan Doman { 845ac106bf6SEd Tanous getCpuDataByService(asyncResp, processorId, serviceName, 846c951448aSJonathan Doman objectPath); 847c951448aSJonathan Doman } 8480fda0f12SGeorge Liu else if (interface == 8490fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Item.Accelerator") 850c951448aSJonathan Doman { 851ac106bf6SEd Tanous getAcceleratorDataByService(asyncResp, processorId, serviceName, 852c951448aSJonathan Doman objectPath); 853c951448aSJonathan Doman } 8540fda0f12SGeorge Liu else if ( 8550fda0f12SGeorge Liu interface == 8560fda0f12SGeorge Liu "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig") 857c951448aSJonathan Doman { 858ac106bf6SEd Tanous getCpuConfigData(asyncResp, processorId, serviceName, 859ac106bf6SEd Tanous objectPath); 860c951448aSJonathan Doman } 8610fda0f12SGeorge Liu else if (interface == 8620fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.LocationCode") 863c951448aSJonathan Doman { 864ac106bf6SEd Tanous getCpuLocationCode(asyncResp, serviceName, objectPath); 865c951448aSJonathan Doman } 86671b82f26SSharad Yadav else if (interface == "xyz.openbmc_project.Common.UUID") 86771b82f26SSharad Yadav { 868ac106bf6SEd Tanous getProcessorUUID(asyncResp, serviceName, objectPath); 86971b82f26SSharad Yadav } 8700fda0f12SGeorge Liu else if (interface == 8710fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.UniqueIdentifier") 87249e429caSJonathan Doman { 873ac106bf6SEd Tanous getCpuUniqueId(asyncResp, serviceName, objectPath); 87449e429caSJonathan Doman } 875dfbf7de5SChris Cain else if (interface == "xyz.openbmc_project.Control.Power.Throttle") 876dfbf7de5SChris Cain { 877ac106bf6SEd Tanous getThrottleProperties(asyncResp, serviceName, objectPath); 878dfbf7de5SChris Cain } 879*98eafce5SGeorge Liu else if (interface == "xyz.openbmc_project.Association.Definitions") 880*98eafce5SGeorge Liu { 881*98eafce5SGeorge Liu getLocationIndicatorActive(asyncResp, objectPath); 882*98eafce5SGeorge Liu } 883c951448aSJonathan Doman } 884c951448aSJonathan Doman } 885c951448aSJonathan Doman } 886c951448aSJonathan Doman 887dba0c291SJonathan Doman /** 888dba0c291SJonathan Doman * Request all the properties for the given D-Bus object and fill out the 889dba0c291SJonathan Doman * related entries in the Redfish OperatingConfig response. 890dba0c291SJonathan Doman * 891ac106bf6SEd Tanous * @param[in,out] asyncResp Async HTTP response. 892dba0c291SJonathan Doman * @param[in] service D-Bus service name to query. 893dba0c291SJonathan Doman * @param[in] objPath D-Bus object to query. 894dba0c291SJonathan Doman */ 895bd79bce8SPatrick Williams inline void getOperatingConfigData( 896bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 897bd79bce8SPatrick Williams const std::string& service, const std::string& objPath) 898dba0c291SJonathan Doman { 899deae6a78SEd Tanous dbus::utility::getAllProperties( 900deae6a78SEd Tanous service, objPath, 901351053f2SKrzysztof Grobelny "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig", 902ac106bf6SEd Tanous [asyncResp](const boost::system::error_code& ec, 903351053f2SKrzysztof Grobelny const dbus::utility::DBusPropertiesMap& properties) { 904dba0c291SJonathan Doman if (ec) 905dba0c291SJonathan Doman { 90662598e31SEd Tanous BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec, ec.message()); 907ac106bf6SEd Tanous messages::internalError(asyncResp->res); 908dba0c291SJonathan Doman return; 909dba0c291SJonathan Doman } 910dba0c291SJonathan Doman 911351053f2SKrzysztof Grobelny const size_t* availableCoreCount = nullptr; 912351053f2SKrzysztof Grobelny const uint32_t* baseSpeed = nullptr; 913351053f2SKrzysztof Grobelny const uint32_t* maxJunctionTemperature = nullptr; 914351053f2SKrzysztof Grobelny const uint32_t* maxSpeed = nullptr; 915351053f2SKrzysztof Grobelny const uint32_t* powerLimit = nullptr; 916351053f2SKrzysztof Grobelny const TurboProfileProperty* turboProfile = nullptr; 917351053f2SKrzysztof Grobelny const BaseSpeedPrioritySettingsProperty* baseSpeedPrioritySettings = 918351053f2SKrzysztof Grobelny nullptr; 919351053f2SKrzysztof Grobelny 920351053f2SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 921bd79bce8SPatrick Williams dbus_utils::UnpackErrorPrinter(), properties, 922bd79bce8SPatrick Williams "AvailableCoreCount", availableCoreCount, "BaseSpeed", 923bd79bce8SPatrick Williams baseSpeed, "MaxJunctionTemperature", maxJunctionTemperature, 924bd79bce8SPatrick Williams "MaxSpeed", maxSpeed, "PowerLimit", powerLimit, "TurboProfile", 925bd79bce8SPatrick Williams turboProfile, "BaseSpeedPrioritySettings", 926bd79bce8SPatrick Williams baseSpeedPrioritySettings); 927351053f2SKrzysztof Grobelny 928351053f2SKrzysztof Grobelny if (!success) 929dba0c291SJonathan Doman { 930ac106bf6SEd Tanous messages::internalError(asyncResp->res); 931351053f2SKrzysztof Grobelny return; 932dba0c291SJonathan Doman } 933dba0c291SJonathan Doman 934ac106bf6SEd Tanous nlohmann::json& json = asyncResp->res.jsonValue; 935351053f2SKrzysztof Grobelny 936351053f2SKrzysztof Grobelny if (availableCoreCount != nullptr) 937351053f2SKrzysztof Grobelny { 938351053f2SKrzysztof Grobelny json["TotalAvailableCoreCount"] = *availableCoreCount; 939351053f2SKrzysztof Grobelny } 940351053f2SKrzysztof Grobelny 941351053f2SKrzysztof Grobelny if (baseSpeed != nullptr) 942351053f2SKrzysztof Grobelny { 943351053f2SKrzysztof Grobelny json["BaseSpeedMHz"] = *baseSpeed; 944351053f2SKrzysztof Grobelny } 945351053f2SKrzysztof Grobelny 946351053f2SKrzysztof Grobelny if (maxJunctionTemperature != nullptr) 947351053f2SKrzysztof Grobelny { 948351053f2SKrzysztof Grobelny json["MaxJunctionTemperatureCelsius"] = *maxJunctionTemperature; 949351053f2SKrzysztof Grobelny } 950351053f2SKrzysztof Grobelny 951351053f2SKrzysztof Grobelny if (maxSpeed != nullptr) 952351053f2SKrzysztof Grobelny { 953351053f2SKrzysztof Grobelny json["MaxSpeedMHz"] = *maxSpeed; 954351053f2SKrzysztof Grobelny } 955351053f2SKrzysztof Grobelny 956351053f2SKrzysztof Grobelny if (powerLimit != nullptr) 957351053f2SKrzysztof Grobelny { 958351053f2SKrzysztof Grobelny json["TDPWatts"] = *powerLimit; 959351053f2SKrzysztof Grobelny } 960351053f2SKrzysztof Grobelny 961351053f2SKrzysztof Grobelny if (turboProfile != nullptr) 962351053f2SKrzysztof Grobelny { 963dba0c291SJonathan Doman nlohmann::json& turboArray = json["TurboProfile"]; 964dba0c291SJonathan Doman turboArray = nlohmann::json::array(); 965351053f2SKrzysztof Grobelny for (const auto& [turboSpeed, coreCount] : *turboProfile) 966dba0c291SJonathan Doman { 9671476687dSEd Tanous nlohmann::json::object_t turbo; 9681476687dSEd Tanous turbo["ActiveCoreCount"] = coreCount; 9691476687dSEd Tanous turbo["MaxSpeedMHz"] = turboSpeed; 970b2ba3072SPatrick Williams turboArray.emplace_back(std::move(turbo)); 971dba0c291SJonathan Doman } 972dba0c291SJonathan Doman } 973dba0c291SJonathan Doman 974351053f2SKrzysztof Grobelny if (baseSpeedPrioritySettings != nullptr) 975351053f2SKrzysztof Grobelny { 976bd79bce8SPatrick Williams nlohmann::json& baseSpeedArray = 977bd79bce8SPatrick Williams json["BaseSpeedPrioritySettings"]; 978dba0c291SJonathan Doman baseSpeedArray = nlohmann::json::array(); 979351053f2SKrzysztof Grobelny for (const auto& [baseSpeedMhz, coreList] : 980351053f2SKrzysztof Grobelny *baseSpeedPrioritySettings) 981dba0c291SJonathan Doman { 9821476687dSEd Tanous nlohmann::json::object_t speed; 9831476687dSEd Tanous speed["CoreCount"] = coreList.size(); 9841476687dSEd Tanous speed["CoreIDs"] = coreList; 985351053f2SKrzysztof Grobelny speed["BaseSpeedMHz"] = baseSpeedMhz; 986b2ba3072SPatrick Williams baseSpeedArray.emplace_back(std::move(speed)); 987dba0c291SJonathan Doman } 988dba0c291SJonathan Doman } 989351053f2SKrzysztof Grobelny }); 990dba0c291SJonathan Doman } 991dba0c291SJonathan Doman 9923cde86f1SJonathan Doman /** 9933cde86f1SJonathan Doman * Handle the PATCH operation of the AppliedOperatingConfig property. Do basic 9943cde86f1SJonathan Doman * validation of the input data, and then set the D-Bus property. 9953cde86f1SJonathan Doman * 9963cde86f1SJonathan Doman * @param[in,out] resp Async HTTP response. 9973cde86f1SJonathan Doman * @param[in] processorId Processor's Id. 9983cde86f1SJonathan Doman * @param[in] appliedConfigUri New property value to apply. 9993cde86f1SJonathan Doman * @param[in] cpuObjectPath Path of CPU object to modify. 10003cde86f1SJonathan Doman * @param[in] serviceMap Service map for CPU object. 10013cde86f1SJonathan Doman */ 10023cde86f1SJonathan Doman inline void patchAppliedOperatingConfig( 10033cde86f1SJonathan Doman const std::shared_ptr<bmcweb::AsyncResp>& resp, 10043cde86f1SJonathan Doman const std::string& processorId, const std::string& appliedConfigUri, 10055df6eda2SShantappa Teekappanavar const std::string& cpuObjectPath, 10065df6eda2SShantappa Teekappanavar const dbus::utility::MapperServiceMap& serviceMap) 10073cde86f1SJonathan Doman { 10083cde86f1SJonathan Doman // Check that the property even exists by checking for the interface 10093cde86f1SJonathan Doman const std::string* controlService = nullptr; 10103cde86f1SJonathan Doman for (const auto& [serviceName, interfaceList] : serviceMap) 10113cde86f1SJonathan Doman { 10123544d2a7SEd Tanous if (std::ranges::find(interfaceList, 10133cde86f1SJonathan Doman "xyz.openbmc_project.Control.Processor." 10143cde86f1SJonathan Doman "CurrentOperatingConfig") != interfaceList.end()) 10153cde86f1SJonathan Doman { 10163cde86f1SJonathan Doman controlService = &serviceName; 10173cde86f1SJonathan Doman break; 10183cde86f1SJonathan Doman } 10193cde86f1SJonathan Doman } 10203cde86f1SJonathan Doman 10213cde86f1SJonathan Doman if (controlService == nullptr) 10223cde86f1SJonathan Doman { 10233cde86f1SJonathan Doman messages::internalError(resp->res); 10243cde86f1SJonathan Doman return; 10253cde86f1SJonathan Doman } 10263cde86f1SJonathan Doman 10273cde86f1SJonathan Doman // Check that the config URI is a child of the cpu URI being patched. 1028253f11b8SEd Tanous std::string expectedPrefix(std::format("/redfish/v1/Systems/{}/Processors/", 1029253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME)); 10303cde86f1SJonathan Doman expectedPrefix += processorId; 10313cde86f1SJonathan Doman expectedPrefix += "/OperatingConfigs/"; 103211ba3979SEd Tanous if (!appliedConfigUri.starts_with(expectedPrefix) || 10333cde86f1SJonathan Doman expectedPrefix.size() == appliedConfigUri.size()) 10343cde86f1SJonathan Doman { 103587c44966SAsmitha Karunanithi messages::propertyValueIncorrect(resp->res, "AppliedOperatingConfig", 103687c44966SAsmitha Karunanithi appliedConfigUri); 10373cde86f1SJonathan Doman return; 10383cde86f1SJonathan Doman } 10393cde86f1SJonathan Doman 10403cde86f1SJonathan Doman // Generate the D-Bus path of the OperatingConfig object, by assuming it's a 10413cde86f1SJonathan Doman // direct child of the CPU object. 10423cde86f1SJonathan Doman // Strip the expectedPrefix from the config URI to get the "filename", and 10433cde86f1SJonathan Doman // append to the CPU's path. 10443cde86f1SJonathan Doman std::string configBaseName = appliedConfigUri.substr(expectedPrefix.size()); 10453cde86f1SJonathan Doman sdbusplus::message::object_path configPath(cpuObjectPath); 10463cde86f1SJonathan Doman configPath /= configBaseName; 10473cde86f1SJonathan Doman 104862598e31SEd Tanous BMCWEB_LOG_INFO("Setting config to {}", configPath.str); 10493cde86f1SJonathan Doman 10503cde86f1SJonathan Doman // Set the property, with handler to check error responses 105187c44966SAsmitha Karunanithi setDbusProperty( 1052e93abac6SGinu George resp, "AppliedOperatingConfig", *controlService, cpuObjectPath, 10539ae226faSGeorge Liu "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig", 1054e93abac6SGinu George "AppliedConfig", configPath); 10553cde86f1SJonathan Doman } 10563cde86f1SJonathan Doman 1057bd79bce8SPatrick Williams inline void handleProcessorHead( 1058bd79bce8SPatrick Williams crow::App& app, const crow::Request& req, 1059ac106bf6SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1060bd79bce8SPatrick Williams const std::string& /* systemName */, const std::string& /* processorId */) 106171a24ca4SNikhil Namjoshi { 1062ac106bf6SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 106371a24ca4SNikhil Namjoshi { 106471a24ca4SNikhil Namjoshi return; 106571a24ca4SNikhil Namjoshi } 1066ac106bf6SEd Tanous asyncResp->res.addHeader( 106771a24ca4SNikhil Namjoshi boost::beast::http::field::link, 106871a24ca4SNikhil Namjoshi "</redfish/v1/JsonSchemas/Processor/Processor.json>; rel=describedby"); 106971a24ca4SNikhil Namjoshi } 107071a24ca4SNikhil Namjoshi 107171a24ca4SNikhil Namjoshi inline void handleProcessorCollectionHead( 107271a24ca4SNikhil Namjoshi crow::App& app, const crow::Request& req, 1073ac106bf6SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 107471a24ca4SNikhil Namjoshi const std::string& /* systemName */) 107571a24ca4SNikhil Namjoshi { 1076ac106bf6SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 107771a24ca4SNikhil Namjoshi { 107871a24ca4SNikhil Namjoshi return; 107971a24ca4SNikhil Namjoshi } 1080ac106bf6SEd Tanous asyncResp->res.addHeader( 108171a24ca4SNikhil Namjoshi boost::beast::http::field::link, 108271a24ca4SNikhil Namjoshi "</redfish/v1/JsonSchemas/ProcessorCollection/ProcessorCollection.json>; rel=describedby"); 108371a24ca4SNikhil Namjoshi } 108471a24ca4SNikhil Namjoshi 1085*98eafce5SGeorge Liu inline void handleProcessorGet( 1086*98eafce5SGeorge Liu App& app, const crow::Request& req, 1087*98eafce5SGeorge Liu const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1088*98eafce5SGeorge Liu const std::string& systemName, const std::string& processorId) 1089*98eafce5SGeorge Liu { 1090*98eafce5SGeorge Liu if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 1091*98eafce5SGeorge Liu { 1092*98eafce5SGeorge Liu return; 1093*98eafce5SGeorge Liu } 1094*98eafce5SGeorge Liu if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 1095*98eafce5SGeorge Liu { 1096*98eafce5SGeorge Liu // Option currently returns no systems. TBD 1097*98eafce5SGeorge Liu messages::resourceNotFound(asyncResp->res, "ComputerSystem", 1098*98eafce5SGeorge Liu systemName); 1099*98eafce5SGeorge Liu return; 1100*98eafce5SGeorge Liu } 1101*98eafce5SGeorge Liu if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 1102*98eafce5SGeorge Liu { 1103*98eafce5SGeorge Liu messages::resourceNotFound(asyncResp->res, "ComputerSystem", 1104*98eafce5SGeorge Liu systemName); 1105*98eafce5SGeorge Liu return; 1106*98eafce5SGeorge Liu } 1107*98eafce5SGeorge Liu 1108*98eafce5SGeorge Liu getProcessorObject( 1109*98eafce5SGeorge Liu asyncResp, processorId, 1110*98eafce5SGeorge Liu std::bind_front(getProcessorData, asyncResp, processorId)); 1111*98eafce5SGeorge Liu } 1112*98eafce5SGeorge Liu 1113*98eafce5SGeorge Liu inline void doPatchProcessor( 1114*98eafce5SGeorge Liu const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1115*98eafce5SGeorge Liu const std::string& processorId, 1116*98eafce5SGeorge Liu const std::optional<std::string>& appliedConfigUri, 1117*98eafce5SGeorge Liu std::optional<bool> locationIndicatorActive, const std::string& objectPath, 1118*98eafce5SGeorge Liu const dbus::utility::MapperServiceMap& serviceMap) 1119*98eafce5SGeorge Liu { 1120*98eafce5SGeorge Liu if (appliedConfigUri) 1121*98eafce5SGeorge Liu { 1122*98eafce5SGeorge Liu patchAppliedOperatingConfig(asyncResp, processorId, *appliedConfigUri, 1123*98eafce5SGeorge Liu objectPath, serviceMap); 1124*98eafce5SGeorge Liu } 1125*98eafce5SGeorge Liu 1126*98eafce5SGeorge Liu if (locationIndicatorActive) 1127*98eafce5SGeorge Liu { 1128*98eafce5SGeorge Liu // Utility function handles reporting errors 1129*98eafce5SGeorge Liu setLocationIndicatorActive(asyncResp, objectPath, 1130*98eafce5SGeorge Liu *locationIndicatorActive); 1131*98eafce5SGeorge Liu } 1132*98eafce5SGeorge Liu } 1133*98eafce5SGeorge Liu 1134*98eafce5SGeorge Liu inline void handleProcessorPatch( 1135*98eafce5SGeorge Liu App& app, const crow::Request& req, 1136*98eafce5SGeorge Liu const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1137*98eafce5SGeorge Liu const std::string& systemName, const std::string& processorId) 1138*98eafce5SGeorge Liu { 1139*98eafce5SGeorge Liu if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 1140*98eafce5SGeorge Liu { 1141*98eafce5SGeorge Liu return; 1142*98eafce5SGeorge Liu } 1143*98eafce5SGeorge Liu if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 1144*98eafce5SGeorge Liu { 1145*98eafce5SGeorge Liu // Option currently returns no systems. TBD 1146*98eafce5SGeorge Liu messages::resourceNotFound(asyncResp->res, "ComputerSystem", 1147*98eafce5SGeorge Liu systemName); 1148*98eafce5SGeorge Liu return; 1149*98eafce5SGeorge Liu } 1150*98eafce5SGeorge Liu if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 1151*98eafce5SGeorge Liu { 1152*98eafce5SGeorge Liu messages::resourceNotFound(asyncResp->res, "ComputerSystem", 1153*98eafce5SGeorge Liu systemName); 1154*98eafce5SGeorge Liu return; 1155*98eafce5SGeorge Liu } 1156*98eafce5SGeorge Liu 1157*98eafce5SGeorge Liu std::optional<std::string> appliedConfigUri; 1158*98eafce5SGeorge Liu std::optional<bool> locationIndicatorActive; 1159*98eafce5SGeorge Liu if (!json_util::readJsonPatch( 1160*98eafce5SGeorge Liu req, asyncResp->res, // 1161*98eafce5SGeorge Liu "AppliedOperatingConfig/@odata.id", appliedConfigUri, // 1162*98eafce5SGeorge Liu "LocationIndicatorActive", locationIndicatorActive // 1163*98eafce5SGeorge Liu )) 1164*98eafce5SGeorge Liu { 1165*98eafce5SGeorge Liu return; 1166*98eafce5SGeorge Liu } 1167*98eafce5SGeorge Liu 1168*98eafce5SGeorge Liu // Check for 404 and find matching D-Bus object, then run 1169*98eafce5SGeorge Liu // property patch handlers if that all succeeds. 1170*98eafce5SGeorge Liu getProcessorObject( 1171*98eafce5SGeorge Liu asyncResp, processorId, 1172*98eafce5SGeorge Liu std::bind_front(doPatchProcessor, asyncResp, processorId, 1173*98eafce5SGeorge Liu appliedConfigUri, locationIndicatorActive)); 1174*98eafce5SGeorge Liu } 1175*98eafce5SGeorge Liu 11767e860f15SJohn Edward Broadbent inline void requestRoutesOperatingConfigCollection(App& app) 1177dba0c291SJonathan Doman { 11787f3e84a1SEd Tanous BMCWEB_ROUTE(app, 11797f3e84a1SEd Tanous "/redfish/v1/Systems/<str>/Processors/<str>/OperatingConfigs/") 1180ed398213SEd Tanous .privileges(redfish::privileges::getOperatingConfigCollection) 1181bd79bce8SPatrick Williams .methods( 1182bd79bce8SPatrick Williams boost::beast::http::verb:: 1183bd79bce8SPatrick Williams get)([&app](const crow::Request& req, 118445ca1b86SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1185bd79bce8SPatrick Williams const std::string& systemName, 1186bd79bce8SPatrick Williams const std::string& cpuName) { 11873ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 118845ca1b86SEd Tanous { 118945ca1b86SEd Tanous return; 119045ca1b86SEd Tanous } 11917f3e84a1SEd Tanous 119225b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 11937f3e84a1SEd Tanous { 11947f3e84a1SEd Tanous // Option currently returns no systems. TBD 11957f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 11967f3e84a1SEd Tanous systemName); 11977f3e84a1SEd Tanous return; 11987f3e84a1SEd Tanous } 11997f3e84a1SEd Tanous 1200253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 12017f3e84a1SEd Tanous { 12027f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 12037f3e84a1SEd Tanous systemName); 12047f3e84a1SEd Tanous return; 12057f3e84a1SEd Tanous } 12068d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.type"] = 1207dba0c291SJonathan Doman "#OperatingConfigCollection.OperatingConfigCollection"; 1208ef4c65b7SEd Tanous asyncResp->res.jsonValue["@odata.id"] = boost::urls::format( 1209253f11b8SEd Tanous "/redfish/v1/Systems/{}/Processors/{}/OperatingConfigs", 1210253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME, cpuName); 12110fda0f12SGeorge Liu asyncResp->res.jsonValue["Name"] = "Operating Config Collection"; 1212dba0c291SJonathan Doman 12137e860f15SJohn Edward Broadbent // First find the matching CPU object so we know how to 12147e860f15SJohn Edward Broadbent // constrain our search for related Config objects. 12157a1dbc48SGeorge Liu const std::array<std::string_view, 1> interfaces = { 12167a1dbc48SGeorge Liu "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig"}; 12177a1dbc48SGeorge Liu dbus::utility::getSubTreePaths( 12187a1dbc48SGeorge Liu "/xyz/openbmc_project/inventory", 0, interfaces, 1219bd79bce8SPatrick Williams [asyncResp, 1220bd79bce8SPatrick Williams cpuName](const boost::system::error_code& ec, 1221bd79bce8SPatrick Williams const dbus::utility::MapperGetSubTreePathsResponse& 1222bd79bce8SPatrick Williams objects) { 1223dba0c291SJonathan Doman if (ec) 1224dba0c291SJonathan Doman { 1225bd79bce8SPatrick Williams BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec, 1226bd79bce8SPatrick Williams ec.message()); 1227dba0c291SJonathan Doman messages::internalError(asyncResp->res); 1228dba0c291SJonathan Doman return; 1229dba0c291SJonathan Doman } 1230dba0c291SJonathan Doman 1231dba0c291SJonathan Doman for (const std::string& object : objects) 1232dba0c291SJonathan Doman { 123311ba3979SEd Tanous if (!object.ends_with(cpuName)) 1234dba0c291SJonathan Doman { 1235dba0c291SJonathan Doman continue; 1236dba0c291SJonathan Doman } 1237dba0c291SJonathan Doman 12387e860f15SJohn Edward Broadbent // Not expected that there will be multiple matching 12397e860f15SJohn Edward Broadbent // CPU objects, but if there are just use the first 12407e860f15SJohn Edward Broadbent // one. 1241dba0c291SJonathan Doman 12427e860f15SJohn Edward Broadbent // Use the common search routine to construct the 12437e860f15SJohn Edward Broadbent // Collection of all Config objects under this CPU. 12447a1dbc48SGeorge Liu constexpr std::array<std::string_view, 1> interface{ 12455a39f77aSPatrick Williams "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig"}; 1246dba0c291SJonathan Doman collection_util::getCollectionMembers( 1247dba0c291SJonathan Doman asyncResp, 1248ef4c65b7SEd Tanous boost::urls::format( 1249253f11b8SEd Tanous "/redfish/v1/Systems/{}/Processors/{}/OperatingConfigs", 1250253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME, cpuName), 125136b5f1edSLakshmi Yadlapati interface, object); 1252dba0c291SJonathan Doman return; 1253dba0c291SJonathan Doman } 12547a1dbc48SGeorge Liu }); 12557e860f15SJohn Edward Broadbent }); 1256dba0c291SJonathan Doman } 1257dba0c291SJonathan Doman 12587e860f15SJohn Edward Broadbent inline void requestRoutesOperatingConfig(App& app) 1259dba0c291SJonathan Doman { 12607e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 12617e860f15SJohn Edward Broadbent app, 12627f3e84a1SEd Tanous "/redfish/v1/Systems/<str>/Processors/<str>/OperatingConfigs/<str>/") 1263ed398213SEd Tanous .privileges(redfish::privileges::getOperatingConfig) 1264bd79bce8SPatrick Williams .methods( 1265bd79bce8SPatrick Williams boost::beast::http::verb:: 1266bd79bce8SPatrick Williams get)([&app](const crow::Request& req, 126745ca1b86SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1268bd79bce8SPatrick Williams const std::string& systemName, 1269bd79bce8SPatrick Williams const std::string& cpuName, 12707f3e84a1SEd Tanous const std::string& configName) { 12713ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 127245ca1b86SEd Tanous { 127345ca1b86SEd Tanous return; 127445ca1b86SEd Tanous } 127525b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 12767f3e84a1SEd Tanous { 12777f3e84a1SEd Tanous // Option currently returns no systems. TBD 12787f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 12797f3e84a1SEd Tanous systemName); 12807f3e84a1SEd Tanous return; 12817f3e84a1SEd Tanous } 12827f3e84a1SEd Tanous 1283253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 12847f3e84a1SEd Tanous { 12857f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 12867f3e84a1SEd Tanous systemName); 12877f3e84a1SEd Tanous return; 12887f3e84a1SEd Tanous } 12897e860f15SJohn Edward Broadbent // Ask for all objects implementing OperatingConfig so we can search 12907e860f15SJohn Edward Broadbent // for one with a matching name 1291e99073f5SGeorge Liu constexpr std::array<std::string_view, 1> interfaces = { 1292e99073f5SGeorge Liu "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig"}; 1293e99073f5SGeorge Liu dbus::utility::getSubTree( 1294e99073f5SGeorge Liu "/xyz/openbmc_project/inventory", 0, interfaces, 129539662a3bSEd Tanous [asyncResp, cpuName, configName]( 1296e99073f5SGeorge Liu const boost::system::error_code& ec, 12975df6eda2SShantappa Teekappanavar const dbus::utility::MapperGetSubTreeResponse& subtree) { 1298dba0c291SJonathan Doman if (ec) 1299dba0c291SJonathan Doman { 1300bd79bce8SPatrick Williams BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec, 1301bd79bce8SPatrick Williams ec.message()); 1302dba0c291SJonathan Doman messages::internalError(asyncResp->res); 1303dba0c291SJonathan Doman return; 1304dba0c291SJonathan Doman } 1305bd79bce8SPatrick Williams const std::string expectedEnding = 1306bd79bce8SPatrick Williams cpuName + '/' + configName; 1307dba0c291SJonathan Doman for (const auto& [objectPath, serviceMap] : subtree) 1308dba0c291SJonathan Doman { 1309dba0c291SJonathan Doman // Ignore any configs without matching cpuX/configY 1310bd79bce8SPatrick Williams if (!objectPath.ends_with(expectedEnding) || 1311bd79bce8SPatrick Williams serviceMap.empty()) 1312dba0c291SJonathan Doman { 1313dba0c291SJonathan Doman continue; 1314dba0c291SJonathan Doman } 1315dba0c291SJonathan Doman 1316dba0c291SJonathan Doman nlohmann::json& json = asyncResp->res.jsonValue; 1317bd79bce8SPatrick Williams json["@odata.type"] = 1318bd79bce8SPatrick Williams "#OperatingConfig.v1_0_0.OperatingConfig"; 1319ef4c65b7SEd Tanous json["@odata.id"] = boost::urls::format( 1320253f11b8SEd Tanous "/redfish/v1/Systems/{}/Processors/{}/OperatingConfigs/{}", 1321bd79bce8SPatrick Williams BMCWEB_REDFISH_SYSTEM_URI_NAME, cpuName, 1322bd79bce8SPatrick Williams configName); 1323dba0c291SJonathan Doman json["Name"] = "Processor Profile"; 1324dba0c291SJonathan Doman json["Id"] = configName; 1325dba0c291SJonathan Doman 1326dba0c291SJonathan Doman // Just use the first implementation of the object - not 13277e860f15SJohn Edward Broadbent // expected that there would be multiple matching 13287e860f15SJohn Edward Broadbent // services 1329bd79bce8SPatrick Williams getOperatingConfigData( 1330bd79bce8SPatrick Williams asyncResp, serviceMap.begin()->first, objectPath); 1331dba0c291SJonathan Doman return; 1332dba0c291SJonathan Doman } 1333bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, 1334bd79bce8SPatrick Williams "OperatingConfig", configName); 1335e99073f5SGeorge Liu }); 13367e860f15SJohn Edward Broadbent }); 1337ac6a4445SGunnar Mills } 1338ac6a4445SGunnar Mills 13397e860f15SJohn Edward Broadbent inline void requestRoutesProcessorCollection(App& app) 13407e860f15SJohn Edward Broadbent { 1341ac6a4445SGunnar Mills /** 1342ac6a4445SGunnar Mills * Functions triggers appropriate requests on DBus 1343ac6a4445SGunnar Mills */ 134422d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/") 134571a24ca4SNikhil Namjoshi .privileges(redfish::privileges::headProcessorCollection) 134671a24ca4SNikhil Namjoshi .methods(boost::beast::http::verb::head)( 134771a24ca4SNikhil Namjoshi std::bind_front(handleProcessorCollectionHead, std::ref(app))); 134871a24ca4SNikhil Namjoshi 134971a24ca4SNikhil Namjoshi BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/") 1350ed398213SEd Tanous .privileges(redfish::privileges::getProcessorCollection) 1351bd79bce8SPatrick Williams .methods( 1352bd79bce8SPatrick Williams boost::beast::http::verb:: 1353bd79bce8SPatrick Williams get)([&app](const crow::Request& req, 135422d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 135522d268cbSEd Tanous const std::string& systemName) { 13563ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 135745ca1b86SEd Tanous { 135845ca1b86SEd Tanous return; 135945ca1b86SEd Tanous } 136025b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 13617f3e84a1SEd Tanous { 13627f3e84a1SEd Tanous // Option currently returns no systems. TBD 13637f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 13647f3e84a1SEd Tanous systemName); 13657f3e84a1SEd Tanous return; 13667f3e84a1SEd Tanous } 13677f3e84a1SEd Tanous 1368253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 136922d268cbSEd Tanous { 137022d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 137122d268cbSEd Tanous systemName); 137222d268cbSEd Tanous return; 137322d268cbSEd Tanous } 137422d268cbSEd Tanous 137571a24ca4SNikhil Namjoshi asyncResp->res.addHeader( 137671a24ca4SNikhil Namjoshi boost::beast::http::field::link, 137771a24ca4SNikhil Namjoshi "</redfish/v1/JsonSchemas/ProcessorCollection/ProcessorCollection.json>; rel=describedby"); 137871a24ca4SNikhil Namjoshi 13798d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.type"] = 1380ac6a4445SGunnar Mills "#ProcessorCollection.ProcessorCollection"; 13818d1b46d7Szhanghch05 asyncResp->res.jsonValue["Name"] = "Processor Collection"; 1382ac6a4445SGunnar Mills 13838d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.id"] = 1384253f11b8SEd Tanous std::format("/redfish/v1/Systems/{}/Processors", 1385253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 1386ac6a4445SGunnar Mills 138705030b8eSGunnar Mills collection_util::getCollectionMembers( 1388ae9031f0SWilly Tu asyncResp, 1389253f11b8SEd Tanous boost::urls::format("/redfish/v1/Systems/{}/Processors", 1390253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME), 139136b5f1edSLakshmi Yadlapati processorInterfaces, "/xyz/openbmc_project/inventory"); 13927e860f15SJohn Edward Broadbent }); 1393ac6a4445SGunnar Mills } 1394ac6a4445SGunnar Mills 13957e860f15SJohn Edward Broadbent inline void requestRoutesProcessor(App& app) 13967e860f15SJohn Edward Broadbent { 1397ac6a4445SGunnar Mills /** 1398ac6a4445SGunnar Mills * Functions triggers appropriate requests on DBus 1399ac6a4445SGunnar Mills */ 14007e860f15SJohn Edward Broadbent 140122d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/<str>/") 140271a24ca4SNikhil Namjoshi .privileges(redfish::privileges::headProcessor) 140371a24ca4SNikhil Namjoshi .methods(boost::beast::http::verb::head)( 140471a24ca4SNikhil Namjoshi std::bind_front(handleProcessorHead, std::ref(app))); 140571a24ca4SNikhil Namjoshi 140671a24ca4SNikhil Namjoshi BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/<str>/") 1407ed398213SEd Tanous .privileges(redfish::privileges::getProcessor) 1408*98eafce5SGeorge Liu .methods(boost::beast::http::verb::get)( 1409*98eafce5SGeorge Liu std::bind_front(handleProcessorGet, std::ref(app))); 14103cde86f1SJonathan Doman 141122d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/<str>/") 1412ed398213SEd Tanous .privileges(redfish::privileges::patchProcessor) 14137e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::patch)( 1414*98eafce5SGeorge Liu std::bind_front(handleProcessorPatch, std::ref(app))); 14153cde86f1SJonathan Doman } 1416ac6a4445SGunnar Mills 1417ac6a4445SGunnar Mills } // namespace redfish 1418