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" 107a1dbc48SGeorge Liu #include "dbus_utility.hpp" 111e1e598dSJonathan Doman #include "error_messages.hpp" 12dfbf7de5SChris Cain #include "generated/enums/processor.hpp" 13539d8c6bSEd Tanous #include "generated/enums/resource.hpp" 14d7857201SEd Tanous #include "http_request.hpp" 15d7857201SEd Tanous #include "logging.hpp" 163ccb3adbSEd Tanous #include "query.hpp" 173ccb3adbSEd Tanous #include "registries/privilege_registry.hpp" 183ccb3adbSEd Tanous #include "utils/collection.hpp" 193ccb3adbSEd Tanous #include "utils/dbus_utils.hpp" 20d7857201SEd Tanous #include "utils/hex_utils.hpp" 213ccb3adbSEd Tanous #include "utils/json_utils.hpp" 22ac6a4445SGunnar Mills 23d7857201SEd Tanous #include <boost/beast/http/field.hpp> 24d7857201SEd Tanous #include <boost/beast/http/verb.hpp> 25e99073f5SGeorge Liu #include <boost/system/error_code.hpp> 26ef4c65b7SEd Tanous #include <boost/url/format.hpp> 27dba0c291SJonathan Doman #include <sdbusplus/message/native_types.hpp> 28351053f2SKrzysztof Grobelny #include <sdbusplus/unpack_properties.hpp> 29ac6a4445SGunnar Mills 30d7857201SEd Tanous #include <algorithm> 317a1dbc48SGeorge Liu #include <array> 32d7857201SEd Tanous #include <cstddef> 33d7857201SEd Tanous #include <cstdint> 34d7857201SEd Tanous #include <format> 35d7857201SEd Tanous #include <functional> 36b9d679d1SMichael Shen #include <limits> 37d7857201SEd Tanous #include <memory> 38d7857201SEd Tanous #include <optional> 393544d2a7SEd Tanous #include <ranges> 403c569218SEd Tanous #include <string> 417a1dbc48SGeorge Liu #include <string_view> 42d7857201SEd Tanous #include <tuple> 43d7857201SEd Tanous #include <utility> 44d7857201SEd Tanous #include <variant> 45d7857201SEd Tanous #include <vector> 467a1dbc48SGeorge Liu 47ac6a4445SGunnar Mills namespace redfish 48ac6a4445SGunnar Mills { 49ac6a4445SGunnar Mills 50c951448aSJonathan Doman // Interfaces which imply a D-Bus object represents a Processor 517a1dbc48SGeorge Liu constexpr std::array<std::string_view, 2> processorInterfaces = { 52c951448aSJonathan Doman "xyz.openbmc_project.Inventory.Item.Cpu", 53c951448aSJonathan Doman "xyz.openbmc_project.Inventory.Item.Accelerator"}; 542bab9831SJonathan Doman 5571b82f26SSharad Yadav /** 5671b82f26SSharad Yadav * @brief Fill out uuid info of a processor by 5771b82f26SSharad Yadav * requesting data from the given D-Bus object. 5871b82f26SSharad Yadav * 59ac106bf6SEd Tanous * @param[in,out] asyncResp Async HTTP response. 6071b82f26SSharad Yadav * @param[in] service D-Bus service to query. 6171b82f26SSharad Yadav * @param[in] objPath D-Bus object to query. 6271b82f26SSharad Yadav */ 63ac106bf6SEd Tanous inline void getProcessorUUID(std::shared_ptr<bmcweb::AsyncResp> asyncResp, 6471b82f26SSharad Yadav const std::string& service, 6571b82f26SSharad Yadav const std::string& objPath) 6671b82f26SSharad Yadav { 6762598e31SEd Tanous BMCWEB_LOG_DEBUG("Get Processor UUID"); 68deae6a78SEd Tanous dbus::utility::getProperty<std::string>( 69deae6a78SEd Tanous service, objPath, "xyz.openbmc_project.Common.UUID", "UUID", 70ac106bf6SEd Tanous [objPath, asyncResp{std::move(asyncResp)}]( 71ac106bf6SEd Tanous const boost::system::error_code& ec, const std::string& property) { 7271b82f26SSharad Yadav if (ec) 7371b82f26SSharad Yadav { 7462598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error"); 75ac106bf6SEd Tanous messages::internalError(asyncResp->res); 7671b82f26SSharad Yadav return; 7771b82f26SSharad Yadav } 78ac106bf6SEd Tanous asyncResp->res.jsonValue["UUID"] = property; 791e1e598dSJonathan Doman }); 8071b82f26SSharad Yadav } 8171b82f26SSharad Yadav 82711ac7a9SEd Tanous inline void getCpuDataByInterface( 83ac106bf6SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 8480f79a40SMichael Shen const dbus::utility::DBusInterfacesMap& cpuInterfacesProperties) 85ac6a4445SGunnar Mills { 8662598e31SEd Tanous BMCWEB_LOG_DEBUG("Get CPU resources by interface."); 87ac6a4445SGunnar Mills 88a1649ec6SChicago Duan // Set the default value of state 89539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled; 90539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["Health"] = resource::Health::OK; 91ac6a4445SGunnar Mills 92ac6a4445SGunnar Mills for (const auto& interface : cpuInterfacesProperties) 93ac6a4445SGunnar Mills { 94ac6a4445SGunnar Mills for (const auto& property : interface.second) 95ac6a4445SGunnar Mills { 96a1649ec6SChicago Duan if (property.first == "Present") 97ac6a4445SGunnar Mills { 98a1649ec6SChicago Duan const bool* cpuPresent = std::get_if<bool>(&property.second); 99a1649ec6SChicago Duan if (cpuPresent == nullptr) 100ac6a4445SGunnar Mills { 101ac6a4445SGunnar Mills // Important property not in desired type 102ac106bf6SEd Tanous messages::internalError(asyncResp->res); 103ac6a4445SGunnar Mills return; 104ac6a4445SGunnar Mills } 105e05aec50SEd Tanous if (!*cpuPresent) 106ac6a4445SGunnar Mills { 107a1649ec6SChicago Duan // Slot is not populated 108539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["State"] = 109539d8c6bSEd Tanous resource::State::Absent; 110a1649ec6SChicago Duan } 111a1649ec6SChicago Duan } 112a1649ec6SChicago Duan else if (property.first == "Functional") 113a1649ec6SChicago Duan { 114a1649ec6SChicago Duan const bool* cpuFunctional = std::get_if<bool>(&property.second); 115a1649ec6SChicago Duan if (cpuFunctional == nullptr) 116a1649ec6SChicago Duan { 117ac106bf6SEd Tanous messages::internalError(asyncResp->res); 118ac6a4445SGunnar Mills return; 119ac6a4445SGunnar Mills } 120e05aec50SEd Tanous if (!*cpuFunctional) 121a1649ec6SChicago Duan { 122539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["Health"] = 123539d8c6bSEd Tanous resource::Health::Critical; 124a1649ec6SChicago Duan } 125a1649ec6SChicago Duan } 126a1649ec6SChicago Duan else if (property.first == "CoreCount") 127a1649ec6SChicago Duan { 128a1649ec6SChicago Duan const uint16_t* coresCount = 129a1649ec6SChicago Duan std::get_if<uint16_t>(&property.second); 130a1649ec6SChicago Duan if (coresCount == nullptr) 131a1649ec6SChicago Duan { 132ac106bf6SEd Tanous messages::internalError(asyncResp->res); 133a1649ec6SChicago Duan return; 134a1649ec6SChicago Duan } 135ac106bf6SEd Tanous asyncResp->res.jsonValue["TotalCores"] = *coresCount; 136ac6a4445SGunnar Mills } 137dc3fa667SJonathan Doman else if (property.first == "MaxSpeedInMhz") 138dc3fa667SJonathan Doman { 139dc3fa667SJonathan Doman const uint32_t* value = std::get_if<uint32_t>(&property.second); 140dc3fa667SJonathan Doman if (value != nullptr) 141dc3fa667SJonathan Doman { 142ac106bf6SEd Tanous asyncResp->res.jsonValue["MaxSpeedMHz"] = *value; 143dc3fa667SJonathan Doman } 144dc3fa667SJonathan Doman } 145ac6a4445SGunnar Mills else if (property.first == "Socket") 146ac6a4445SGunnar Mills { 147ac6a4445SGunnar Mills const std::string* value = 148ac6a4445SGunnar Mills std::get_if<std::string>(&property.second); 149ac6a4445SGunnar Mills if (value != nullptr) 150ac6a4445SGunnar Mills { 151ac106bf6SEd Tanous asyncResp->res.jsonValue["Socket"] = *value; 152ac6a4445SGunnar Mills } 153ac6a4445SGunnar Mills } 154ac6a4445SGunnar Mills else if (property.first == "ThreadCount") 155ac6a4445SGunnar Mills { 156dc3fa667SJonathan Doman const uint16_t* value = std::get_if<uint16_t>(&property.second); 157ac6a4445SGunnar Mills if (value != nullptr) 158ac6a4445SGunnar Mills { 159ac106bf6SEd Tanous asyncResp->res.jsonValue["TotalThreads"] = *value; 160ac6a4445SGunnar Mills } 161ac6a4445SGunnar Mills } 1621930fbd4SBrandon Kim else if (property.first == "EffectiveFamily") 163ac6a4445SGunnar Mills { 1641930fbd4SBrandon Kim const uint16_t* value = std::get_if<uint16_t>(&property.second); 1656169de2cSBrad Bishop if (value != nullptr && *value != 2) 166ac6a4445SGunnar Mills { 167ac106bf6SEd Tanous asyncResp->res.jsonValue["ProcessorId"]["EffectiveFamily"] = 168866e4862SEd Tanous "0x" + intToHexString(*value, 4); 169ac6a4445SGunnar Mills } 170ac6a4445SGunnar Mills } 1711930fbd4SBrandon Kim else if (property.first == "EffectiveModel") 1721930fbd4SBrandon Kim { 1731930fbd4SBrandon Kim const uint16_t* value = std::get_if<uint16_t>(&property.second); 1741930fbd4SBrandon Kim if (value == nullptr) 1751930fbd4SBrandon Kim { 176ac106bf6SEd Tanous messages::internalError(asyncResp->res); 1771930fbd4SBrandon Kim return; 1781930fbd4SBrandon Kim } 1796169de2cSBrad Bishop if (*value != 0) 1806169de2cSBrad Bishop { 181ac106bf6SEd Tanous asyncResp->res.jsonValue["ProcessorId"]["EffectiveModel"] = 182866e4862SEd Tanous "0x" + intToHexString(*value, 4); 1831930fbd4SBrandon Kim } 1846169de2cSBrad Bishop } 185ac6a4445SGunnar Mills else if (property.first == "Id") 186ac6a4445SGunnar Mills { 187ac6a4445SGunnar Mills const uint64_t* value = std::get_if<uint64_t>(&property.second); 188ac6a4445SGunnar Mills if (value != nullptr && *value != 0) 189ac6a4445SGunnar Mills { 190ac106bf6SEd Tanous asyncResp->res 191ac6a4445SGunnar Mills .jsonValue["ProcessorId"]["IdentificationRegisters"] = 192866e4862SEd Tanous "0x" + intToHexString(*value, 16); 193ac6a4445SGunnar Mills } 194ac6a4445SGunnar Mills } 1951930fbd4SBrandon Kim else if (property.first == "Microcode") 1961930fbd4SBrandon Kim { 1971930fbd4SBrandon Kim const uint32_t* value = std::get_if<uint32_t>(&property.second); 1981930fbd4SBrandon Kim if (value == nullptr) 1991930fbd4SBrandon Kim { 200ac106bf6SEd Tanous messages::internalError(asyncResp->res); 2011930fbd4SBrandon Kim return; 2021930fbd4SBrandon Kim } 2036169de2cSBrad Bishop if (*value != 0) 2046169de2cSBrad Bishop { 205ac106bf6SEd Tanous asyncResp->res.jsonValue["ProcessorId"]["MicrocodeInfo"] = 206866e4862SEd Tanous "0x" + intToHexString(*value, 8); 2071930fbd4SBrandon Kim } 2086169de2cSBrad Bishop } 2091930fbd4SBrandon Kim else if (property.first == "Step") 2101930fbd4SBrandon Kim { 2111930fbd4SBrandon Kim const uint16_t* value = std::get_if<uint16_t>(&property.second); 2121930fbd4SBrandon Kim if (value == nullptr) 2131930fbd4SBrandon Kim { 214ac106bf6SEd Tanous messages::internalError(asyncResp->res); 2151930fbd4SBrandon Kim return; 2161930fbd4SBrandon Kim } 217b9d679d1SMichael Shen if (*value != std::numeric_limits<uint16_t>::max()) 2186169de2cSBrad Bishop { 219ac106bf6SEd Tanous asyncResp->res.jsonValue["ProcessorId"]["Step"] = 220866e4862SEd Tanous "0x" + intToHexString(*value, 4); 2211930fbd4SBrandon Kim } 222ac6a4445SGunnar Mills } 223ac6a4445SGunnar Mills } 224ac6a4445SGunnar Mills } 2256169de2cSBrad Bishop } 226ac6a4445SGunnar Mills 227bd79bce8SPatrick Williams inline void getCpuDataByService( 228bd79bce8SPatrick Williams std::shared_ptr<bmcweb::AsyncResp> asyncResp, const std::string& cpuId, 229bd79bce8SPatrick Williams const std::string& service, const std::string& objPath) 230ac6a4445SGunnar Mills { 23162598e31SEd Tanous BMCWEB_LOG_DEBUG("Get available system cpu resources by service."); 232ac6a4445SGunnar Mills 2335eb468daSGeorge Liu sdbusplus::message::object_path path("/xyz/openbmc_project/inventory"); 2345eb468daSGeorge Liu dbus::utility::getManagedObjects( 2355eb468daSGeorge Liu service, path, 236ac106bf6SEd Tanous [cpuId, service, objPath, asyncResp{std::move(asyncResp)}]( 2375e7e2dc5SEd Tanous const boost::system::error_code& ec, 238ac6a4445SGunnar Mills const dbus::utility::ManagedObjectType& dbusData) { 239ac6a4445SGunnar Mills if (ec) 240ac6a4445SGunnar Mills { 24162598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error"); 242ac106bf6SEd Tanous messages::internalError(asyncResp->res); 243ac6a4445SGunnar Mills return; 244ac6a4445SGunnar Mills } 245ac106bf6SEd Tanous asyncResp->res.jsonValue["Id"] = cpuId; 246ac106bf6SEd Tanous asyncResp->res.jsonValue["Name"] = "Processor"; 247539d8c6bSEd Tanous asyncResp->res.jsonValue["ProcessorType"] = 248539d8c6bSEd Tanous processor::ProcessorType::CPU; 249ac6a4445SGunnar Mills 250ac6a4445SGunnar Mills for (const auto& object : dbusData) 251ac6a4445SGunnar Mills { 252ac6a4445SGunnar Mills if (object.first.str == objPath) 253ac6a4445SGunnar Mills { 254ac106bf6SEd Tanous getCpuDataByInterface(asyncResp, object.second); 255ac6a4445SGunnar Mills } 256ac6a4445SGunnar Mills } 257ac6a4445SGunnar Mills return; 2585eb468daSGeorge Liu }); 259ac6a4445SGunnar Mills } 260ac6a4445SGunnar Mills 261dfbf7de5SChris Cain /** 262dfbf7de5SChris Cain * @brief Translates throttle cause DBUS property to redfish. 263dfbf7de5SChris Cain * 264dfbf7de5SChris Cain * @param[in] dbusSource The throttle cause from DBUS 265dfbf7de5SChris Cain * 266dfbf7de5SChris Cain * @return Returns as a string, the throttle cause in Redfish terms. If 267dfbf7de5SChris Cain * translation cannot be done, returns "Unknown" throttle reason. 268dfbf7de5SChris Cain */ 269*504af5a0SPatrick Williams inline processor::ThrottleCause dbusToRfThrottleCause( 270*504af5a0SPatrick Williams const std::string& dbusSource) 271dfbf7de5SChris Cain { 272dfbf7de5SChris Cain if (dbusSource == 273dfbf7de5SChris Cain "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.ClockLimit") 274dfbf7de5SChris Cain { 275dfbf7de5SChris Cain return processor::ThrottleCause::ClockLimit; 276dfbf7de5SChris Cain } 277dfbf7de5SChris Cain if (dbusSource == 278dfbf7de5SChris Cain "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.ManagementDetectedFault") 279dfbf7de5SChris Cain { 280dfbf7de5SChris Cain return processor::ThrottleCause::ManagementDetectedFault; 281dfbf7de5SChris Cain } 282dfbf7de5SChris Cain if (dbusSource == 283dfbf7de5SChris Cain "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.PowerLimit") 284dfbf7de5SChris Cain { 285dfbf7de5SChris Cain return processor::ThrottleCause::PowerLimit; 286dfbf7de5SChris Cain } 287dfbf7de5SChris Cain if (dbusSource == 288dfbf7de5SChris Cain "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.ThermalLimit") 289dfbf7de5SChris Cain { 290dfbf7de5SChris Cain return processor::ThrottleCause::ThermalLimit; 291dfbf7de5SChris Cain } 292dfbf7de5SChris Cain if (dbusSource == 293dfbf7de5SChris Cain "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.Unknown") 294dfbf7de5SChris Cain { 295dfbf7de5SChris Cain return processor::ThrottleCause::Unknown; 296dfbf7de5SChris Cain } 297dfbf7de5SChris Cain return processor::ThrottleCause::Invalid; 298dfbf7de5SChris Cain } 299dfbf7de5SChris Cain 300*504af5a0SPatrick Williams inline void readThrottleProperties( 301*504af5a0SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 302dfbf7de5SChris Cain const boost::system::error_code& ec, 303dfbf7de5SChris Cain const dbus::utility::DBusPropertiesMap& properties) 304dfbf7de5SChris Cain { 305dfbf7de5SChris Cain if (ec) 306dfbf7de5SChris Cain { 30762598e31SEd Tanous BMCWEB_LOG_ERROR("Processor Throttle getAllProperties error {}", ec); 308ac106bf6SEd Tanous messages::internalError(asyncResp->res); 309dfbf7de5SChris Cain return; 310dfbf7de5SChris Cain } 311dfbf7de5SChris Cain 312dfbf7de5SChris Cain const bool* status = nullptr; 313dfbf7de5SChris Cain const std::vector<std::string>* causes = nullptr; 314dfbf7de5SChris Cain 315dfbf7de5SChris Cain if (!sdbusplus::unpackPropertiesNoThrow(dbus_utils::UnpackErrorPrinter(), 316dfbf7de5SChris Cain properties, "Throttled", status, 317dfbf7de5SChris Cain "ThrottleCauses", causes)) 318dfbf7de5SChris Cain { 319ac106bf6SEd Tanous messages::internalError(asyncResp->res); 320dfbf7de5SChris Cain return; 321dfbf7de5SChris Cain } 322dfbf7de5SChris Cain 323ac106bf6SEd Tanous asyncResp->res.jsonValue["Throttled"] = *status; 324dfbf7de5SChris Cain nlohmann::json::array_t rCauses; 325dfbf7de5SChris Cain for (const std::string& cause : *causes) 326dfbf7de5SChris Cain { 327dfbf7de5SChris Cain processor::ThrottleCause rfCause = dbusToRfThrottleCause(cause); 328dfbf7de5SChris Cain if (rfCause == processor::ThrottleCause::Invalid) 329dfbf7de5SChris Cain { 330ac106bf6SEd Tanous messages::internalError(asyncResp->res); 331dfbf7de5SChris Cain return; 332dfbf7de5SChris Cain } 333dfbf7de5SChris Cain 334dfbf7de5SChris Cain rCauses.emplace_back(rfCause); 335dfbf7de5SChris Cain } 336ac106bf6SEd Tanous asyncResp->res.jsonValue["ThrottleCauses"] = std::move(rCauses); 337dfbf7de5SChris Cain } 338dfbf7de5SChris Cain 339bd79bce8SPatrick Williams inline void getThrottleProperties( 340bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 341bd79bce8SPatrick Williams const std::string& service, const std::string& objectPath) 342dfbf7de5SChris Cain { 34362598e31SEd Tanous BMCWEB_LOG_DEBUG("Get processor throttle resources"); 344dfbf7de5SChris Cain 345deae6a78SEd Tanous dbus::utility::getAllProperties( 346deae6a78SEd Tanous service, objectPath, "xyz.openbmc_project.Control.Power.Throttle", 347ac106bf6SEd Tanous [asyncResp](const boost::system::error_code& ec, 348dfbf7de5SChris Cain const dbus::utility::DBusPropertiesMap& properties) { 349ac106bf6SEd Tanous readThrottleProperties(asyncResp, ec, properties); 350dfbf7de5SChris Cain }); 351dfbf7de5SChris Cain } 352dfbf7de5SChris Cain 353ac106bf6SEd Tanous inline void getCpuAssetData(std::shared_ptr<bmcweb::AsyncResp> asyncResp, 354ac6a4445SGunnar Mills const std::string& service, 355ac6a4445SGunnar Mills const std::string& objPath) 356ac6a4445SGunnar Mills { 35762598e31SEd Tanous BMCWEB_LOG_DEBUG("Get Cpu Asset Data"); 358deae6a78SEd Tanous dbus::utility::getAllProperties( 359deae6a78SEd Tanous service, objPath, "xyz.openbmc_project.Inventory.Decorator.Asset", 360ac106bf6SEd Tanous [objPath, asyncResp{std::move(asyncResp)}]( 3615e7e2dc5SEd Tanous const boost::system::error_code& ec, 362351053f2SKrzysztof Grobelny const dbus::utility::DBusPropertiesMap& properties) { 363ac6a4445SGunnar Mills if (ec) 364ac6a4445SGunnar Mills { 36562598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error"); 366ac106bf6SEd Tanous messages::internalError(asyncResp->res); 367ac6a4445SGunnar Mills return; 368ac6a4445SGunnar Mills } 369ac6a4445SGunnar Mills 370351053f2SKrzysztof Grobelny const std::string* serialNumber = nullptr; 371351053f2SKrzysztof Grobelny const std::string* model = nullptr; 372351053f2SKrzysztof Grobelny const std::string* manufacturer = nullptr; 373351053f2SKrzysztof Grobelny const std::string* partNumber = nullptr; 374351053f2SKrzysztof Grobelny const std::string* sparePartNumber = nullptr; 375351053f2SKrzysztof Grobelny 376351053f2SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 377351053f2SKrzysztof Grobelny dbus_utils::UnpackErrorPrinter(), properties, "SerialNumber", 378351053f2SKrzysztof Grobelny serialNumber, "Model", model, "Manufacturer", manufacturer, 379351053f2SKrzysztof Grobelny "PartNumber", partNumber, "SparePartNumber", sparePartNumber); 380351053f2SKrzysztof Grobelny 381351053f2SKrzysztof Grobelny if (!success) 382ac6a4445SGunnar Mills { 383ac106bf6SEd Tanous messages::internalError(asyncResp->res); 384351053f2SKrzysztof Grobelny return; 385ac6a4445SGunnar Mills } 386351053f2SKrzysztof Grobelny 387351053f2SKrzysztof Grobelny if (serialNumber != nullptr && !serialNumber->empty()) 388ac6a4445SGunnar Mills { 389ac106bf6SEd Tanous asyncResp->res.jsonValue["SerialNumber"] = *serialNumber; 390351053f2SKrzysztof Grobelny } 391351053f2SKrzysztof Grobelny 392351053f2SKrzysztof Grobelny if ((model != nullptr) && !model->empty()) 393ac6a4445SGunnar Mills { 394ac106bf6SEd Tanous asyncResp->res.jsonValue["Model"] = *model; 395ac6a4445SGunnar Mills } 396ac6a4445SGunnar Mills 397351053f2SKrzysztof Grobelny if (manufacturer != nullptr) 398ac6a4445SGunnar Mills { 399ac106bf6SEd Tanous asyncResp->res.jsonValue["Manufacturer"] = *manufacturer; 400ac6a4445SGunnar Mills 401ac6a4445SGunnar Mills // Otherwise would be unexpected. 402351053f2SKrzysztof Grobelny if (manufacturer->find("Intel") != std::string::npos) 403ac6a4445SGunnar Mills { 404ac106bf6SEd Tanous asyncResp->res.jsonValue["ProcessorArchitecture"] = "x86"; 405ac106bf6SEd Tanous asyncResp->res.jsonValue["InstructionSet"] = "x86-64"; 406ac6a4445SGunnar Mills } 407351053f2SKrzysztof Grobelny else if (manufacturer->find("IBM") != std::string::npos) 408ac6a4445SGunnar Mills { 409ac106bf6SEd Tanous asyncResp->res.jsonValue["ProcessorArchitecture"] = "Power"; 410ac106bf6SEd Tanous asyncResp->res.jsonValue["InstructionSet"] = "PowerISA"; 411ac6a4445SGunnar Mills } 412ac6a4445SGunnar Mills } 413cba4f448SSunnySrivastava1984 414351053f2SKrzysztof Grobelny if (partNumber != nullptr) 415cba4f448SSunnySrivastava1984 { 416ac106bf6SEd Tanous asyncResp->res.jsonValue["PartNumber"] = *partNumber; 417cba4f448SSunnySrivastava1984 } 418cba4f448SSunnySrivastava1984 4196169de2cSBrad Bishop if (sparePartNumber != nullptr && !sparePartNumber->empty()) 420cba4f448SSunnySrivastava1984 { 421ac106bf6SEd Tanous asyncResp->res.jsonValue["SparePartNumber"] = *sparePartNumber; 422cba4f448SSunnySrivastava1984 } 423351053f2SKrzysztof Grobelny }); 424ac6a4445SGunnar Mills } 425ac6a4445SGunnar Mills 426ac106bf6SEd Tanous inline void getCpuRevisionData(std::shared_ptr<bmcweb::AsyncResp> asyncResp, 427ac6a4445SGunnar Mills const std::string& service, 428ac6a4445SGunnar Mills const std::string& objPath) 429ac6a4445SGunnar Mills { 43062598e31SEd Tanous BMCWEB_LOG_DEBUG("Get Cpu Revision Data"); 431deae6a78SEd Tanous dbus::utility::getAllProperties( 432deae6a78SEd Tanous service, objPath, "xyz.openbmc_project.Inventory.Decorator.Revision", 433ac106bf6SEd Tanous [objPath, asyncResp{std::move(asyncResp)}]( 4345e7e2dc5SEd Tanous const boost::system::error_code& ec, 435351053f2SKrzysztof Grobelny const dbus::utility::DBusPropertiesMap& properties) { 436ac6a4445SGunnar Mills if (ec) 437ac6a4445SGunnar Mills { 43862598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error"); 439ac106bf6SEd Tanous messages::internalError(asyncResp->res); 440ac6a4445SGunnar Mills return; 441ac6a4445SGunnar Mills } 442ac6a4445SGunnar Mills 443351053f2SKrzysztof Grobelny const std::string* version = nullptr; 444351053f2SKrzysztof Grobelny 445351053f2SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 446bd79bce8SPatrick Williams dbus_utils::UnpackErrorPrinter(), properties, "Version", 447bd79bce8SPatrick Williams version); 448351053f2SKrzysztof Grobelny 449351053f2SKrzysztof Grobelny if (!success) 450ac6a4445SGunnar Mills { 451ac106bf6SEd Tanous messages::internalError(asyncResp->res); 452351053f2SKrzysztof Grobelny return; 453351053f2SKrzysztof Grobelny } 454351053f2SKrzysztof Grobelny 455351053f2SKrzysztof Grobelny if (version != nullptr) 456ac6a4445SGunnar Mills { 457ac106bf6SEd Tanous asyncResp->res.jsonValue["Version"] = *version; 458ac6a4445SGunnar Mills } 459351053f2SKrzysztof Grobelny }); 460ac6a4445SGunnar Mills } 461ac6a4445SGunnar Mills 4628d1b46d7Szhanghch05 inline void getAcceleratorDataByService( 463ac106bf6SEd Tanous std::shared_ptr<bmcweb::AsyncResp> asyncResp, const std::string& acclrtrId, 4648d1b46d7Szhanghch05 const std::string& service, const std::string& objPath) 465ac6a4445SGunnar Mills { 46662598e31SEd Tanous BMCWEB_LOG_DEBUG("Get available system Accelerator resources by service."); 467deae6a78SEd Tanous dbus::utility::getAllProperties( 468deae6a78SEd Tanous service, objPath, "", 469ac106bf6SEd Tanous [acclrtrId, asyncResp{std::move(asyncResp)}]( 4705e7e2dc5SEd Tanous const boost::system::error_code& ec, 471351053f2SKrzysztof Grobelny const dbus::utility::DBusPropertiesMap& properties) { 472ac6a4445SGunnar Mills if (ec) 473ac6a4445SGunnar Mills { 47462598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error"); 475ac106bf6SEd Tanous messages::internalError(asyncResp->res); 476ac6a4445SGunnar Mills return; 477ac6a4445SGunnar Mills } 478ac6a4445SGunnar Mills 479351053f2SKrzysztof Grobelny const bool* functional = nullptr; 480351053f2SKrzysztof Grobelny const bool* present = nullptr; 481351053f2SKrzysztof Grobelny 482351053f2SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 483351053f2SKrzysztof Grobelny dbus_utils::UnpackErrorPrinter(), properties, "Functional", 484351053f2SKrzysztof Grobelny functional, "Present", present); 485351053f2SKrzysztof Grobelny 486351053f2SKrzysztof Grobelny if (!success) 487ac6a4445SGunnar Mills { 488ac106bf6SEd Tanous messages::internalError(asyncResp->res); 489351053f2SKrzysztof Grobelny return; 490ac6a4445SGunnar Mills } 491ac6a4445SGunnar Mills 492ac6a4445SGunnar Mills std::string state = "Enabled"; 493ac6a4445SGunnar Mills std::string health = "OK"; 494ac6a4445SGunnar Mills 495351053f2SKrzysztof Grobelny if (present != nullptr && !*present) 496ac6a4445SGunnar Mills { 497ac6a4445SGunnar Mills state = "Absent"; 498ac6a4445SGunnar Mills } 499ac6a4445SGunnar Mills 500351053f2SKrzysztof Grobelny if (functional != nullptr && !*functional) 501ac6a4445SGunnar Mills { 502ac6a4445SGunnar Mills if (state == "Enabled") 503ac6a4445SGunnar Mills { 504ac6a4445SGunnar Mills health = "Critical"; 505ac6a4445SGunnar Mills } 506ac6a4445SGunnar Mills } 507ac6a4445SGunnar Mills 508ac106bf6SEd Tanous asyncResp->res.jsonValue["Id"] = acclrtrId; 509ac106bf6SEd Tanous asyncResp->res.jsonValue["Name"] = "Processor"; 510ac106bf6SEd Tanous asyncResp->res.jsonValue["Status"]["State"] = state; 511ac106bf6SEd Tanous asyncResp->res.jsonValue["Status"]["Health"] = health; 512539d8c6bSEd Tanous asyncResp->res.jsonValue["ProcessorType"] = 513539d8c6bSEd Tanous processor::ProcessorType::Accelerator; 514351053f2SKrzysztof Grobelny }); 515ac6a4445SGunnar Mills } 516ac6a4445SGunnar Mills 517dba0c291SJonathan Doman // OperatingConfig D-Bus Types 518dba0c291SJonathan Doman using TurboProfileProperty = std::vector<std::tuple<uint32_t, size_t>>; 519dba0c291SJonathan Doman using BaseSpeedPrioritySettingsProperty = 520dba0c291SJonathan Doman std::vector<std::tuple<uint32_t, std::vector<uint32_t>>>; 521dba0c291SJonathan Doman // uint32_t and size_t may or may not be the same type, requiring a dedup'd 522dba0c291SJonathan Doman // variant 523dba0c291SJonathan Doman 524dba0c291SJonathan Doman /** 525dba0c291SJonathan Doman * Fill out the HighSpeedCoreIDs in a Processor resource from the given 526dba0c291SJonathan Doman * OperatingConfig D-Bus property. 527dba0c291SJonathan Doman * 528ac106bf6SEd Tanous * @param[in,out] asyncResp Async HTTP response. 529dba0c291SJonathan Doman * @param[in] baseSpeedSettings Full list of base speed priority groups, 530dba0c291SJonathan Doman * to use to determine the list of high 531dba0c291SJonathan Doman * speed cores. 532dba0c291SJonathan Doman */ 533dba0c291SJonathan Doman inline void highSpeedCoreIdsHandler( 534ac106bf6SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 535dba0c291SJonathan Doman const BaseSpeedPrioritySettingsProperty& baseSpeedSettings) 536dba0c291SJonathan Doman { 537dba0c291SJonathan Doman // The D-Bus property does not indicate which bucket is the "high 538dba0c291SJonathan Doman // priority" group, so let's discern that by looking for the one with 539dba0c291SJonathan Doman // highest base frequency. 540dba0c291SJonathan Doman auto highPriorityGroup = baseSpeedSettings.cend(); 541dba0c291SJonathan Doman uint32_t highestBaseSpeed = 0; 542dba0c291SJonathan Doman for (auto it = baseSpeedSettings.cbegin(); it != baseSpeedSettings.cend(); 543dba0c291SJonathan Doman ++it) 544dba0c291SJonathan Doman { 545dba0c291SJonathan Doman const uint32_t baseFreq = std::get<uint32_t>(*it); 546dba0c291SJonathan Doman if (baseFreq > highestBaseSpeed) 547dba0c291SJonathan Doman { 548dba0c291SJonathan Doman highestBaseSpeed = baseFreq; 549dba0c291SJonathan Doman highPriorityGroup = it; 550dba0c291SJonathan Doman } 551dba0c291SJonathan Doman } 552dba0c291SJonathan Doman 553ac106bf6SEd Tanous nlohmann::json& jsonCoreIds = asyncResp->res.jsonValue["HighSpeedCoreIDs"]; 554dba0c291SJonathan Doman jsonCoreIds = nlohmann::json::array(); 555dba0c291SJonathan Doman 556dba0c291SJonathan Doman // There may not be any entries in the D-Bus property, so only populate 557dba0c291SJonathan Doman // if there was actually something there. 558dba0c291SJonathan Doman if (highPriorityGroup != baseSpeedSettings.cend()) 559dba0c291SJonathan Doman { 560dba0c291SJonathan Doman jsonCoreIds = std::get<std::vector<uint32_t>>(*highPriorityGroup); 561dba0c291SJonathan Doman } 562dba0c291SJonathan Doman } 563dba0c291SJonathan Doman 564dba0c291SJonathan Doman /** 565dba0c291SJonathan Doman * Fill out OperatingConfig related items in a Processor resource by requesting 566dba0c291SJonathan Doman * data from the given D-Bus object. 567dba0c291SJonathan Doman * 568ac106bf6SEd Tanous * @param[in,out] asyncResp Async HTTP response. 569dba0c291SJonathan Doman * @param[in] cpuId CPU D-Bus name. 570dba0c291SJonathan Doman * @param[in] service D-Bus service to query. 571dba0c291SJonathan Doman * @param[in] objPath D-Bus object to query. 572dba0c291SJonathan Doman */ 573*504af5a0SPatrick Williams inline void getCpuConfigData( 574*504af5a0SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 575ac106bf6SEd Tanous const std::string& cpuId, const std::string& service, 576dba0c291SJonathan Doman const std::string& objPath) 577dba0c291SJonathan Doman { 57862598e31SEd Tanous BMCWEB_LOG_INFO("Getting CPU operating configs for {}", cpuId); 579dba0c291SJonathan Doman 580dba0c291SJonathan Doman // First, GetAll CurrentOperatingConfig properties on the object 581deae6a78SEd Tanous dbus::utility::getAllProperties( 582deae6a78SEd Tanous service, objPath, 583351053f2SKrzysztof Grobelny "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig", 584ac106bf6SEd Tanous [asyncResp, cpuId, 5855e7e2dc5SEd Tanous service](const boost::system::error_code& ec, 586351053f2SKrzysztof Grobelny const dbus::utility::DBusPropertiesMap& properties) { 587dba0c291SJonathan Doman if (ec) 588dba0c291SJonathan Doman { 58962598e31SEd Tanous BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec, ec.message()); 590ac106bf6SEd Tanous messages::internalError(asyncResp->res); 591dba0c291SJonathan Doman return; 592dba0c291SJonathan Doman } 593dba0c291SJonathan Doman 594ac106bf6SEd Tanous nlohmann::json& json = asyncResp->res.jsonValue; 595dba0c291SJonathan Doman 596351053f2SKrzysztof Grobelny const sdbusplus::message::object_path* appliedConfig = nullptr; 597351053f2SKrzysztof Grobelny const bool* baseSpeedPriorityEnabled = nullptr; 598351053f2SKrzysztof Grobelny 599351053f2SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 600351053f2SKrzysztof Grobelny dbus_utils::UnpackErrorPrinter(), properties, "AppliedConfig", 601351053f2SKrzysztof Grobelny appliedConfig, "BaseSpeedPriorityEnabled", 602351053f2SKrzysztof Grobelny baseSpeedPriorityEnabled); 603351053f2SKrzysztof Grobelny 604351053f2SKrzysztof Grobelny if (!success) 605dba0c291SJonathan Doman { 606ac106bf6SEd Tanous messages::internalError(asyncResp->res); 607351053f2SKrzysztof Grobelny return; 608dba0c291SJonathan Doman } 609dba0c291SJonathan Doman 610351053f2SKrzysztof Grobelny if (appliedConfig != nullptr) 611351053f2SKrzysztof Grobelny { 612351053f2SKrzysztof Grobelny const std::string& dbusPath = appliedConfig->str; 6131476687dSEd Tanous nlohmann::json::object_t operatingConfig; 614ef4c65b7SEd Tanous operatingConfig["@odata.id"] = boost::urls::format( 615253f11b8SEd Tanous "/redfish/v1/Systems/{}/Processors/{}/OperatingConfigs", 616253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME, cpuId); 6171476687dSEd Tanous json["OperatingConfigs"] = std::move(operatingConfig); 618dba0c291SJonathan Doman 619dba0c291SJonathan Doman // Reuse the D-Bus config object name for the Redfish 620dba0c291SJonathan Doman // URI 621dba0c291SJonathan Doman size_t baseNamePos = dbusPath.rfind('/'); 622dba0c291SJonathan Doman if (baseNamePos == std::string::npos || 623dba0c291SJonathan Doman baseNamePos == (dbusPath.size() - 1)) 624dba0c291SJonathan Doman { 625dba0c291SJonathan Doman // If the AppliedConfig was somehow not a valid path, 626dba0c291SJonathan Doman // skip adding any more properties, since everything 627dba0c291SJonathan Doman // else is tied to this applied config. 628ac106bf6SEd Tanous messages::internalError(asyncResp->res); 629351053f2SKrzysztof Grobelny return; 630dba0c291SJonathan Doman } 6311476687dSEd Tanous nlohmann::json::object_t appliedOperatingConfig; 632ef4c65b7SEd Tanous appliedOperatingConfig["@odata.id"] = boost::urls::format( 633253f11b8SEd Tanous "/redfish/v1/Systems/{}/Processors/{}/OperatingConfigs/{}", 634253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME, cpuId, 635253f11b8SEd Tanous dbusPath.substr(baseNamePos + 1)); 636bd79bce8SPatrick Williams json["AppliedOperatingConfig"] = 637bd79bce8SPatrick Williams std::move(appliedOperatingConfig); 638dba0c291SJonathan Doman 639dba0c291SJonathan Doman // Once we found the current applied config, queue another 640dba0c291SJonathan Doman // request to read the base freq core ids out of that 641dba0c291SJonathan Doman // config. 642deae6a78SEd Tanous dbus::utility::getProperty<BaseSpeedPrioritySettingsProperty>( 643deae6a78SEd Tanous service, dbusPath, 6441e1e598dSJonathan Doman "xyz.openbmc_project.Inventory.Item.Cpu." 6451e1e598dSJonathan Doman "OperatingConfig", 6461e1e598dSJonathan Doman "BaseSpeedPrioritySettings", 647bd79bce8SPatrick Williams [asyncResp](const boost::system::error_code& ec2, 648bd79bce8SPatrick Williams const BaseSpeedPrioritySettingsProperty& 649bd79bce8SPatrick Williams baseSpeedList) { 6508a592810SEd Tanous if (ec2) 651dba0c291SJonathan Doman { 652bd79bce8SPatrick Williams BMCWEB_LOG_WARNING("D-Bus Property Get error: {}", 653bd79bce8SPatrick Williams ec2); 654ac106bf6SEd Tanous messages::internalError(asyncResp->res); 655dba0c291SJonathan Doman return; 656dba0c291SJonathan Doman } 6571e1e598dSJonathan Doman 658ac106bf6SEd Tanous highSpeedCoreIdsHandler(asyncResp, baseSpeedList); 6591e1e598dSJonathan Doman }); 660dba0c291SJonathan Doman } 661351053f2SKrzysztof Grobelny 662351053f2SKrzysztof Grobelny if (baseSpeedPriorityEnabled != nullptr) 663dba0c291SJonathan Doman { 664dba0c291SJonathan Doman json["BaseSpeedPriorityState"] = 665351053f2SKrzysztof Grobelny *baseSpeedPriorityEnabled ? "Enabled" : "Disabled"; 666dba0c291SJonathan Doman } 667351053f2SKrzysztof Grobelny }); 668dba0c291SJonathan Doman } 669dba0c291SJonathan Doman 670cba4f448SSunnySrivastava1984 /** 671cba4f448SSunnySrivastava1984 * @brief Fill out location info of a processor by 672cba4f448SSunnySrivastava1984 * requesting data from the given D-Bus object. 673cba4f448SSunnySrivastava1984 * 674ac106bf6SEd Tanous * @param[in,out] asyncResp Async HTTP response. 675cba4f448SSunnySrivastava1984 * @param[in] service D-Bus service to query. 676cba4f448SSunnySrivastava1984 * @param[in] objPath D-Bus object to query. 677cba4f448SSunnySrivastava1984 */ 678ac106bf6SEd Tanous inline void getCpuLocationCode(std::shared_ptr<bmcweb::AsyncResp> asyncResp, 679cba4f448SSunnySrivastava1984 const std::string& service, 680cba4f448SSunnySrivastava1984 const std::string& objPath) 681cba4f448SSunnySrivastava1984 { 68262598e31SEd Tanous BMCWEB_LOG_DEBUG("Get Cpu Location Data"); 683deae6a78SEd Tanous dbus::utility::getProperty<std::string>( 684deae6a78SEd Tanous service, objPath, 6851e1e598dSJonathan Doman "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode", 686ac106bf6SEd Tanous [objPath, asyncResp{std::move(asyncResp)}]( 687ac106bf6SEd Tanous const boost::system::error_code& ec, const std::string& property) { 688cba4f448SSunnySrivastava1984 if (ec) 689cba4f448SSunnySrivastava1984 { 69062598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error"); 691ac106bf6SEd Tanous messages::internalError(asyncResp->res); 692cba4f448SSunnySrivastava1984 return; 693cba4f448SSunnySrivastava1984 } 694cba4f448SSunnySrivastava1984 695bd79bce8SPatrick Williams asyncResp->res 696bd79bce8SPatrick Williams .jsonValue["Location"]["PartLocation"]["ServiceLabel"] = 6971e1e598dSJonathan Doman property; 6981e1e598dSJonathan Doman }); 699cba4f448SSunnySrivastava1984 } 700cba4f448SSunnySrivastava1984 701c951448aSJonathan Doman /** 70249e429caSJonathan Doman * Populate the unique identifier in a Processor resource by requesting data 70349e429caSJonathan Doman * from the given D-Bus object. 70449e429caSJonathan Doman * 705ac106bf6SEd Tanous * @param[in,out] asyncResp Async HTTP response. 70649e429caSJonathan Doman * @param[in] service D-Bus service to query. 70749e429caSJonathan Doman * @param[in] objPath D-Bus object to query. 70849e429caSJonathan Doman */ 709ac106bf6SEd Tanous inline void getCpuUniqueId(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 71049e429caSJonathan Doman const std::string& service, 71149e429caSJonathan Doman const std::string& objectPath) 71249e429caSJonathan Doman { 71362598e31SEd Tanous BMCWEB_LOG_DEBUG("Get CPU UniqueIdentifier"); 714deae6a78SEd Tanous dbus::utility::getProperty<std::string>( 715deae6a78SEd Tanous service, objectPath, 7161e1e598dSJonathan Doman "xyz.openbmc_project.Inventory.Decorator.UniqueIdentifier", 7171e1e598dSJonathan Doman "UniqueIdentifier", 718ac106bf6SEd Tanous [asyncResp](const boost::system::error_code& ec, 719ac106bf6SEd Tanous const std::string& id) { 7201e1e598dSJonathan Doman if (ec) 72149e429caSJonathan Doman { 72262598e31SEd Tanous BMCWEB_LOG_ERROR("Failed to read cpu unique id: {}", ec); 723ac106bf6SEd Tanous messages::internalError(asyncResp->res); 72449e429caSJonathan Doman return; 72549e429caSJonathan Doman } 726ac106bf6SEd Tanous asyncResp->res 727ac106bf6SEd Tanous .jsonValue["ProcessorId"]["ProtectedIdentificationNumber"] = id; 7281e1e598dSJonathan Doman }); 72949e429caSJonathan Doman } 73049e429caSJonathan Doman 73149e429caSJonathan Doman /** 732c951448aSJonathan Doman * Find the D-Bus object representing the requested Processor, and call the 733c951448aSJonathan Doman * handler with the results. If matching object is not found, add 404 error to 734c951448aSJonathan Doman * response and don't call the handler. 735c951448aSJonathan Doman * 736c951448aSJonathan Doman * @param[in,out] resp Async HTTP response. 737c951448aSJonathan Doman * @param[in] processorId Redfish Processor Id. 738c951448aSJonathan Doman * @param[in] handler Callback to continue processing request upon 739c951448aSJonathan Doman * successfully finding object. 740c951448aSJonathan Doman */ 741c951448aSJonathan Doman template <typename Handler> 7428d1b46d7Szhanghch05 inline void getProcessorObject(const std::shared_ptr<bmcweb::AsyncResp>& resp, 743c951448aSJonathan Doman const std::string& processorId, 744c951448aSJonathan Doman Handler&& handler) 745ac6a4445SGunnar Mills { 74662598e31SEd Tanous BMCWEB_LOG_DEBUG("Get available system processor resources."); 747ac6a4445SGunnar Mills 748c951448aSJonathan Doman // GetSubTree on all interfaces which provide info about a Processor 749dfbf7de5SChris Cain constexpr std::array<std::string_view, 9> interfaces = { 750e99073f5SGeorge Liu "xyz.openbmc_project.Common.UUID", 751e99073f5SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.Asset", 752e99073f5SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.Revision", 753e99073f5SGeorge Liu "xyz.openbmc_project.Inventory.Item.Cpu", 754e99073f5SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.LocationCode", 755e99073f5SGeorge Liu "xyz.openbmc_project.Inventory.Item.Accelerator", 756e99073f5SGeorge Liu "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig", 757dfbf7de5SChris Cain "xyz.openbmc_project.Inventory.Decorator.UniqueIdentifier", 758dfbf7de5SChris Cain "xyz.openbmc_project.Control.Power.Throttle"}; 759e99073f5SGeorge Liu dbus::utility::getSubTree( 760e99073f5SGeorge Liu "/xyz/openbmc_project/inventory", 0, interfaces, 761c951448aSJonathan Doman [resp, processorId, handler = std::forward<Handler>(handler)]( 762e99073f5SGeorge Liu const boost::system::error_code& ec, 763e99073f5SGeorge Liu const dbus::utility::MapperGetSubTreeResponse& subtree) { 764ac6a4445SGunnar Mills if (ec) 765ac6a4445SGunnar Mills { 76662598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error: {}", ec); 767c951448aSJonathan Doman messages::internalError(resp->res); 768ac6a4445SGunnar Mills return; 769ac6a4445SGunnar Mills } 7702bab9831SJonathan Doman for (const auto& [objectPath, serviceMap] : subtree) 771ac6a4445SGunnar Mills { 7722bab9831SJonathan Doman // Ignore any objects which don't end with our desired cpu name 77311ba3979SEd Tanous if (!objectPath.ends_with(processorId)) 774ac6a4445SGunnar Mills { 7752bab9831SJonathan Doman continue; 776ac6a4445SGunnar Mills } 7772bab9831SJonathan Doman 778c951448aSJonathan Doman bool found = false; 779c951448aSJonathan Doman // Filter out objects that don't have the CPU-specific 780c951448aSJonathan Doman // interfaces to make sure we can return 404 on non-CPUs 781c951448aSJonathan Doman // (e.g. /redfish/../Processors/dimm0) 7822bab9831SJonathan Doman for (const auto& [serviceName, interfaceList] : serviceMap) 783ac6a4445SGunnar Mills { 7843544d2a7SEd Tanous if (std::ranges::find_first_of(interfaceList, 7853544d2a7SEd Tanous processorInterfaces) != 7863544d2a7SEd Tanous std::end(interfaceList)) 7872bab9831SJonathan Doman { 788c951448aSJonathan Doman found = true; 789c951448aSJonathan Doman break; 790c951448aSJonathan Doman } 791c951448aSJonathan Doman } 792c951448aSJonathan Doman 793c951448aSJonathan Doman if (!found) 7942bab9831SJonathan Doman { 795c951448aSJonathan Doman continue; 796ac6a4445SGunnar Mills } 797c951448aSJonathan Doman 798c951448aSJonathan Doman // Process the first object which does match our cpu name and 799c951448aSJonathan Doman // required interfaces, and potentially ignore any other 800c951448aSJonathan Doman // matching objects. Assume all interfaces we want to process 801c951448aSJonathan Doman // must be on the same object path. 802c951448aSJonathan Doman 8038a592810SEd Tanous handler(objectPath, serviceMap); 804ac6a4445SGunnar Mills return; 805ac6a4445SGunnar Mills } 806c951448aSJonathan Doman messages::resourceNotFound(resp->res, "Processor", processorId); 807e99073f5SGeorge Liu }); 808ac6a4445SGunnar Mills } 809ac6a4445SGunnar Mills 810bd79bce8SPatrick Williams inline void getProcessorData( 811bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 812bd79bce8SPatrick Williams const std::string& processorId, const std::string& objectPath, 8135df6eda2SShantappa Teekappanavar const dbus::utility::MapperServiceMap& serviceMap) 814c951448aSJonathan Doman { 815c951448aSJonathan Doman for (const auto& [serviceName, interfaceList] : serviceMap) 816c951448aSJonathan Doman { 817c951448aSJonathan Doman for (const auto& interface : interfaceList) 818c951448aSJonathan Doman { 819c951448aSJonathan Doman if (interface == "xyz.openbmc_project.Inventory.Decorator.Asset") 820c951448aSJonathan Doman { 821ac106bf6SEd Tanous getCpuAssetData(asyncResp, serviceName, objectPath); 822c951448aSJonathan Doman } 8230fda0f12SGeorge Liu else if (interface == 8240fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.Revision") 825c951448aSJonathan Doman { 826ac106bf6SEd Tanous getCpuRevisionData(asyncResp, serviceName, objectPath); 827c951448aSJonathan Doman } 828c951448aSJonathan Doman else if (interface == "xyz.openbmc_project.Inventory.Item.Cpu") 829c951448aSJonathan Doman { 830ac106bf6SEd Tanous getCpuDataByService(asyncResp, processorId, serviceName, 831c951448aSJonathan Doman objectPath); 832c951448aSJonathan Doman } 8330fda0f12SGeorge Liu else if (interface == 8340fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Item.Accelerator") 835c951448aSJonathan Doman { 836ac106bf6SEd Tanous getAcceleratorDataByService(asyncResp, processorId, serviceName, 837c951448aSJonathan Doman objectPath); 838c951448aSJonathan Doman } 8390fda0f12SGeorge Liu else if ( 8400fda0f12SGeorge Liu interface == 8410fda0f12SGeorge Liu "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig") 842c951448aSJonathan Doman { 843ac106bf6SEd Tanous getCpuConfigData(asyncResp, processorId, serviceName, 844ac106bf6SEd Tanous objectPath); 845c951448aSJonathan Doman } 8460fda0f12SGeorge Liu else if (interface == 8470fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.LocationCode") 848c951448aSJonathan Doman { 849ac106bf6SEd Tanous getCpuLocationCode(asyncResp, serviceName, objectPath); 850c951448aSJonathan Doman } 85171b82f26SSharad Yadav else if (interface == "xyz.openbmc_project.Common.UUID") 85271b82f26SSharad Yadav { 853ac106bf6SEd Tanous getProcessorUUID(asyncResp, serviceName, objectPath); 85471b82f26SSharad Yadav } 8550fda0f12SGeorge Liu else if (interface == 8560fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.UniqueIdentifier") 85749e429caSJonathan Doman { 858ac106bf6SEd Tanous getCpuUniqueId(asyncResp, serviceName, objectPath); 85949e429caSJonathan Doman } 860dfbf7de5SChris Cain else if (interface == "xyz.openbmc_project.Control.Power.Throttle") 861dfbf7de5SChris Cain { 862ac106bf6SEd Tanous getThrottleProperties(asyncResp, serviceName, objectPath); 863dfbf7de5SChris Cain } 864c951448aSJonathan Doman } 865c951448aSJonathan Doman } 866c951448aSJonathan Doman } 867c951448aSJonathan Doman 868dba0c291SJonathan Doman /** 869dba0c291SJonathan Doman * Request all the properties for the given D-Bus object and fill out the 870dba0c291SJonathan Doman * related entries in the Redfish OperatingConfig response. 871dba0c291SJonathan Doman * 872ac106bf6SEd Tanous * @param[in,out] asyncResp Async HTTP response. 873dba0c291SJonathan Doman * @param[in] service D-Bus service name to query. 874dba0c291SJonathan Doman * @param[in] objPath D-Bus object to query. 875dba0c291SJonathan Doman */ 876bd79bce8SPatrick Williams inline void getOperatingConfigData( 877bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 878bd79bce8SPatrick Williams const std::string& service, const std::string& objPath) 879dba0c291SJonathan Doman { 880deae6a78SEd Tanous dbus::utility::getAllProperties( 881deae6a78SEd Tanous service, objPath, 882351053f2SKrzysztof Grobelny "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig", 883ac106bf6SEd Tanous [asyncResp](const boost::system::error_code& ec, 884351053f2SKrzysztof Grobelny const dbus::utility::DBusPropertiesMap& properties) { 885dba0c291SJonathan Doman if (ec) 886dba0c291SJonathan Doman { 88762598e31SEd Tanous BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec, ec.message()); 888ac106bf6SEd Tanous messages::internalError(asyncResp->res); 889dba0c291SJonathan Doman return; 890dba0c291SJonathan Doman } 891dba0c291SJonathan Doman 892351053f2SKrzysztof Grobelny const size_t* availableCoreCount = nullptr; 893351053f2SKrzysztof Grobelny const uint32_t* baseSpeed = nullptr; 894351053f2SKrzysztof Grobelny const uint32_t* maxJunctionTemperature = nullptr; 895351053f2SKrzysztof Grobelny const uint32_t* maxSpeed = nullptr; 896351053f2SKrzysztof Grobelny const uint32_t* powerLimit = nullptr; 897351053f2SKrzysztof Grobelny const TurboProfileProperty* turboProfile = nullptr; 898351053f2SKrzysztof Grobelny const BaseSpeedPrioritySettingsProperty* baseSpeedPrioritySettings = 899351053f2SKrzysztof Grobelny nullptr; 900351053f2SKrzysztof Grobelny 901351053f2SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 902bd79bce8SPatrick Williams dbus_utils::UnpackErrorPrinter(), properties, 903bd79bce8SPatrick Williams "AvailableCoreCount", availableCoreCount, "BaseSpeed", 904bd79bce8SPatrick Williams baseSpeed, "MaxJunctionTemperature", maxJunctionTemperature, 905bd79bce8SPatrick Williams "MaxSpeed", maxSpeed, "PowerLimit", powerLimit, "TurboProfile", 906bd79bce8SPatrick Williams turboProfile, "BaseSpeedPrioritySettings", 907bd79bce8SPatrick Williams baseSpeedPrioritySettings); 908351053f2SKrzysztof Grobelny 909351053f2SKrzysztof Grobelny if (!success) 910dba0c291SJonathan Doman { 911ac106bf6SEd Tanous messages::internalError(asyncResp->res); 912351053f2SKrzysztof Grobelny return; 913dba0c291SJonathan Doman } 914dba0c291SJonathan Doman 915ac106bf6SEd Tanous nlohmann::json& json = asyncResp->res.jsonValue; 916351053f2SKrzysztof Grobelny 917351053f2SKrzysztof Grobelny if (availableCoreCount != nullptr) 918351053f2SKrzysztof Grobelny { 919351053f2SKrzysztof Grobelny json["TotalAvailableCoreCount"] = *availableCoreCount; 920351053f2SKrzysztof Grobelny } 921351053f2SKrzysztof Grobelny 922351053f2SKrzysztof Grobelny if (baseSpeed != nullptr) 923351053f2SKrzysztof Grobelny { 924351053f2SKrzysztof Grobelny json["BaseSpeedMHz"] = *baseSpeed; 925351053f2SKrzysztof Grobelny } 926351053f2SKrzysztof Grobelny 927351053f2SKrzysztof Grobelny if (maxJunctionTemperature != nullptr) 928351053f2SKrzysztof Grobelny { 929351053f2SKrzysztof Grobelny json["MaxJunctionTemperatureCelsius"] = *maxJunctionTemperature; 930351053f2SKrzysztof Grobelny } 931351053f2SKrzysztof Grobelny 932351053f2SKrzysztof Grobelny if (maxSpeed != nullptr) 933351053f2SKrzysztof Grobelny { 934351053f2SKrzysztof Grobelny json["MaxSpeedMHz"] = *maxSpeed; 935351053f2SKrzysztof Grobelny } 936351053f2SKrzysztof Grobelny 937351053f2SKrzysztof Grobelny if (powerLimit != nullptr) 938351053f2SKrzysztof Grobelny { 939351053f2SKrzysztof Grobelny json["TDPWatts"] = *powerLimit; 940351053f2SKrzysztof Grobelny } 941351053f2SKrzysztof Grobelny 942351053f2SKrzysztof Grobelny if (turboProfile != nullptr) 943351053f2SKrzysztof Grobelny { 944dba0c291SJonathan Doman nlohmann::json& turboArray = json["TurboProfile"]; 945dba0c291SJonathan Doman turboArray = nlohmann::json::array(); 946351053f2SKrzysztof Grobelny for (const auto& [turboSpeed, coreCount] : *turboProfile) 947dba0c291SJonathan Doman { 9481476687dSEd Tanous nlohmann::json::object_t turbo; 9491476687dSEd Tanous turbo["ActiveCoreCount"] = coreCount; 9501476687dSEd Tanous turbo["MaxSpeedMHz"] = turboSpeed; 951b2ba3072SPatrick Williams turboArray.emplace_back(std::move(turbo)); 952dba0c291SJonathan Doman } 953dba0c291SJonathan Doman } 954dba0c291SJonathan Doman 955351053f2SKrzysztof Grobelny if (baseSpeedPrioritySettings != nullptr) 956351053f2SKrzysztof Grobelny { 957bd79bce8SPatrick Williams nlohmann::json& baseSpeedArray = 958bd79bce8SPatrick Williams json["BaseSpeedPrioritySettings"]; 959dba0c291SJonathan Doman baseSpeedArray = nlohmann::json::array(); 960351053f2SKrzysztof Grobelny for (const auto& [baseSpeedMhz, coreList] : 961351053f2SKrzysztof Grobelny *baseSpeedPrioritySettings) 962dba0c291SJonathan Doman { 9631476687dSEd Tanous nlohmann::json::object_t speed; 9641476687dSEd Tanous speed["CoreCount"] = coreList.size(); 9651476687dSEd Tanous speed["CoreIDs"] = coreList; 966351053f2SKrzysztof Grobelny speed["BaseSpeedMHz"] = baseSpeedMhz; 967b2ba3072SPatrick Williams baseSpeedArray.emplace_back(std::move(speed)); 968dba0c291SJonathan Doman } 969dba0c291SJonathan Doman } 970351053f2SKrzysztof Grobelny }); 971dba0c291SJonathan Doman } 972dba0c291SJonathan Doman 9733cde86f1SJonathan Doman /** 9743cde86f1SJonathan Doman * Handle the PATCH operation of the AppliedOperatingConfig property. Do basic 9753cde86f1SJonathan Doman * validation of the input data, and then set the D-Bus property. 9763cde86f1SJonathan Doman * 9773cde86f1SJonathan Doman * @param[in,out] resp Async HTTP response. 9783cde86f1SJonathan Doman * @param[in] processorId Processor's Id. 9793cde86f1SJonathan Doman * @param[in] appliedConfigUri New property value to apply. 9803cde86f1SJonathan Doman * @param[in] cpuObjectPath Path of CPU object to modify. 9813cde86f1SJonathan Doman * @param[in] serviceMap Service map for CPU object. 9823cde86f1SJonathan Doman */ 9833cde86f1SJonathan Doman inline void patchAppliedOperatingConfig( 9843cde86f1SJonathan Doman const std::shared_ptr<bmcweb::AsyncResp>& resp, 9853cde86f1SJonathan Doman const std::string& processorId, const std::string& appliedConfigUri, 9865df6eda2SShantappa Teekappanavar const std::string& cpuObjectPath, 9875df6eda2SShantappa Teekappanavar const dbus::utility::MapperServiceMap& serviceMap) 9883cde86f1SJonathan Doman { 9893cde86f1SJonathan Doman // Check that the property even exists by checking for the interface 9903cde86f1SJonathan Doman const std::string* controlService = nullptr; 9913cde86f1SJonathan Doman for (const auto& [serviceName, interfaceList] : serviceMap) 9923cde86f1SJonathan Doman { 9933544d2a7SEd Tanous if (std::ranges::find(interfaceList, 9943cde86f1SJonathan Doman "xyz.openbmc_project.Control.Processor." 9953cde86f1SJonathan Doman "CurrentOperatingConfig") != interfaceList.end()) 9963cde86f1SJonathan Doman { 9973cde86f1SJonathan Doman controlService = &serviceName; 9983cde86f1SJonathan Doman break; 9993cde86f1SJonathan Doman } 10003cde86f1SJonathan Doman } 10013cde86f1SJonathan Doman 10023cde86f1SJonathan Doman if (controlService == nullptr) 10033cde86f1SJonathan Doman { 10043cde86f1SJonathan Doman messages::internalError(resp->res); 10053cde86f1SJonathan Doman return; 10063cde86f1SJonathan Doman } 10073cde86f1SJonathan Doman 10083cde86f1SJonathan Doman // Check that the config URI is a child of the cpu URI being patched. 1009253f11b8SEd Tanous std::string expectedPrefix(std::format("/redfish/v1/Systems/{}/Processors/", 1010253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME)); 10113cde86f1SJonathan Doman expectedPrefix += processorId; 10123cde86f1SJonathan Doman expectedPrefix += "/OperatingConfigs/"; 101311ba3979SEd Tanous if (!appliedConfigUri.starts_with(expectedPrefix) || 10143cde86f1SJonathan Doman expectedPrefix.size() == appliedConfigUri.size()) 10153cde86f1SJonathan Doman { 101687c44966SAsmitha Karunanithi messages::propertyValueIncorrect(resp->res, "AppliedOperatingConfig", 101787c44966SAsmitha Karunanithi appliedConfigUri); 10183cde86f1SJonathan Doman return; 10193cde86f1SJonathan Doman } 10203cde86f1SJonathan Doman 10213cde86f1SJonathan Doman // Generate the D-Bus path of the OperatingConfig object, by assuming it's a 10223cde86f1SJonathan Doman // direct child of the CPU object. 10233cde86f1SJonathan Doman // Strip the expectedPrefix from the config URI to get the "filename", and 10243cde86f1SJonathan Doman // append to the CPU's path. 10253cde86f1SJonathan Doman std::string configBaseName = appliedConfigUri.substr(expectedPrefix.size()); 10263cde86f1SJonathan Doman sdbusplus::message::object_path configPath(cpuObjectPath); 10273cde86f1SJonathan Doman configPath /= configBaseName; 10283cde86f1SJonathan Doman 102962598e31SEd Tanous BMCWEB_LOG_INFO("Setting config to {}", configPath.str); 10303cde86f1SJonathan Doman 10313cde86f1SJonathan Doman // Set the property, with handler to check error responses 103287c44966SAsmitha Karunanithi setDbusProperty( 1033e93abac6SGinu George resp, "AppliedOperatingConfig", *controlService, cpuObjectPath, 10349ae226faSGeorge Liu "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig", 1035e93abac6SGinu George "AppliedConfig", configPath); 10363cde86f1SJonathan Doman } 10373cde86f1SJonathan Doman 1038bd79bce8SPatrick Williams inline void handleProcessorHead( 1039bd79bce8SPatrick Williams crow::App& app, const crow::Request& req, 1040ac106bf6SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1041bd79bce8SPatrick Williams const std::string& /* systemName */, const std::string& /* processorId */) 104271a24ca4SNikhil Namjoshi { 1043ac106bf6SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 104471a24ca4SNikhil Namjoshi { 104571a24ca4SNikhil Namjoshi return; 104671a24ca4SNikhil Namjoshi } 1047ac106bf6SEd Tanous asyncResp->res.addHeader( 104871a24ca4SNikhil Namjoshi boost::beast::http::field::link, 104971a24ca4SNikhil Namjoshi "</redfish/v1/JsonSchemas/Processor/Processor.json>; rel=describedby"); 105071a24ca4SNikhil Namjoshi } 105171a24ca4SNikhil Namjoshi 105271a24ca4SNikhil Namjoshi inline void handleProcessorCollectionHead( 105371a24ca4SNikhil Namjoshi crow::App& app, const crow::Request& req, 1054ac106bf6SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 105571a24ca4SNikhil Namjoshi const std::string& /* systemName */) 105671a24ca4SNikhil Namjoshi { 1057ac106bf6SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 105871a24ca4SNikhil Namjoshi { 105971a24ca4SNikhil Namjoshi return; 106071a24ca4SNikhil Namjoshi } 1061ac106bf6SEd Tanous asyncResp->res.addHeader( 106271a24ca4SNikhil Namjoshi boost::beast::http::field::link, 106371a24ca4SNikhil Namjoshi "</redfish/v1/JsonSchemas/ProcessorCollection/ProcessorCollection.json>; rel=describedby"); 106471a24ca4SNikhil Namjoshi } 106571a24ca4SNikhil Namjoshi 10667e860f15SJohn Edward Broadbent inline void requestRoutesOperatingConfigCollection(App& app) 1067dba0c291SJonathan Doman { 10687f3e84a1SEd Tanous BMCWEB_ROUTE(app, 10697f3e84a1SEd Tanous "/redfish/v1/Systems/<str>/Processors/<str>/OperatingConfigs/") 1070ed398213SEd Tanous .privileges(redfish::privileges::getOperatingConfigCollection) 1071bd79bce8SPatrick Williams .methods( 1072bd79bce8SPatrick Williams boost::beast::http::verb:: 1073bd79bce8SPatrick Williams get)([&app](const crow::Request& req, 107445ca1b86SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1075bd79bce8SPatrick Williams const std::string& systemName, 1076bd79bce8SPatrick Williams const std::string& cpuName) { 10773ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 107845ca1b86SEd Tanous { 107945ca1b86SEd Tanous return; 108045ca1b86SEd Tanous } 10817f3e84a1SEd Tanous 108225b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 10837f3e84a1SEd Tanous { 10847f3e84a1SEd Tanous // Option currently returns no systems. TBD 10857f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 10867f3e84a1SEd Tanous systemName); 10877f3e84a1SEd Tanous return; 10887f3e84a1SEd Tanous } 10897f3e84a1SEd Tanous 1090253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 10917f3e84a1SEd Tanous { 10927f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 10937f3e84a1SEd Tanous systemName); 10947f3e84a1SEd Tanous return; 10957f3e84a1SEd Tanous } 10968d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.type"] = 1097dba0c291SJonathan Doman "#OperatingConfigCollection.OperatingConfigCollection"; 1098ef4c65b7SEd Tanous asyncResp->res.jsonValue["@odata.id"] = boost::urls::format( 1099253f11b8SEd Tanous "/redfish/v1/Systems/{}/Processors/{}/OperatingConfigs", 1100253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME, cpuName); 11010fda0f12SGeorge Liu asyncResp->res.jsonValue["Name"] = "Operating Config Collection"; 1102dba0c291SJonathan Doman 11037e860f15SJohn Edward Broadbent // First find the matching CPU object so we know how to 11047e860f15SJohn Edward Broadbent // constrain our search for related Config objects. 11057a1dbc48SGeorge Liu const std::array<std::string_view, 1> interfaces = { 11067a1dbc48SGeorge Liu "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig"}; 11077a1dbc48SGeorge Liu dbus::utility::getSubTreePaths( 11087a1dbc48SGeorge Liu "/xyz/openbmc_project/inventory", 0, interfaces, 1109bd79bce8SPatrick Williams [asyncResp, 1110bd79bce8SPatrick Williams cpuName](const boost::system::error_code& ec, 1111bd79bce8SPatrick Williams const dbus::utility::MapperGetSubTreePathsResponse& 1112bd79bce8SPatrick Williams objects) { 1113dba0c291SJonathan Doman if (ec) 1114dba0c291SJonathan Doman { 1115bd79bce8SPatrick Williams BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec, 1116bd79bce8SPatrick Williams ec.message()); 1117dba0c291SJonathan Doman messages::internalError(asyncResp->res); 1118dba0c291SJonathan Doman return; 1119dba0c291SJonathan Doman } 1120dba0c291SJonathan Doman 1121dba0c291SJonathan Doman for (const std::string& object : objects) 1122dba0c291SJonathan Doman { 112311ba3979SEd Tanous if (!object.ends_with(cpuName)) 1124dba0c291SJonathan Doman { 1125dba0c291SJonathan Doman continue; 1126dba0c291SJonathan Doman } 1127dba0c291SJonathan Doman 11287e860f15SJohn Edward Broadbent // Not expected that there will be multiple matching 11297e860f15SJohn Edward Broadbent // CPU objects, but if there are just use the first 11307e860f15SJohn Edward Broadbent // one. 1131dba0c291SJonathan Doman 11327e860f15SJohn Edward Broadbent // Use the common search routine to construct the 11337e860f15SJohn Edward Broadbent // Collection of all Config objects under this CPU. 11347a1dbc48SGeorge Liu constexpr std::array<std::string_view, 1> interface{ 11355a39f77aSPatrick Williams "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig"}; 1136dba0c291SJonathan Doman collection_util::getCollectionMembers( 1137dba0c291SJonathan Doman asyncResp, 1138ef4c65b7SEd Tanous boost::urls::format( 1139253f11b8SEd Tanous "/redfish/v1/Systems/{}/Processors/{}/OperatingConfigs", 1140253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME, cpuName), 114136b5f1edSLakshmi Yadlapati interface, object); 1142dba0c291SJonathan Doman return; 1143dba0c291SJonathan Doman } 11447a1dbc48SGeorge Liu }); 11457e860f15SJohn Edward Broadbent }); 1146dba0c291SJonathan Doman } 1147dba0c291SJonathan Doman 11487e860f15SJohn Edward Broadbent inline void requestRoutesOperatingConfig(App& app) 1149dba0c291SJonathan Doman { 11507e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 11517e860f15SJohn Edward Broadbent app, 11527f3e84a1SEd Tanous "/redfish/v1/Systems/<str>/Processors/<str>/OperatingConfigs/<str>/") 1153ed398213SEd Tanous .privileges(redfish::privileges::getOperatingConfig) 1154bd79bce8SPatrick Williams .methods( 1155bd79bce8SPatrick Williams boost::beast::http::verb:: 1156bd79bce8SPatrick Williams get)([&app](const crow::Request& req, 115745ca1b86SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1158bd79bce8SPatrick Williams const std::string& systemName, 1159bd79bce8SPatrick Williams const std::string& cpuName, 11607f3e84a1SEd Tanous const std::string& configName) { 11613ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 116245ca1b86SEd Tanous { 116345ca1b86SEd Tanous return; 116445ca1b86SEd Tanous } 116525b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 11667f3e84a1SEd Tanous { 11677f3e84a1SEd Tanous // Option currently returns no systems. TBD 11687f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 11697f3e84a1SEd Tanous systemName); 11707f3e84a1SEd Tanous return; 11717f3e84a1SEd Tanous } 11727f3e84a1SEd Tanous 1173253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 11747f3e84a1SEd Tanous { 11757f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 11767f3e84a1SEd Tanous systemName); 11777f3e84a1SEd Tanous return; 11787f3e84a1SEd Tanous } 11797e860f15SJohn Edward Broadbent // Ask for all objects implementing OperatingConfig so we can search 11807e860f15SJohn Edward Broadbent // for one with a matching name 1181e99073f5SGeorge Liu constexpr std::array<std::string_view, 1> interfaces = { 1182e99073f5SGeorge Liu "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig"}; 1183e99073f5SGeorge Liu dbus::utility::getSubTree( 1184e99073f5SGeorge Liu "/xyz/openbmc_project/inventory", 0, interfaces, 118539662a3bSEd Tanous [asyncResp, cpuName, configName]( 1186e99073f5SGeorge Liu const boost::system::error_code& ec, 11875df6eda2SShantappa Teekappanavar const dbus::utility::MapperGetSubTreeResponse& subtree) { 1188dba0c291SJonathan Doman if (ec) 1189dba0c291SJonathan Doman { 1190bd79bce8SPatrick Williams BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec, 1191bd79bce8SPatrick Williams ec.message()); 1192dba0c291SJonathan Doman messages::internalError(asyncResp->res); 1193dba0c291SJonathan Doman return; 1194dba0c291SJonathan Doman } 1195bd79bce8SPatrick Williams const std::string expectedEnding = 1196bd79bce8SPatrick Williams cpuName + '/' + configName; 1197dba0c291SJonathan Doman for (const auto& [objectPath, serviceMap] : subtree) 1198dba0c291SJonathan Doman { 1199dba0c291SJonathan Doman // Ignore any configs without matching cpuX/configY 1200bd79bce8SPatrick Williams if (!objectPath.ends_with(expectedEnding) || 1201bd79bce8SPatrick Williams serviceMap.empty()) 1202dba0c291SJonathan Doman { 1203dba0c291SJonathan Doman continue; 1204dba0c291SJonathan Doman } 1205dba0c291SJonathan Doman 1206dba0c291SJonathan Doman nlohmann::json& json = asyncResp->res.jsonValue; 1207bd79bce8SPatrick Williams json["@odata.type"] = 1208bd79bce8SPatrick Williams "#OperatingConfig.v1_0_0.OperatingConfig"; 1209ef4c65b7SEd Tanous json["@odata.id"] = boost::urls::format( 1210253f11b8SEd Tanous "/redfish/v1/Systems/{}/Processors/{}/OperatingConfigs/{}", 1211bd79bce8SPatrick Williams BMCWEB_REDFISH_SYSTEM_URI_NAME, cpuName, 1212bd79bce8SPatrick Williams configName); 1213dba0c291SJonathan Doman json["Name"] = "Processor Profile"; 1214dba0c291SJonathan Doman json["Id"] = configName; 1215dba0c291SJonathan Doman 1216dba0c291SJonathan Doman // Just use the first implementation of the object - not 12177e860f15SJohn Edward Broadbent // expected that there would be multiple matching 12187e860f15SJohn Edward Broadbent // services 1219bd79bce8SPatrick Williams getOperatingConfigData( 1220bd79bce8SPatrick Williams asyncResp, serviceMap.begin()->first, objectPath); 1221dba0c291SJonathan Doman return; 1222dba0c291SJonathan Doman } 1223bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, 1224bd79bce8SPatrick Williams "OperatingConfig", configName); 1225e99073f5SGeorge Liu }); 12267e860f15SJohn Edward Broadbent }); 1227ac6a4445SGunnar Mills } 1228ac6a4445SGunnar Mills 12297e860f15SJohn Edward Broadbent inline void requestRoutesProcessorCollection(App& app) 12307e860f15SJohn Edward Broadbent { 1231ac6a4445SGunnar Mills /** 1232ac6a4445SGunnar Mills * Functions triggers appropriate requests on DBus 1233ac6a4445SGunnar Mills */ 123422d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/") 123571a24ca4SNikhil Namjoshi .privileges(redfish::privileges::headProcessorCollection) 123671a24ca4SNikhil Namjoshi .methods(boost::beast::http::verb::head)( 123771a24ca4SNikhil Namjoshi std::bind_front(handleProcessorCollectionHead, std::ref(app))); 123871a24ca4SNikhil Namjoshi 123971a24ca4SNikhil Namjoshi BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/") 1240ed398213SEd Tanous .privileges(redfish::privileges::getProcessorCollection) 1241bd79bce8SPatrick Williams .methods( 1242bd79bce8SPatrick Williams boost::beast::http::verb:: 1243bd79bce8SPatrick Williams get)([&app](const crow::Request& req, 124422d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 124522d268cbSEd Tanous const std::string& systemName) { 12463ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 124745ca1b86SEd Tanous { 124845ca1b86SEd Tanous return; 124945ca1b86SEd Tanous } 125025b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 12517f3e84a1SEd Tanous { 12527f3e84a1SEd Tanous // Option currently returns no systems. TBD 12537f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 12547f3e84a1SEd Tanous systemName); 12557f3e84a1SEd Tanous return; 12567f3e84a1SEd Tanous } 12577f3e84a1SEd Tanous 1258253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 125922d268cbSEd Tanous { 126022d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 126122d268cbSEd Tanous systemName); 126222d268cbSEd Tanous return; 126322d268cbSEd Tanous } 126422d268cbSEd Tanous 126571a24ca4SNikhil Namjoshi asyncResp->res.addHeader( 126671a24ca4SNikhil Namjoshi boost::beast::http::field::link, 126771a24ca4SNikhil Namjoshi "</redfish/v1/JsonSchemas/ProcessorCollection/ProcessorCollection.json>; rel=describedby"); 126871a24ca4SNikhil Namjoshi 12698d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.type"] = 1270ac6a4445SGunnar Mills "#ProcessorCollection.ProcessorCollection"; 12718d1b46d7Szhanghch05 asyncResp->res.jsonValue["Name"] = "Processor Collection"; 1272ac6a4445SGunnar Mills 12738d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.id"] = 1274253f11b8SEd Tanous std::format("/redfish/v1/Systems/{}/Processors", 1275253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 1276ac6a4445SGunnar Mills 127705030b8eSGunnar Mills collection_util::getCollectionMembers( 1278ae9031f0SWilly Tu asyncResp, 1279253f11b8SEd Tanous boost::urls::format("/redfish/v1/Systems/{}/Processors", 1280253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME), 128136b5f1edSLakshmi Yadlapati processorInterfaces, "/xyz/openbmc_project/inventory"); 12827e860f15SJohn Edward Broadbent }); 1283ac6a4445SGunnar Mills } 1284ac6a4445SGunnar Mills 12857e860f15SJohn Edward Broadbent inline void requestRoutesProcessor(App& app) 12867e860f15SJohn Edward Broadbent { 1287ac6a4445SGunnar Mills /** 1288ac6a4445SGunnar Mills * Functions triggers appropriate requests on DBus 1289ac6a4445SGunnar Mills */ 12907e860f15SJohn Edward Broadbent 129122d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/<str>/") 129271a24ca4SNikhil Namjoshi .privileges(redfish::privileges::headProcessor) 129371a24ca4SNikhil Namjoshi .methods(boost::beast::http::verb::head)( 129471a24ca4SNikhil Namjoshi std::bind_front(handleProcessorHead, std::ref(app))); 129571a24ca4SNikhil Namjoshi 129671a24ca4SNikhil Namjoshi BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/<str>/") 1297ed398213SEd Tanous .privileges(redfish::privileges::getProcessor) 1298bd79bce8SPatrick Williams .methods( 1299bd79bce8SPatrick Williams boost::beast::http::verb:: 1300bd79bce8SPatrick Williams get)([&app](const crow::Request& req, 13017e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 130222d268cbSEd Tanous const std::string& systemName, 13037e860f15SJohn Edward Broadbent const std::string& processorId) { 13043ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 130545ca1b86SEd Tanous { 130645ca1b86SEd Tanous return; 130745ca1b86SEd Tanous } 130825b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 13097f3e84a1SEd Tanous { 13107f3e84a1SEd Tanous // Option currently returns no systems. TBD 13117f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 13127f3e84a1SEd Tanous systemName); 13137f3e84a1SEd Tanous return; 13147f3e84a1SEd Tanous } 1315253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 131622d268cbSEd Tanous { 131722d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 131822d268cbSEd Tanous systemName); 131922d268cbSEd Tanous return; 132022d268cbSEd Tanous } 132122d268cbSEd Tanous 132271a24ca4SNikhil Namjoshi asyncResp->res.addHeader( 132371a24ca4SNikhil Namjoshi boost::beast::http::field::link, 132471a24ca4SNikhil Namjoshi "</redfish/v1/JsonSchemas/Processor/Processor.json>; rel=describedby"); 13258d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.type"] = 1326dfbf7de5SChris Cain "#Processor.v1_18_0.Processor"; 1327bd79bce8SPatrick Williams asyncResp->res.jsonValue["@odata.id"] = boost::urls::format( 1328bd79bce8SPatrick Williams "/redfish/v1/Systems/{}/Processors/{}", 1329253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME, processorId); 1330ac6a4445SGunnar Mills 13318a592810SEd Tanous getProcessorObject( 13328a592810SEd Tanous asyncResp, processorId, 13338a592810SEd Tanous std::bind_front(getProcessorData, asyncResp, processorId)); 13347e860f15SJohn Edward Broadbent }); 13353cde86f1SJonathan Doman 133622d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/<str>/") 1337ed398213SEd Tanous .privileges(redfish::privileges::patchProcessor) 13387e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::patch)( 133945ca1b86SEd Tanous [&app](const crow::Request& req, 13407e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 134122d268cbSEd Tanous const std::string& systemName, 13427e860f15SJohn Edward Broadbent const std::string& processorId) { 13433ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 134445ca1b86SEd Tanous { 134545ca1b86SEd Tanous return; 134645ca1b86SEd Tanous } 134725b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 13487f3e84a1SEd Tanous { 13497f3e84a1SEd Tanous // Option currently returns no systems. TBD 13507f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 13517f3e84a1SEd Tanous systemName); 13527f3e84a1SEd Tanous return; 13537f3e84a1SEd Tanous } 1354253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 135522d268cbSEd Tanous { 135622d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 135722d268cbSEd Tanous systemName); 135822d268cbSEd Tanous return; 135922d268cbSEd Tanous } 136022d268cbSEd Tanous 13613c569218SEd Tanous std::optional<std::string> appliedConfigUri; 1362bd79bce8SPatrick Williams if (!json_util::readJsonPatch( 1363afc474aeSMyung Bae req, asyncResp->res, // 1364afc474aeSMyung Bae "AppliedOperatingConfig/@odata.id", appliedConfigUri // 1365afc474aeSMyung Bae )) 13663cde86f1SJonathan Doman { 13673cde86f1SJonathan Doman return; 13683cde86f1SJonathan Doman } 13693cde86f1SJonathan Doman 13703c569218SEd Tanous if (appliedConfigUri) 13713cde86f1SJonathan Doman { 13727e860f15SJohn Edward Broadbent // Check for 404 and find matching D-Bus object, then run 13737e860f15SJohn Edward Broadbent // property patch handlers if that all succeeds. 1374bd79bce8SPatrick Williams getProcessorObject( 13757e860f15SJohn Edward Broadbent asyncResp, processorId, 1376bd79bce8SPatrick Williams std::bind_front(patchAppliedOperatingConfig, asyncResp, 1377bd79bce8SPatrick Williams processorId, *appliedConfigUri)); 13783cde86f1SJonathan Doman } 13797e860f15SJohn Edward Broadbent }); 13803cde86f1SJonathan Doman } 1381ac6a4445SGunnar Mills 1382ac6a4445SGunnar Mills } // namespace redfish 1383