1ac6a4445SGunnar Mills /* 2ac6a4445SGunnar Mills // Copyright (c) 2018 Intel Corporation 3ac6a4445SGunnar Mills // 4ac6a4445SGunnar Mills // Licensed under the Apache License, Version 2.0 (the "License"); 5ac6a4445SGunnar Mills // you may not use this file except in compliance with the License. 6ac6a4445SGunnar Mills // You may obtain a copy of the License at 7ac6a4445SGunnar Mills // 8ac6a4445SGunnar Mills // http://www.apache.org/licenses/LICENSE-2.0 9ac6a4445SGunnar Mills // 10ac6a4445SGunnar Mills // Unless required by applicable law or agreed to in writing, software 11ac6a4445SGunnar Mills // distributed under the License is distributed on an "AS IS" BASIS, 12ac6a4445SGunnar Mills // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ac6a4445SGunnar Mills // See the License for the specific language governing permissions and 14ac6a4445SGunnar Mills // limitations under the License. 15ac6a4445SGunnar Mills */ 16ac6a4445SGunnar Mills #pragma once 17ac6a4445SGunnar Mills 181e1e598dSJonathan Doman #include "dbus_singleton.hpp" 191e1e598dSJonathan Doman #include "error_messages.hpp" 20ac6a4445SGunnar Mills #include "health.hpp" 21ac6a4445SGunnar Mills 227e860f15SJohn Edward Broadbent #include <app.hpp> 23ac6a4445SGunnar Mills #include <boost/container/flat_map.hpp> 24168e20c1SEd Tanous #include <dbus_utility.hpp> 2545ca1b86SEd Tanous #include <query.hpp> 26ed398213SEd Tanous #include <registries/privilege_registry.hpp> 271e1e598dSJonathan Doman #include <sdbusplus/asio/property.hpp> 28dba0c291SJonathan Doman #include <sdbusplus/message/native_types.hpp> 29*351053f2SKrzysztof Grobelny #include <sdbusplus/unpack_properties.hpp> 30dba0c291SJonathan Doman #include <sdbusplus/utility/dedup_variant.hpp> 31ac6a4445SGunnar Mills #include <utils/collection.hpp> 32*351053f2SKrzysztof Grobelny #include <utils/dbus_utils.hpp> 33ac6a4445SGunnar Mills #include <utils/json_utils.hpp> 34ac6a4445SGunnar Mills 35ac6a4445SGunnar Mills namespace redfish 36ac6a4445SGunnar Mills { 37ac6a4445SGunnar Mills 38c951448aSJonathan Doman // Interfaces which imply a D-Bus object represents a Processor 39c951448aSJonathan Doman constexpr std::array<const char*, 2> processorInterfaces = { 40c951448aSJonathan Doman "xyz.openbmc_project.Inventory.Item.Cpu", 41c951448aSJonathan Doman "xyz.openbmc_project.Inventory.Item.Accelerator"}; 422bab9831SJonathan Doman 4371b82f26SSharad Yadav /** 4471b82f26SSharad Yadav * @brief Fill out uuid info of a processor by 4571b82f26SSharad Yadav * requesting data from the given D-Bus object. 4671b82f26SSharad Yadav * 4771b82f26SSharad Yadav * @param[in,out] aResp Async HTTP response. 4871b82f26SSharad Yadav * @param[in] service D-Bus service to query. 4971b82f26SSharad Yadav * @param[in] objPath D-Bus object to query. 5071b82f26SSharad Yadav */ 5171b82f26SSharad Yadav inline void getProcessorUUID(std::shared_ptr<bmcweb::AsyncResp> aResp, 5271b82f26SSharad Yadav const std::string& service, 5371b82f26SSharad Yadav const std::string& objPath) 5471b82f26SSharad Yadav { 5571b82f26SSharad Yadav BMCWEB_LOG_DEBUG << "Get Processor UUID"; 561e1e598dSJonathan Doman sdbusplus::asio::getProperty<std::string>( 571e1e598dSJonathan Doman *crow::connections::systemBus, service, objPath, 581e1e598dSJonathan Doman "xyz.openbmc_project.Common.UUID", "UUID", 591e1e598dSJonathan Doman [objPath, aResp{std::move(aResp)}](const boost::system::error_code ec, 601e1e598dSJonathan Doman const std::string& property) { 6171b82f26SSharad Yadav if (ec) 6271b82f26SSharad Yadav { 6371b82f26SSharad Yadav BMCWEB_LOG_DEBUG << "DBUS response error"; 6471b82f26SSharad Yadav messages::internalError(aResp->res); 6571b82f26SSharad Yadav return; 6671b82f26SSharad Yadav } 671e1e598dSJonathan Doman aResp->res.jsonValue["UUID"] = property; 681e1e598dSJonathan Doman }); 6971b82f26SSharad Yadav } 7071b82f26SSharad Yadav 71711ac7a9SEd Tanous inline void getCpuDataByInterface( 72711ac7a9SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& aResp, 73711ac7a9SEd Tanous const dbus::utility::DBusInteracesMap& cpuInterfacesProperties) 74ac6a4445SGunnar Mills { 75ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "Get CPU resources by interface."; 76ac6a4445SGunnar Mills 77a1649ec6SChicago Duan // Set the default value of state 78a1649ec6SChicago Duan aResp->res.jsonValue["Status"]["State"] = "Enabled"; 79a1649ec6SChicago Duan aResp->res.jsonValue["Status"]["Health"] = "OK"; 80ac6a4445SGunnar Mills 81ac6a4445SGunnar Mills for (const auto& interface : cpuInterfacesProperties) 82ac6a4445SGunnar Mills { 83ac6a4445SGunnar Mills for (const auto& property : interface.second) 84ac6a4445SGunnar Mills { 85a1649ec6SChicago Duan if (property.first == "Present") 86ac6a4445SGunnar Mills { 87a1649ec6SChicago Duan const bool* cpuPresent = std::get_if<bool>(&property.second); 88a1649ec6SChicago Duan if (cpuPresent == nullptr) 89ac6a4445SGunnar Mills { 90ac6a4445SGunnar Mills // Important property not in desired type 91ac6a4445SGunnar Mills messages::internalError(aResp->res); 92ac6a4445SGunnar Mills return; 93ac6a4445SGunnar Mills } 94e05aec50SEd Tanous if (!*cpuPresent) 95ac6a4445SGunnar Mills { 96a1649ec6SChicago Duan // Slot is not populated 97ac6a4445SGunnar Mills aResp->res.jsonValue["Status"]["State"] = "Absent"; 98a1649ec6SChicago Duan } 99a1649ec6SChicago Duan } 100a1649ec6SChicago Duan else if (property.first == "Functional") 101a1649ec6SChicago Duan { 102a1649ec6SChicago Duan const bool* cpuFunctional = std::get_if<bool>(&property.second); 103a1649ec6SChicago Duan if (cpuFunctional == nullptr) 104a1649ec6SChicago Duan { 105a1649ec6SChicago Duan messages::internalError(aResp->res); 106ac6a4445SGunnar Mills return; 107ac6a4445SGunnar Mills } 108e05aec50SEd Tanous if (!*cpuFunctional) 109a1649ec6SChicago Duan { 110a1649ec6SChicago Duan aResp->res.jsonValue["Status"]["Health"] = "Critical"; 111a1649ec6SChicago Duan } 112a1649ec6SChicago Duan } 113a1649ec6SChicago Duan else if (property.first == "CoreCount") 114a1649ec6SChicago Duan { 115a1649ec6SChicago Duan const uint16_t* coresCount = 116a1649ec6SChicago Duan std::get_if<uint16_t>(&property.second); 117a1649ec6SChicago Duan if (coresCount == nullptr) 118a1649ec6SChicago Duan { 119a1649ec6SChicago Duan messages::internalError(aResp->res); 120a1649ec6SChicago Duan return; 121a1649ec6SChicago Duan } 122ac6a4445SGunnar Mills aResp->res.jsonValue["TotalCores"] = *coresCount; 123ac6a4445SGunnar Mills } 124dc3fa667SJonathan Doman else if (property.first == "MaxSpeedInMhz") 125dc3fa667SJonathan Doman { 126dc3fa667SJonathan Doman const uint32_t* value = std::get_if<uint32_t>(&property.second); 127dc3fa667SJonathan Doman if (value != nullptr) 128dc3fa667SJonathan Doman { 129dc3fa667SJonathan Doman aResp->res.jsonValue["MaxSpeedMHz"] = *value; 130dc3fa667SJonathan Doman } 131dc3fa667SJonathan Doman } 132ac6a4445SGunnar Mills else if (property.first == "Socket") 133ac6a4445SGunnar Mills { 134ac6a4445SGunnar Mills const std::string* value = 135ac6a4445SGunnar Mills std::get_if<std::string>(&property.second); 136ac6a4445SGunnar Mills if (value != nullptr) 137ac6a4445SGunnar Mills { 138ac6a4445SGunnar Mills aResp->res.jsonValue["Socket"] = *value; 139ac6a4445SGunnar Mills } 140ac6a4445SGunnar Mills } 141ac6a4445SGunnar Mills else if (property.first == "ThreadCount") 142ac6a4445SGunnar Mills { 143dc3fa667SJonathan Doman const uint16_t* value = std::get_if<uint16_t>(&property.second); 144ac6a4445SGunnar Mills if (value != nullptr) 145ac6a4445SGunnar Mills { 146ac6a4445SGunnar Mills aResp->res.jsonValue["TotalThreads"] = *value; 147ac6a4445SGunnar Mills } 148ac6a4445SGunnar Mills } 1491930fbd4SBrandon Kim else if (property.first == "EffectiveFamily") 150ac6a4445SGunnar Mills { 1511930fbd4SBrandon Kim const uint16_t* value = std::get_if<uint16_t>(&property.second); 152ac6a4445SGunnar Mills if (value != nullptr) 153ac6a4445SGunnar Mills { 154ac6a4445SGunnar Mills aResp->res.jsonValue["ProcessorId"]["EffectiveFamily"] = 155866e4862SEd Tanous "0x" + intToHexString(*value, 4); 156ac6a4445SGunnar Mills } 157ac6a4445SGunnar Mills } 1581930fbd4SBrandon Kim else if (property.first == "EffectiveModel") 1591930fbd4SBrandon Kim { 1601930fbd4SBrandon Kim const uint16_t* value = std::get_if<uint16_t>(&property.second); 1611930fbd4SBrandon Kim if (value == nullptr) 1621930fbd4SBrandon Kim { 1631930fbd4SBrandon Kim messages::internalError(aResp->res); 1641930fbd4SBrandon Kim return; 1651930fbd4SBrandon Kim } 1661930fbd4SBrandon Kim aResp->res.jsonValue["ProcessorId"]["EffectiveModel"] = 167866e4862SEd Tanous "0x" + intToHexString(*value, 4); 1681930fbd4SBrandon Kim } 169ac6a4445SGunnar Mills else if (property.first == "Id") 170ac6a4445SGunnar Mills { 171ac6a4445SGunnar Mills const uint64_t* value = std::get_if<uint64_t>(&property.second); 172ac6a4445SGunnar Mills if (value != nullptr && *value != 0) 173ac6a4445SGunnar Mills { 174ac6a4445SGunnar Mills aResp->res 175ac6a4445SGunnar Mills .jsonValue["ProcessorId"]["IdentificationRegisters"] = 176866e4862SEd Tanous "0x" + intToHexString(*value, 16); 177ac6a4445SGunnar Mills } 178ac6a4445SGunnar Mills } 1791930fbd4SBrandon Kim else if (property.first == "Microcode") 1801930fbd4SBrandon Kim { 1811930fbd4SBrandon Kim const uint32_t* value = std::get_if<uint32_t>(&property.second); 1821930fbd4SBrandon Kim if (value == nullptr) 1831930fbd4SBrandon Kim { 1841930fbd4SBrandon Kim messages::internalError(aResp->res); 1851930fbd4SBrandon Kim return; 1861930fbd4SBrandon Kim } 1871930fbd4SBrandon Kim aResp->res.jsonValue["ProcessorId"]["MicrocodeInfo"] = 188866e4862SEd Tanous "0x" + intToHexString(*value, 8); 1891930fbd4SBrandon Kim } 1901930fbd4SBrandon Kim else if (property.first == "Step") 1911930fbd4SBrandon Kim { 1921930fbd4SBrandon Kim const uint16_t* value = std::get_if<uint16_t>(&property.second); 1931930fbd4SBrandon Kim if (value == nullptr) 1941930fbd4SBrandon Kim { 1951930fbd4SBrandon Kim messages::internalError(aResp->res); 1961930fbd4SBrandon Kim return; 1971930fbd4SBrandon Kim } 1981930fbd4SBrandon Kim aResp->res.jsonValue["ProcessorId"]["Step"] = 199866e4862SEd Tanous "0x" + intToHexString(*value, 4); 2001930fbd4SBrandon Kim } 201ac6a4445SGunnar Mills } 202ac6a4445SGunnar Mills } 203ac6a4445SGunnar Mills } 204ac6a4445SGunnar Mills 2058d1b46d7Szhanghch05 inline void getCpuDataByService(std::shared_ptr<bmcweb::AsyncResp> aResp, 206ac6a4445SGunnar Mills const std::string& cpuId, 207ac6a4445SGunnar Mills const std::string& service, 208ac6a4445SGunnar Mills const std::string& objPath) 209ac6a4445SGunnar Mills { 210ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "Get available system cpu resources by service."; 211ac6a4445SGunnar Mills 212ac6a4445SGunnar Mills crow::connections::systemBus->async_method_call( 213ac6a4445SGunnar Mills [cpuId, service, objPath, aResp{std::move(aResp)}]( 214ac6a4445SGunnar Mills const boost::system::error_code ec, 215ac6a4445SGunnar Mills const dbus::utility::ManagedObjectType& dbusData) { 216ac6a4445SGunnar Mills if (ec) 217ac6a4445SGunnar Mills { 218ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "DBUS response error"; 219ac6a4445SGunnar Mills messages::internalError(aResp->res); 220ac6a4445SGunnar Mills return; 221ac6a4445SGunnar Mills } 222ac6a4445SGunnar Mills aResp->res.jsonValue["Id"] = cpuId; 223ac6a4445SGunnar Mills aResp->res.jsonValue["Name"] = "Processor"; 224ac6a4445SGunnar Mills aResp->res.jsonValue["ProcessorType"] = "CPU"; 225ac6a4445SGunnar Mills 226ac6a4445SGunnar Mills bool slotPresent = false; 227ac6a4445SGunnar Mills std::string corePath = objPath + "/core"; 228ac6a4445SGunnar Mills size_t totalCores = 0; 229ac6a4445SGunnar Mills for (const auto& object : dbusData) 230ac6a4445SGunnar Mills { 231ac6a4445SGunnar Mills if (object.first.str == objPath) 232ac6a4445SGunnar Mills { 233ac6a4445SGunnar Mills getCpuDataByInterface(aResp, object.second); 234ac6a4445SGunnar Mills } 23511ba3979SEd Tanous else if (object.first.str.starts_with(corePath)) 236ac6a4445SGunnar Mills { 237ac6a4445SGunnar Mills for (const auto& interface : object.second) 238ac6a4445SGunnar Mills { 239002d39b4SEd Tanous if (interface.first == "xyz.openbmc_project.Inventory.Item") 240ac6a4445SGunnar Mills { 241ac6a4445SGunnar Mills for (const auto& property : interface.second) 242ac6a4445SGunnar Mills { 243ac6a4445SGunnar Mills if (property.first == "Present") 244ac6a4445SGunnar Mills { 245ac6a4445SGunnar Mills const bool* present = 246ac6a4445SGunnar Mills std::get_if<bool>(&property.second); 247ac6a4445SGunnar Mills if (present != nullptr) 248ac6a4445SGunnar Mills { 249e05aec50SEd Tanous if (*present) 250ac6a4445SGunnar Mills { 251ac6a4445SGunnar Mills slotPresent = true; 252ac6a4445SGunnar Mills totalCores++; 253ac6a4445SGunnar Mills } 254ac6a4445SGunnar Mills } 255ac6a4445SGunnar Mills } 256ac6a4445SGunnar Mills } 257ac6a4445SGunnar Mills } 258ac6a4445SGunnar Mills } 259ac6a4445SGunnar Mills } 260ac6a4445SGunnar Mills } 261ac6a4445SGunnar Mills // In getCpuDataByInterface(), state and health are set 262ac6a4445SGunnar Mills // based on the present and functional status. If core 263ac6a4445SGunnar Mills // count is zero, then it has a higher precedence. 264ac6a4445SGunnar Mills if (slotPresent) 265ac6a4445SGunnar Mills { 266ac6a4445SGunnar Mills if (totalCores == 0) 267ac6a4445SGunnar Mills { 268ac6a4445SGunnar Mills // Slot is not populated, set status end return 269ac6a4445SGunnar Mills aResp->res.jsonValue["Status"]["State"] = "Absent"; 270ac6a4445SGunnar Mills aResp->res.jsonValue["Status"]["Health"] = "OK"; 271ac6a4445SGunnar Mills } 272ac6a4445SGunnar Mills aResp->res.jsonValue["TotalCores"] = totalCores; 273ac6a4445SGunnar Mills } 274ac6a4445SGunnar Mills return; 275ac6a4445SGunnar Mills }, 276ac6a4445SGunnar Mills service, "/xyz/openbmc_project/inventory", 277ac6a4445SGunnar Mills "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 278ac6a4445SGunnar Mills } 279ac6a4445SGunnar Mills 2808d1b46d7Szhanghch05 inline void getCpuAssetData(std::shared_ptr<bmcweb::AsyncResp> aResp, 281ac6a4445SGunnar Mills const std::string& service, 282ac6a4445SGunnar Mills const std::string& objPath) 283ac6a4445SGunnar Mills { 284ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "Get Cpu Asset Data"; 285*351053f2SKrzysztof Grobelny sdbusplus::asio::getAllProperties( 286*351053f2SKrzysztof Grobelny *crow::connections::systemBus, service, objPath, 287*351053f2SKrzysztof Grobelny "xyz.openbmc_project.Inventory.Decorator.Asset", 288ac6a4445SGunnar Mills [objPath, aResp{std::move(aResp)}]( 289ac6a4445SGunnar Mills const boost::system::error_code ec, 290*351053f2SKrzysztof Grobelny const dbus::utility::DBusPropertiesMap& properties) { 291ac6a4445SGunnar Mills if (ec) 292ac6a4445SGunnar Mills { 293ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "DBUS response error"; 294ac6a4445SGunnar Mills messages::internalError(aResp->res); 295ac6a4445SGunnar Mills return; 296ac6a4445SGunnar Mills } 297ac6a4445SGunnar Mills 298*351053f2SKrzysztof Grobelny const std::string* serialNumber = nullptr; 299*351053f2SKrzysztof Grobelny const std::string* model = nullptr; 300*351053f2SKrzysztof Grobelny const std::string* manufacturer = nullptr; 301*351053f2SKrzysztof Grobelny const std::string* partNumber = nullptr; 302*351053f2SKrzysztof Grobelny const std::string* sparePartNumber = nullptr; 303*351053f2SKrzysztof Grobelny 304*351053f2SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 305*351053f2SKrzysztof Grobelny dbus_utils::UnpackErrorPrinter(), properties, "SerialNumber", 306*351053f2SKrzysztof Grobelny serialNumber, "Model", model, "Manufacturer", manufacturer, 307*351053f2SKrzysztof Grobelny "PartNumber", partNumber, "SparePartNumber", sparePartNumber); 308*351053f2SKrzysztof Grobelny 309*351053f2SKrzysztof Grobelny if (!success) 310ac6a4445SGunnar Mills { 311*351053f2SKrzysztof Grobelny messages::internalError(aResp->res); 312*351053f2SKrzysztof Grobelny return; 313ac6a4445SGunnar Mills } 314*351053f2SKrzysztof Grobelny 315*351053f2SKrzysztof Grobelny if (serialNumber != nullptr && !serialNumber->empty()) 316ac6a4445SGunnar Mills { 317*351053f2SKrzysztof Grobelny aResp->res.jsonValue["SerialNumber"] = *serialNumber; 318*351053f2SKrzysztof Grobelny } 319*351053f2SKrzysztof Grobelny 320*351053f2SKrzysztof Grobelny if ((model != nullptr) && !model->empty()) 321ac6a4445SGunnar Mills { 322ac6a4445SGunnar Mills aResp->res.jsonValue["Model"] = *model; 323ac6a4445SGunnar Mills } 324ac6a4445SGunnar Mills 325*351053f2SKrzysztof Grobelny if (manufacturer != nullptr) 326ac6a4445SGunnar Mills { 327*351053f2SKrzysztof Grobelny aResp->res.jsonValue["Manufacturer"] = *manufacturer; 328ac6a4445SGunnar Mills 329ac6a4445SGunnar Mills // Otherwise would be unexpected. 330*351053f2SKrzysztof Grobelny if (manufacturer->find("Intel") != std::string::npos) 331ac6a4445SGunnar Mills { 332002d39b4SEd Tanous aResp->res.jsonValue["ProcessorArchitecture"] = "x86"; 333ac6a4445SGunnar Mills aResp->res.jsonValue["InstructionSet"] = "x86-64"; 334ac6a4445SGunnar Mills } 335*351053f2SKrzysztof Grobelny else if (manufacturer->find("IBM") != std::string::npos) 336ac6a4445SGunnar Mills { 337002d39b4SEd Tanous aResp->res.jsonValue["ProcessorArchitecture"] = "Power"; 338ac6a4445SGunnar Mills aResp->res.jsonValue["InstructionSet"] = "PowerISA"; 339ac6a4445SGunnar Mills } 340ac6a4445SGunnar Mills } 341cba4f448SSunnySrivastava1984 342*351053f2SKrzysztof Grobelny if (partNumber != nullptr) 343cba4f448SSunnySrivastava1984 { 344cba4f448SSunnySrivastava1984 aResp->res.jsonValue["PartNumber"] = *partNumber; 345cba4f448SSunnySrivastava1984 } 346cba4f448SSunnySrivastava1984 347*351053f2SKrzysztof Grobelny if (sparePartNumber != nullptr) 348cba4f448SSunnySrivastava1984 { 349cba4f448SSunnySrivastava1984 aResp->res.jsonValue["SparePartNumber"] = *sparePartNumber; 350cba4f448SSunnySrivastava1984 } 351*351053f2SKrzysztof Grobelny }); 352ac6a4445SGunnar Mills } 353ac6a4445SGunnar Mills 3548d1b46d7Szhanghch05 inline void getCpuRevisionData(std::shared_ptr<bmcweb::AsyncResp> aResp, 355ac6a4445SGunnar Mills const std::string& service, 356ac6a4445SGunnar Mills const std::string& objPath) 357ac6a4445SGunnar Mills { 358ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "Get Cpu Revision Data"; 359*351053f2SKrzysztof Grobelny sdbusplus::asio::getAllProperties( 360*351053f2SKrzysztof Grobelny *crow::connections::systemBus, service, objPath, 361*351053f2SKrzysztof Grobelny "xyz.openbmc_project.Inventory.Decorator.Revision", 362ac6a4445SGunnar Mills [objPath, aResp{std::move(aResp)}]( 363ac6a4445SGunnar Mills const boost::system::error_code ec, 364*351053f2SKrzysztof Grobelny const dbus::utility::DBusPropertiesMap& properties) { 365ac6a4445SGunnar Mills if (ec) 366ac6a4445SGunnar Mills { 367ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "DBUS response error"; 368ac6a4445SGunnar Mills messages::internalError(aResp->res); 369ac6a4445SGunnar Mills return; 370ac6a4445SGunnar Mills } 371ac6a4445SGunnar Mills 372*351053f2SKrzysztof Grobelny const std::string* version = nullptr; 373*351053f2SKrzysztof Grobelny 374*351053f2SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 375*351053f2SKrzysztof Grobelny dbus_utils::UnpackErrorPrinter(), properties, "Version", version); 376*351053f2SKrzysztof Grobelny 377*351053f2SKrzysztof Grobelny if (!success) 378ac6a4445SGunnar Mills { 379*351053f2SKrzysztof Grobelny messages::internalError(aResp->res); 380*351053f2SKrzysztof Grobelny return; 381*351053f2SKrzysztof Grobelny } 382*351053f2SKrzysztof Grobelny 383*351053f2SKrzysztof Grobelny if (version != nullptr) 384ac6a4445SGunnar Mills { 385*351053f2SKrzysztof Grobelny aResp->res.jsonValue["Version"] = *version; 386ac6a4445SGunnar Mills } 387*351053f2SKrzysztof Grobelny }); 388ac6a4445SGunnar Mills } 389ac6a4445SGunnar Mills 3908d1b46d7Szhanghch05 inline void getAcceleratorDataByService( 3918d1b46d7Szhanghch05 std::shared_ptr<bmcweb::AsyncResp> aResp, const std::string& acclrtrId, 3928d1b46d7Szhanghch05 const std::string& service, const std::string& objPath) 393ac6a4445SGunnar Mills { 394ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG 395ac6a4445SGunnar Mills << "Get available system Accelerator resources by service."; 396*351053f2SKrzysztof Grobelny sdbusplus::asio::getAllProperties( 397*351053f2SKrzysztof Grobelny *crow::connections::systemBus, service, objPath, "", 398ac6a4445SGunnar Mills [acclrtrId, aResp{std::move(aResp)}]( 399ac6a4445SGunnar Mills const boost::system::error_code ec, 400*351053f2SKrzysztof Grobelny const dbus::utility::DBusPropertiesMap& properties) { 401ac6a4445SGunnar Mills if (ec) 402ac6a4445SGunnar Mills { 403ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "DBUS response error"; 404ac6a4445SGunnar Mills messages::internalError(aResp->res); 405ac6a4445SGunnar Mills return; 406ac6a4445SGunnar Mills } 407ac6a4445SGunnar Mills 408*351053f2SKrzysztof Grobelny const bool* functional = nullptr; 409*351053f2SKrzysztof Grobelny const bool* present = nullptr; 410*351053f2SKrzysztof Grobelny 411*351053f2SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 412*351053f2SKrzysztof Grobelny dbus_utils::UnpackErrorPrinter(), properties, "Functional", 413*351053f2SKrzysztof Grobelny functional, "Present", present); 414*351053f2SKrzysztof Grobelny 415*351053f2SKrzysztof Grobelny if (!success) 416ac6a4445SGunnar Mills { 417*351053f2SKrzysztof Grobelny messages::internalError(aResp->res); 418*351053f2SKrzysztof Grobelny return; 419ac6a4445SGunnar Mills } 420ac6a4445SGunnar Mills 421ac6a4445SGunnar Mills std::string state = "Enabled"; 422ac6a4445SGunnar Mills std::string health = "OK"; 423ac6a4445SGunnar Mills 424*351053f2SKrzysztof Grobelny if (present != nullptr && !*present) 425ac6a4445SGunnar Mills { 426ac6a4445SGunnar Mills state = "Absent"; 427ac6a4445SGunnar Mills } 428ac6a4445SGunnar Mills 429*351053f2SKrzysztof Grobelny if (functional != nullptr && !*functional) 430ac6a4445SGunnar Mills { 431ac6a4445SGunnar Mills if (state == "Enabled") 432ac6a4445SGunnar Mills { 433ac6a4445SGunnar Mills health = "Critical"; 434ac6a4445SGunnar Mills } 435ac6a4445SGunnar Mills } 436ac6a4445SGunnar Mills 437*351053f2SKrzysztof Grobelny aResp->res.jsonValue["Id"] = acclrtrId; 438*351053f2SKrzysztof Grobelny aResp->res.jsonValue["Name"] = "Processor"; 439ac6a4445SGunnar Mills aResp->res.jsonValue["Status"]["State"] = state; 440ac6a4445SGunnar Mills aResp->res.jsonValue["Status"]["Health"] = health; 441ac6a4445SGunnar Mills aResp->res.jsonValue["ProcessorType"] = "Accelerator"; 442*351053f2SKrzysztof Grobelny }); 443ac6a4445SGunnar Mills } 444ac6a4445SGunnar Mills 445dba0c291SJonathan Doman // OperatingConfig D-Bus Types 446dba0c291SJonathan Doman using TurboProfileProperty = std::vector<std::tuple<uint32_t, size_t>>; 447dba0c291SJonathan Doman using BaseSpeedPrioritySettingsProperty = 448dba0c291SJonathan Doman std::vector<std::tuple<uint32_t, std::vector<uint32_t>>>; 449dba0c291SJonathan Doman // uint32_t and size_t may or may not be the same type, requiring a dedup'd 450dba0c291SJonathan Doman // variant 451dba0c291SJonathan Doman 452dba0c291SJonathan Doman /** 453dba0c291SJonathan Doman * Fill out the HighSpeedCoreIDs in a Processor resource from the given 454dba0c291SJonathan Doman * OperatingConfig D-Bus property. 455dba0c291SJonathan Doman * 456dba0c291SJonathan Doman * @param[in,out] aResp Async HTTP response. 457dba0c291SJonathan Doman * @param[in] baseSpeedSettings Full list of base speed priority groups, 458dba0c291SJonathan Doman * to use to determine the list of high 459dba0c291SJonathan Doman * speed cores. 460dba0c291SJonathan Doman */ 461dba0c291SJonathan Doman inline void highSpeedCoreIdsHandler( 4628d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& aResp, 463dba0c291SJonathan Doman const BaseSpeedPrioritySettingsProperty& baseSpeedSettings) 464dba0c291SJonathan Doman { 465dba0c291SJonathan Doman // The D-Bus property does not indicate which bucket is the "high 466dba0c291SJonathan Doman // priority" group, so let's discern that by looking for the one with 467dba0c291SJonathan Doman // highest base frequency. 468dba0c291SJonathan Doman auto highPriorityGroup = baseSpeedSettings.cend(); 469dba0c291SJonathan Doman uint32_t highestBaseSpeed = 0; 470dba0c291SJonathan Doman for (auto it = baseSpeedSettings.cbegin(); it != baseSpeedSettings.cend(); 471dba0c291SJonathan Doman ++it) 472dba0c291SJonathan Doman { 473dba0c291SJonathan Doman const uint32_t baseFreq = std::get<uint32_t>(*it); 474dba0c291SJonathan Doman if (baseFreq > highestBaseSpeed) 475dba0c291SJonathan Doman { 476dba0c291SJonathan Doman highestBaseSpeed = baseFreq; 477dba0c291SJonathan Doman highPriorityGroup = it; 478dba0c291SJonathan Doman } 479dba0c291SJonathan Doman } 480dba0c291SJonathan Doman 481dba0c291SJonathan Doman nlohmann::json& jsonCoreIds = aResp->res.jsonValue["HighSpeedCoreIDs"]; 482dba0c291SJonathan Doman jsonCoreIds = nlohmann::json::array(); 483dba0c291SJonathan Doman 484dba0c291SJonathan Doman // There may not be any entries in the D-Bus property, so only populate 485dba0c291SJonathan Doman // if there was actually something there. 486dba0c291SJonathan Doman if (highPriorityGroup != baseSpeedSettings.cend()) 487dba0c291SJonathan Doman { 488dba0c291SJonathan Doman jsonCoreIds = std::get<std::vector<uint32_t>>(*highPriorityGroup); 489dba0c291SJonathan Doman } 490dba0c291SJonathan Doman } 491dba0c291SJonathan Doman 492dba0c291SJonathan Doman /** 493dba0c291SJonathan Doman * Fill out OperatingConfig related items in a Processor resource by requesting 494dba0c291SJonathan Doman * data from the given D-Bus object. 495dba0c291SJonathan Doman * 496dba0c291SJonathan Doman * @param[in,out] aResp Async HTTP response. 497dba0c291SJonathan Doman * @param[in] cpuId CPU D-Bus name. 498dba0c291SJonathan Doman * @param[in] service D-Bus service to query. 499dba0c291SJonathan Doman * @param[in] objPath D-Bus object to query. 500dba0c291SJonathan Doman */ 5018d1b46d7Szhanghch05 inline void getCpuConfigData(const std::shared_ptr<bmcweb::AsyncResp>& aResp, 502dba0c291SJonathan Doman const std::string& cpuId, 503dba0c291SJonathan Doman const std::string& service, 504dba0c291SJonathan Doman const std::string& objPath) 505dba0c291SJonathan Doman { 506dba0c291SJonathan Doman BMCWEB_LOG_INFO << "Getting CPU operating configs for " << cpuId; 507dba0c291SJonathan Doman 508dba0c291SJonathan Doman // First, GetAll CurrentOperatingConfig properties on the object 509*351053f2SKrzysztof Grobelny sdbusplus::asio::getAllProperties( 510*351053f2SKrzysztof Grobelny *crow::connections::systemBus, service, objPath, 511*351053f2SKrzysztof Grobelny "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig", 512*351053f2SKrzysztof Grobelny [aResp, cpuId, 513*351053f2SKrzysztof Grobelny service](const boost::system::error_code ec, 514*351053f2SKrzysztof Grobelny const dbus::utility::DBusPropertiesMap& properties) { 515dba0c291SJonathan Doman if (ec) 516dba0c291SJonathan Doman { 517002d39b4SEd Tanous BMCWEB_LOG_WARNING << "D-Bus error: " << ec << ", " << ec.message(); 518dba0c291SJonathan Doman messages::internalError(aResp->res); 519dba0c291SJonathan Doman return; 520dba0c291SJonathan Doman } 521dba0c291SJonathan Doman 522dba0c291SJonathan Doman nlohmann::json& json = aResp->res.jsonValue; 523dba0c291SJonathan Doman 524*351053f2SKrzysztof Grobelny const sdbusplus::message::object_path* appliedConfig = nullptr; 525*351053f2SKrzysztof Grobelny const bool* baseSpeedPriorityEnabled = nullptr; 526*351053f2SKrzysztof Grobelny 527*351053f2SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 528*351053f2SKrzysztof Grobelny dbus_utils::UnpackErrorPrinter(), properties, "AppliedConfig", 529*351053f2SKrzysztof Grobelny appliedConfig, "BaseSpeedPriorityEnabled", 530*351053f2SKrzysztof Grobelny baseSpeedPriorityEnabled); 531*351053f2SKrzysztof Grobelny 532*351053f2SKrzysztof Grobelny if (!success) 533dba0c291SJonathan Doman { 534*351053f2SKrzysztof Grobelny messages::internalError(aResp->res); 535*351053f2SKrzysztof Grobelny return; 536dba0c291SJonathan Doman } 537dba0c291SJonathan Doman 538*351053f2SKrzysztof Grobelny if (appliedConfig != nullptr) 539*351053f2SKrzysztof Grobelny { 540*351053f2SKrzysztof Grobelny const std::string& dbusPath = appliedConfig->str; 541*351053f2SKrzysztof Grobelny std::string uri = "/redfish/v1/Systems/system/Processors/" + cpuId + 542*351053f2SKrzysztof Grobelny "/OperatingConfigs"; 5431476687dSEd Tanous nlohmann::json::object_t operatingConfig; 5441476687dSEd Tanous operatingConfig["@odata.id"] = uri; 5451476687dSEd Tanous json["OperatingConfigs"] = std::move(operatingConfig); 546dba0c291SJonathan Doman 547dba0c291SJonathan Doman // Reuse the D-Bus config object name for the Redfish 548dba0c291SJonathan Doman // URI 549dba0c291SJonathan Doman size_t baseNamePos = dbusPath.rfind('/'); 550dba0c291SJonathan Doman if (baseNamePos == std::string::npos || 551dba0c291SJonathan Doman baseNamePos == (dbusPath.size() - 1)) 552dba0c291SJonathan Doman { 553dba0c291SJonathan Doman // If the AppliedConfig was somehow not a valid path, 554dba0c291SJonathan Doman // skip adding any more properties, since everything 555dba0c291SJonathan Doman // else is tied to this applied config. 556dba0c291SJonathan Doman messages::internalError(aResp->res); 557*351053f2SKrzysztof Grobelny return; 558dba0c291SJonathan Doman } 559dba0c291SJonathan Doman uri += '/'; 560dba0c291SJonathan Doman uri += dbusPath.substr(baseNamePos + 1); 5611476687dSEd Tanous nlohmann::json::object_t appliedOperatingConfig; 5621476687dSEd Tanous appliedOperatingConfig["@odata.id"] = uri; 563*351053f2SKrzysztof Grobelny json["AppliedOperatingConfig"] = std::move(appliedOperatingConfig); 564dba0c291SJonathan Doman 565dba0c291SJonathan Doman // Once we found the current applied config, queue another 566dba0c291SJonathan Doman // request to read the base freq core ids out of that 567dba0c291SJonathan Doman // config. 568002d39b4SEd Tanous sdbusplus::asio::getProperty<BaseSpeedPrioritySettingsProperty>( 5691e1e598dSJonathan Doman *crow::connections::systemBus, service, dbusPath, 5701e1e598dSJonathan Doman "xyz.openbmc_project.Inventory.Item.Cpu." 5711e1e598dSJonathan Doman "OperatingConfig", 5721e1e598dSJonathan Doman "BaseSpeedPrioritySettings", 573*351053f2SKrzysztof Grobelny [aResp]( 574*351053f2SKrzysztof Grobelny const boost::system::error_code ec2, 575*351053f2SKrzysztof Grobelny const BaseSpeedPrioritySettingsProperty& baseSpeedList) { 5768a592810SEd Tanous if (ec2) 577dba0c291SJonathan Doman { 578*351053f2SKrzysztof Grobelny BMCWEB_LOG_WARNING << "D-Bus Property Get error: " << ec2; 579dba0c291SJonathan Doman messages::internalError(aResp->res); 580dba0c291SJonathan Doman return; 581dba0c291SJonathan Doman } 5821e1e598dSJonathan Doman 5831e1e598dSJonathan Doman highSpeedCoreIdsHandler(aResp, baseSpeedList); 5841e1e598dSJonathan Doman }); 585dba0c291SJonathan Doman } 586*351053f2SKrzysztof Grobelny 587*351053f2SKrzysztof Grobelny if (baseSpeedPriorityEnabled != nullptr) 588dba0c291SJonathan Doman { 589dba0c291SJonathan Doman json["BaseSpeedPriorityState"] = 590*351053f2SKrzysztof Grobelny *baseSpeedPriorityEnabled ? "Enabled" : "Disabled"; 591dba0c291SJonathan Doman } 592*351053f2SKrzysztof Grobelny }); 593dba0c291SJonathan Doman } 594dba0c291SJonathan Doman 595cba4f448SSunnySrivastava1984 /** 596cba4f448SSunnySrivastava1984 * @brief Fill out location info of a processor by 597cba4f448SSunnySrivastava1984 * requesting data from the given D-Bus object. 598cba4f448SSunnySrivastava1984 * 599cba4f448SSunnySrivastava1984 * @param[in,out] aResp Async HTTP response. 600cba4f448SSunnySrivastava1984 * @param[in] service D-Bus service to query. 601cba4f448SSunnySrivastava1984 * @param[in] objPath D-Bus object to query. 602cba4f448SSunnySrivastava1984 */ 6038d1b46d7Szhanghch05 inline void getCpuLocationCode(std::shared_ptr<bmcweb::AsyncResp> aResp, 604cba4f448SSunnySrivastava1984 const std::string& service, 605cba4f448SSunnySrivastava1984 const std::string& objPath) 606cba4f448SSunnySrivastava1984 { 607cba4f448SSunnySrivastava1984 BMCWEB_LOG_DEBUG << "Get Cpu Location Data"; 6081e1e598dSJonathan Doman sdbusplus::asio::getProperty<std::string>( 6091e1e598dSJonathan Doman *crow::connections::systemBus, service, objPath, 6101e1e598dSJonathan Doman "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode", 6111e1e598dSJonathan Doman [objPath, aResp{std::move(aResp)}](const boost::system::error_code ec, 6121e1e598dSJonathan Doman const std::string& property) { 613cba4f448SSunnySrivastava1984 if (ec) 614cba4f448SSunnySrivastava1984 { 615cba4f448SSunnySrivastava1984 BMCWEB_LOG_DEBUG << "DBUS response error"; 616cba4f448SSunnySrivastava1984 messages::internalError(aResp->res); 617cba4f448SSunnySrivastava1984 return; 618cba4f448SSunnySrivastava1984 } 619cba4f448SSunnySrivastava1984 620cba4f448SSunnySrivastava1984 aResp->res.jsonValue["Location"]["PartLocation"]["ServiceLabel"] = 6211e1e598dSJonathan Doman property; 6221e1e598dSJonathan Doman }); 623cba4f448SSunnySrivastava1984 } 624cba4f448SSunnySrivastava1984 625c951448aSJonathan Doman /** 62649e429caSJonathan Doman * Populate the unique identifier in a Processor resource by requesting data 62749e429caSJonathan Doman * from the given D-Bus object. 62849e429caSJonathan Doman * 62949e429caSJonathan Doman * @param[in,out] aResp Async HTTP response. 63049e429caSJonathan Doman * @param[in] service D-Bus service to query. 63149e429caSJonathan Doman * @param[in] objPath D-Bus object to query. 63249e429caSJonathan Doman */ 63349e429caSJonathan Doman inline void getCpuUniqueId(const std::shared_ptr<bmcweb::AsyncResp>& aResp, 63449e429caSJonathan Doman const std::string& service, 63549e429caSJonathan Doman const std::string& objectPath) 63649e429caSJonathan Doman { 63749e429caSJonathan Doman BMCWEB_LOG_DEBUG << "Get CPU UniqueIdentifier"; 6381e1e598dSJonathan Doman sdbusplus::asio::getProperty<std::string>( 6391e1e598dSJonathan Doman *crow::connections::systemBus, service, objectPath, 6401e1e598dSJonathan Doman "xyz.openbmc_project.Inventory.Decorator.UniqueIdentifier", 6411e1e598dSJonathan Doman "UniqueIdentifier", 6421e1e598dSJonathan Doman [aResp](boost::system::error_code ec, const std::string& id) { 6431e1e598dSJonathan Doman if (ec) 64449e429caSJonathan Doman { 64549e429caSJonathan Doman BMCWEB_LOG_ERROR << "Failed to read cpu unique id: " << ec; 64649e429caSJonathan Doman messages::internalError(aResp->res); 64749e429caSJonathan Doman return; 64849e429caSJonathan Doman } 649002d39b4SEd Tanous aResp->res.jsonValue["ProcessorId"]["ProtectedIdentificationNumber"] = 650002d39b4SEd Tanous id; 6511e1e598dSJonathan Doman }); 65249e429caSJonathan Doman } 65349e429caSJonathan Doman 65449e429caSJonathan Doman /** 655c951448aSJonathan Doman * Find the D-Bus object representing the requested Processor, and call the 656c951448aSJonathan Doman * handler with the results. If matching object is not found, add 404 error to 657c951448aSJonathan Doman * response and don't call the handler. 658c951448aSJonathan Doman * 659c951448aSJonathan Doman * @param[in,out] resp Async HTTP response. 660c951448aSJonathan Doman * @param[in] processorId Redfish Processor Id. 661c951448aSJonathan Doman * @param[in] handler Callback to continue processing request upon 662c951448aSJonathan Doman * successfully finding object. 663c951448aSJonathan Doman */ 664c951448aSJonathan Doman template <typename Handler> 6658d1b46d7Szhanghch05 inline void getProcessorObject(const std::shared_ptr<bmcweb::AsyncResp>& resp, 666c951448aSJonathan Doman const std::string& processorId, 667c951448aSJonathan Doman Handler&& handler) 668ac6a4445SGunnar Mills { 669ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "Get available system processor resources."; 670ac6a4445SGunnar Mills 671c951448aSJonathan Doman // GetSubTree on all interfaces which provide info about a Processor 672ac6a4445SGunnar Mills crow::connections::systemBus->async_method_call( 673c951448aSJonathan Doman [resp, processorId, handler = std::forward<Handler>(handler)]( 674c951448aSJonathan Doman boost::system::error_code ec, 6755df6eda2SShantappa Teekappanavar const dbus::utility::MapperGetSubTreeResponse& subtree) mutable { 676ac6a4445SGunnar Mills if (ec) 677ac6a4445SGunnar Mills { 678c951448aSJonathan Doman BMCWEB_LOG_DEBUG << "DBUS response error: " << ec; 679c951448aSJonathan Doman messages::internalError(resp->res); 680ac6a4445SGunnar Mills return; 681ac6a4445SGunnar Mills } 6822bab9831SJonathan Doman for (const auto& [objectPath, serviceMap] : subtree) 683ac6a4445SGunnar Mills { 6842bab9831SJonathan Doman // Ignore any objects which don't end with our desired cpu name 68511ba3979SEd Tanous if (!objectPath.ends_with(processorId)) 686ac6a4445SGunnar Mills { 6872bab9831SJonathan Doman continue; 688ac6a4445SGunnar Mills } 6892bab9831SJonathan Doman 690c951448aSJonathan Doman bool found = false; 691c951448aSJonathan Doman // Filter out objects that don't have the CPU-specific 692c951448aSJonathan Doman // interfaces to make sure we can return 404 on non-CPUs 693c951448aSJonathan Doman // (e.g. /redfish/../Processors/dimm0) 6942bab9831SJonathan Doman for (const auto& [serviceName, interfaceList] : serviceMap) 695ac6a4445SGunnar Mills { 696c951448aSJonathan Doman if (std::find_first_of( 697c951448aSJonathan Doman interfaceList.begin(), interfaceList.end(), 698c951448aSJonathan Doman processorInterfaces.begin(), 699c951448aSJonathan Doman processorInterfaces.end()) != interfaceList.end()) 7002bab9831SJonathan Doman { 701c951448aSJonathan Doman found = true; 702c951448aSJonathan Doman break; 703c951448aSJonathan Doman } 704c951448aSJonathan Doman } 705c951448aSJonathan Doman 706c951448aSJonathan Doman if (!found) 7072bab9831SJonathan Doman { 708c951448aSJonathan Doman continue; 709ac6a4445SGunnar Mills } 710c951448aSJonathan Doman 711c951448aSJonathan Doman // Process the first object which does match our cpu name and 712c951448aSJonathan Doman // required interfaces, and potentially ignore any other 713c951448aSJonathan Doman // matching objects. Assume all interfaces we want to process 714c951448aSJonathan Doman // must be on the same object path. 715c951448aSJonathan Doman 7168a592810SEd Tanous handler(objectPath, serviceMap); 717ac6a4445SGunnar Mills return; 718ac6a4445SGunnar Mills } 719c951448aSJonathan Doman messages::resourceNotFound(resp->res, "Processor", processorId); 720ac6a4445SGunnar Mills }, 721ac6a4445SGunnar Mills "xyz.openbmc_project.ObjectMapper", 722ac6a4445SGunnar Mills "/xyz/openbmc_project/object_mapper", 723ac6a4445SGunnar Mills "xyz.openbmc_project.ObjectMapper", "GetSubTree", 7242bab9831SJonathan Doman "/xyz/openbmc_project/inventory", 0, 72549e429caSJonathan Doman std::array<const char*, 8>{ 72671b82f26SSharad Yadav "xyz.openbmc_project.Common.UUID", 7272bab9831SJonathan Doman "xyz.openbmc_project.Inventory.Decorator.Asset", 7282bab9831SJonathan Doman "xyz.openbmc_project.Inventory.Decorator.Revision", 7292bab9831SJonathan Doman "xyz.openbmc_project.Inventory.Item.Cpu", 730cba4f448SSunnySrivastava1984 "xyz.openbmc_project.Inventory.Decorator.LocationCode", 731dba0c291SJonathan Doman "xyz.openbmc_project.Inventory.Item.Accelerator", 73249e429caSJonathan Doman "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig", 73349e429caSJonathan Doman "xyz.openbmc_project.Inventory.Decorator.UniqueIdentifier"}); 734ac6a4445SGunnar Mills } 735ac6a4445SGunnar Mills 7368d1b46d7Szhanghch05 inline void getProcessorData(const std::shared_ptr<bmcweb::AsyncResp>& aResp, 737c951448aSJonathan Doman const std::string& processorId, 738c951448aSJonathan Doman const std::string& objectPath, 7395df6eda2SShantappa Teekappanavar const dbus::utility::MapperServiceMap& serviceMap) 740c951448aSJonathan Doman { 741c951448aSJonathan Doman for (const auto& [serviceName, interfaceList] : serviceMap) 742c951448aSJonathan Doman { 743c951448aSJonathan Doman for (const auto& interface : interfaceList) 744c951448aSJonathan Doman { 745c951448aSJonathan Doman if (interface == "xyz.openbmc_project.Inventory.Decorator.Asset") 746c951448aSJonathan Doman { 747c951448aSJonathan Doman getCpuAssetData(aResp, serviceName, objectPath); 748c951448aSJonathan Doman } 7490fda0f12SGeorge Liu else if (interface == 7500fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.Revision") 751c951448aSJonathan Doman { 752c951448aSJonathan Doman getCpuRevisionData(aResp, serviceName, objectPath); 753c951448aSJonathan Doman } 754c951448aSJonathan Doman else if (interface == "xyz.openbmc_project.Inventory.Item.Cpu") 755c951448aSJonathan Doman { 756c951448aSJonathan Doman getCpuDataByService(aResp, processorId, serviceName, 757c951448aSJonathan Doman objectPath); 758c951448aSJonathan Doman } 7590fda0f12SGeorge Liu else if (interface == 7600fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Item.Accelerator") 761c951448aSJonathan Doman { 762c951448aSJonathan Doman getAcceleratorDataByService(aResp, processorId, serviceName, 763c951448aSJonathan Doman objectPath); 764c951448aSJonathan Doman } 7650fda0f12SGeorge Liu else if ( 7660fda0f12SGeorge Liu interface == 7670fda0f12SGeorge Liu "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig") 768c951448aSJonathan Doman { 769c951448aSJonathan Doman getCpuConfigData(aResp, processorId, serviceName, objectPath); 770c951448aSJonathan Doman } 7710fda0f12SGeorge Liu else if (interface == 7720fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.LocationCode") 773c951448aSJonathan Doman { 774c951448aSJonathan Doman getCpuLocationCode(aResp, serviceName, objectPath); 775c951448aSJonathan Doman } 77671b82f26SSharad Yadav else if (interface == "xyz.openbmc_project.Common.UUID") 77771b82f26SSharad Yadav { 77871b82f26SSharad Yadav getProcessorUUID(aResp, serviceName, objectPath); 77971b82f26SSharad Yadav } 7800fda0f12SGeorge Liu else if (interface == 7810fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.UniqueIdentifier") 78249e429caSJonathan Doman { 78349e429caSJonathan Doman getCpuUniqueId(aResp, serviceName, objectPath); 78449e429caSJonathan Doman } 785c951448aSJonathan Doman } 786c951448aSJonathan Doman } 787c951448aSJonathan Doman } 788c951448aSJonathan Doman 789dba0c291SJonathan Doman /** 790dba0c291SJonathan Doman * Request all the properties for the given D-Bus object and fill out the 791dba0c291SJonathan Doman * related entries in the Redfish OperatingConfig response. 792dba0c291SJonathan Doman * 793dba0c291SJonathan Doman * @param[in,out] aResp Async HTTP response. 794dba0c291SJonathan Doman * @param[in] service D-Bus service name to query. 795dba0c291SJonathan Doman * @param[in] objPath D-Bus object to query. 796dba0c291SJonathan Doman */ 7978d1b46d7Szhanghch05 inline void 7988d1b46d7Szhanghch05 getOperatingConfigData(const std::shared_ptr<bmcweb::AsyncResp>& aResp, 799dba0c291SJonathan Doman const std::string& service, 800dba0c291SJonathan Doman const std::string& objPath) 801dba0c291SJonathan Doman { 802*351053f2SKrzysztof Grobelny sdbusplus::asio::getAllProperties( 803*351053f2SKrzysztof Grobelny *crow::connections::systemBus, service, objPath, 804*351053f2SKrzysztof Grobelny "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig", 805914e2d5dSEd Tanous [aResp](const boost::system::error_code ec, 806*351053f2SKrzysztof Grobelny const dbus::utility::DBusPropertiesMap& properties) { 807dba0c291SJonathan Doman if (ec) 808dba0c291SJonathan Doman { 809002d39b4SEd Tanous BMCWEB_LOG_WARNING << "D-Bus error: " << ec << ", " << ec.message(); 810dba0c291SJonathan Doman messages::internalError(aResp->res); 811dba0c291SJonathan Doman return; 812dba0c291SJonathan Doman } 813dba0c291SJonathan Doman 814*351053f2SKrzysztof Grobelny const size_t* availableCoreCount = nullptr; 815*351053f2SKrzysztof Grobelny const uint32_t* baseSpeed = nullptr; 816*351053f2SKrzysztof Grobelny const uint32_t* maxJunctionTemperature = nullptr; 817*351053f2SKrzysztof Grobelny const uint32_t* maxSpeed = nullptr; 818*351053f2SKrzysztof Grobelny const uint32_t* powerLimit = nullptr; 819*351053f2SKrzysztof Grobelny const TurboProfileProperty* turboProfile = nullptr; 820*351053f2SKrzysztof Grobelny const BaseSpeedPrioritySettingsProperty* baseSpeedPrioritySettings = 821*351053f2SKrzysztof Grobelny nullptr; 822*351053f2SKrzysztof Grobelny 823*351053f2SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 824*351053f2SKrzysztof Grobelny dbus_utils::UnpackErrorPrinter(), properties, "AvailableCoreCount", 825*351053f2SKrzysztof Grobelny availableCoreCount, "BaseSpeed", baseSpeed, 826*351053f2SKrzysztof Grobelny "MaxJunctionTemperature", maxJunctionTemperature, "MaxSpeed", 827*351053f2SKrzysztof Grobelny maxSpeed, "PowerLimit", powerLimit, "TurboProfile", turboProfile, 828*351053f2SKrzysztof Grobelny "BaseSpeedPrioritySettings", baseSpeedPrioritySettings); 829*351053f2SKrzysztof Grobelny 830*351053f2SKrzysztof Grobelny if (!success) 831dba0c291SJonathan Doman { 832*351053f2SKrzysztof Grobelny messages::internalError(aResp->res); 833*351053f2SKrzysztof Grobelny return; 834dba0c291SJonathan Doman } 835dba0c291SJonathan Doman 836*351053f2SKrzysztof Grobelny nlohmann::json& json = aResp->res.jsonValue; 837*351053f2SKrzysztof Grobelny 838*351053f2SKrzysztof Grobelny if (availableCoreCount != nullptr) 839*351053f2SKrzysztof Grobelny { 840*351053f2SKrzysztof Grobelny json["TotalAvailableCoreCount"] = *availableCoreCount; 841*351053f2SKrzysztof Grobelny } 842*351053f2SKrzysztof Grobelny 843*351053f2SKrzysztof Grobelny if (baseSpeed != nullptr) 844*351053f2SKrzysztof Grobelny { 845*351053f2SKrzysztof Grobelny json["BaseSpeedMHz"] = *baseSpeed; 846*351053f2SKrzysztof Grobelny } 847*351053f2SKrzysztof Grobelny 848*351053f2SKrzysztof Grobelny if (maxJunctionTemperature != nullptr) 849*351053f2SKrzysztof Grobelny { 850*351053f2SKrzysztof Grobelny json["MaxJunctionTemperatureCelsius"] = *maxJunctionTemperature; 851*351053f2SKrzysztof Grobelny } 852*351053f2SKrzysztof Grobelny 853*351053f2SKrzysztof Grobelny if (maxSpeed != nullptr) 854*351053f2SKrzysztof Grobelny { 855*351053f2SKrzysztof Grobelny json["MaxSpeedMHz"] = *maxSpeed; 856*351053f2SKrzysztof Grobelny } 857*351053f2SKrzysztof Grobelny 858*351053f2SKrzysztof Grobelny if (powerLimit != nullptr) 859*351053f2SKrzysztof Grobelny { 860*351053f2SKrzysztof Grobelny json["TDPWatts"] = *powerLimit; 861*351053f2SKrzysztof Grobelny } 862*351053f2SKrzysztof Grobelny 863*351053f2SKrzysztof Grobelny if (turboProfile != nullptr) 864*351053f2SKrzysztof Grobelny { 865dba0c291SJonathan Doman nlohmann::json& turboArray = json["TurboProfile"]; 866dba0c291SJonathan Doman turboArray = nlohmann::json::array(); 867*351053f2SKrzysztof Grobelny for (const auto& [turboSpeed, coreCount] : *turboProfile) 868dba0c291SJonathan Doman { 8691476687dSEd Tanous nlohmann::json::object_t turbo; 8701476687dSEd Tanous turbo["ActiveCoreCount"] = coreCount; 8711476687dSEd Tanous turbo["MaxSpeedMHz"] = turboSpeed; 8721476687dSEd Tanous turboArray.push_back(std::move(turbo)); 873dba0c291SJonathan Doman } 874dba0c291SJonathan Doman } 875dba0c291SJonathan Doman 876*351053f2SKrzysztof Grobelny if (baseSpeedPrioritySettings != nullptr) 877*351053f2SKrzysztof Grobelny { 878*351053f2SKrzysztof Grobelny nlohmann::json& baseSpeedArray = json["BaseSpeedPrioritySettings"]; 879dba0c291SJonathan Doman baseSpeedArray = nlohmann::json::array(); 880*351053f2SKrzysztof Grobelny for (const auto& [baseSpeedMhz, coreList] : 881*351053f2SKrzysztof Grobelny *baseSpeedPrioritySettings) 882dba0c291SJonathan Doman { 8831476687dSEd Tanous nlohmann::json::object_t speed; 8841476687dSEd Tanous speed["CoreCount"] = coreList.size(); 8851476687dSEd Tanous speed["CoreIDs"] = coreList; 886*351053f2SKrzysztof Grobelny speed["BaseSpeedMHz"] = baseSpeedMhz; 8871476687dSEd Tanous baseSpeedArray.push_back(std::move(speed)); 888dba0c291SJonathan Doman } 889dba0c291SJonathan Doman } 890*351053f2SKrzysztof Grobelny }); 891dba0c291SJonathan Doman } 892dba0c291SJonathan Doman 8933cde86f1SJonathan Doman /** 8943cde86f1SJonathan Doman * Handle the D-Bus response from attempting to set the CPU's AppliedConfig 8953cde86f1SJonathan Doman * property. Main task is to translate error messages into Redfish errors. 8963cde86f1SJonathan Doman * 8973cde86f1SJonathan Doman * @param[in,out] resp HTTP response. 8983cde86f1SJonathan Doman * @param[in] setPropVal Value which we attempted to set. 8993cde86f1SJonathan Doman * @param[in] ec D-Bus response error code. 9003cde86f1SJonathan Doman * @param[in] msg D-Bus response message. 9013cde86f1SJonathan Doman */ 9023cde86f1SJonathan Doman inline void 9033cde86f1SJonathan Doman handleAppliedConfigResponse(const std::shared_ptr<bmcweb::AsyncResp>& resp, 9043cde86f1SJonathan Doman const std::string& setPropVal, 9053cde86f1SJonathan Doman boost::system::error_code ec, 90659d494eeSPatrick Williams const sdbusplus::message_t& msg) 9073cde86f1SJonathan Doman { 9083cde86f1SJonathan Doman if (!ec) 9093cde86f1SJonathan Doman { 9103cde86f1SJonathan Doman BMCWEB_LOG_DEBUG << "Set Property succeeded"; 9113cde86f1SJonathan Doman return; 9123cde86f1SJonathan Doman } 9133cde86f1SJonathan Doman 9143cde86f1SJonathan Doman BMCWEB_LOG_DEBUG << "Set Property failed: " << ec; 9153cde86f1SJonathan Doman 9163cde86f1SJonathan Doman const sd_bus_error* dbusError = msg.get_error(); 9173cde86f1SJonathan Doman if (dbusError == nullptr) 9183cde86f1SJonathan Doman { 9193cde86f1SJonathan Doman messages::internalError(resp->res); 9203cde86f1SJonathan Doman return; 9213cde86f1SJonathan Doman } 9223cde86f1SJonathan Doman 9233cde86f1SJonathan Doman // The asio error code doesn't know about our custom errors, so we have to 9243cde86f1SJonathan Doman // parse the error string. Some of these D-Bus -> Redfish translations are a 9253cde86f1SJonathan Doman // stretch, but it's good to try to communicate something vaguely useful. 9263cde86f1SJonathan Doman if (strcmp(dbusError->name, 9273cde86f1SJonathan Doman "xyz.openbmc_project.Common.Error.InvalidArgument") == 0) 9283cde86f1SJonathan Doman { 9293cde86f1SJonathan Doman // Service did not like the object_path we tried to set. 9303cde86f1SJonathan Doman messages::propertyValueIncorrect( 9313cde86f1SJonathan Doman resp->res, "AppliedOperatingConfig/@odata.id", setPropVal); 9323cde86f1SJonathan Doman } 9333cde86f1SJonathan Doman else if (strcmp(dbusError->name, 9343cde86f1SJonathan Doman "xyz.openbmc_project.Common.Error.NotAllowed") == 0) 9353cde86f1SJonathan Doman { 9363cde86f1SJonathan Doman // Service indicates we can never change the config for this processor. 9373cde86f1SJonathan Doman messages::propertyNotWritable(resp->res, "AppliedOperatingConfig"); 9383cde86f1SJonathan Doman } 9393cde86f1SJonathan Doman else if (strcmp(dbusError->name, 9403cde86f1SJonathan Doman "xyz.openbmc_project.Common.Error.Unavailable") == 0) 9413cde86f1SJonathan Doman { 9423cde86f1SJonathan Doman // Service indicates the config cannot be changed right now, but maybe 9433cde86f1SJonathan Doman // in a different system state. 9443cde86f1SJonathan Doman messages::resourceInStandby(resp->res); 9453cde86f1SJonathan Doman } 9463cde86f1SJonathan Doman else 9473cde86f1SJonathan Doman { 9483cde86f1SJonathan Doman messages::internalError(resp->res); 9493cde86f1SJonathan Doman } 9503cde86f1SJonathan Doman } 9513cde86f1SJonathan Doman 9523cde86f1SJonathan Doman /** 9533cde86f1SJonathan Doman * Handle the PATCH operation of the AppliedOperatingConfig property. Do basic 9543cde86f1SJonathan Doman * validation of the input data, and then set the D-Bus property. 9553cde86f1SJonathan Doman * 9563cde86f1SJonathan Doman * @param[in,out] resp Async HTTP response. 9573cde86f1SJonathan Doman * @param[in] processorId Processor's Id. 9583cde86f1SJonathan Doman * @param[in] appliedConfigUri New property value to apply. 9593cde86f1SJonathan Doman * @param[in] cpuObjectPath Path of CPU object to modify. 9603cde86f1SJonathan Doman * @param[in] serviceMap Service map for CPU object. 9613cde86f1SJonathan Doman */ 9623cde86f1SJonathan Doman inline void patchAppliedOperatingConfig( 9633cde86f1SJonathan Doman const std::shared_ptr<bmcweb::AsyncResp>& resp, 9643cde86f1SJonathan Doman const std::string& processorId, const std::string& appliedConfigUri, 9655df6eda2SShantappa Teekappanavar const std::string& cpuObjectPath, 9665df6eda2SShantappa Teekappanavar const dbus::utility::MapperServiceMap& serviceMap) 9673cde86f1SJonathan Doman { 9683cde86f1SJonathan Doman // Check that the property even exists by checking for the interface 9693cde86f1SJonathan Doman const std::string* controlService = nullptr; 9703cde86f1SJonathan Doman for (const auto& [serviceName, interfaceList] : serviceMap) 9713cde86f1SJonathan Doman { 9723cde86f1SJonathan Doman if (std::find(interfaceList.begin(), interfaceList.end(), 9733cde86f1SJonathan Doman "xyz.openbmc_project.Control.Processor." 9743cde86f1SJonathan Doman "CurrentOperatingConfig") != interfaceList.end()) 9753cde86f1SJonathan Doman { 9763cde86f1SJonathan Doman controlService = &serviceName; 9773cde86f1SJonathan Doman break; 9783cde86f1SJonathan Doman } 9793cde86f1SJonathan Doman } 9803cde86f1SJonathan Doman 9813cde86f1SJonathan Doman if (controlService == nullptr) 9823cde86f1SJonathan Doman { 9833cde86f1SJonathan Doman messages::internalError(resp->res); 9843cde86f1SJonathan Doman return; 9853cde86f1SJonathan Doman } 9863cde86f1SJonathan Doman 9873cde86f1SJonathan Doman // Check that the config URI is a child of the cpu URI being patched. 9883cde86f1SJonathan Doman std::string expectedPrefix("/redfish/v1/Systems/system/Processors/"); 9893cde86f1SJonathan Doman expectedPrefix += processorId; 9903cde86f1SJonathan Doman expectedPrefix += "/OperatingConfigs/"; 99111ba3979SEd Tanous if (!appliedConfigUri.starts_with(expectedPrefix) || 9923cde86f1SJonathan Doman expectedPrefix.size() == appliedConfigUri.size()) 9933cde86f1SJonathan Doman { 9943cde86f1SJonathan Doman messages::propertyValueIncorrect( 9953cde86f1SJonathan Doman resp->res, "AppliedOperatingConfig/@odata.id", appliedConfigUri); 9963cde86f1SJonathan Doman return; 9973cde86f1SJonathan Doman } 9983cde86f1SJonathan Doman 9993cde86f1SJonathan Doman // Generate the D-Bus path of the OperatingConfig object, by assuming it's a 10003cde86f1SJonathan Doman // direct child of the CPU object. 10013cde86f1SJonathan Doman // Strip the expectedPrefix from the config URI to get the "filename", and 10023cde86f1SJonathan Doman // append to the CPU's path. 10033cde86f1SJonathan Doman std::string configBaseName = appliedConfigUri.substr(expectedPrefix.size()); 10043cde86f1SJonathan Doman sdbusplus::message::object_path configPath(cpuObjectPath); 10053cde86f1SJonathan Doman configPath /= configBaseName; 10063cde86f1SJonathan Doman 10073cde86f1SJonathan Doman BMCWEB_LOG_INFO << "Setting config to " << configPath.str; 10083cde86f1SJonathan Doman 10093cde86f1SJonathan Doman // Set the property, with handler to check error responses 10103cde86f1SJonathan Doman crow::connections::systemBus->async_method_call( 1011914e2d5dSEd Tanous [resp, appliedConfigUri](const boost::system::error_code ec, 101259d494eeSPatrick Williams const sdbusplus::message_t& msg) { 10133cde86f1SJonathan Doman handleAppliedConfigResponse(resp, appliedConfigUri, ec, msg); 10143cde86f1SJonathan Doman }, 10153cde86f1SJonathan Doman *controlService, cpuObjectPath, "org.freedesktop.DBus.Properties", 10163cde86f1SJonathan Doman "Set", "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig", 1017168e20c1SEd Tanous "AppliedConfig", dbus::utility::DbusVariantType(std::move(configPath))); 10183cde86f1SJonathan Doman } 10193cde86f1SJonathan Doman 10207e860f15SJohn Edward Broadbent inline void requestRoutesOperatingConfigCollection(App& app) 1021dba0c291SJonathan Doman { 1022dba0c291SJonathan Doman 10237e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 10247e860f15SJohn Edward Broadbent app, "/redfish/v1/Systems/system/Processors/<str>/OperatingConfigs/") 1025ed398213SEd Tanous .privileges(redfish::privileges::getOperatingConfigCollection) 1026002d39b4SEd Tanous .methods(boost::beast::http::verb::get)( 1027002d39b4SEd Tanous [&app](const crow::Request& req, 102845ca1b86SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 10297e860f15SJohn Edward Broadbent const std::string& cpuName) { 10303ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 103145ca1b86SEd Tanous { 103245ca1b86SEd Tanous return; 103345ca1b86SEd Tanous } 10348d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.type"] = 1035dba0c291SJonathan Doman "#OperatingConfigCollection.OperatingConfigCollection"; 10368d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.id"] = req.url; 10370fda0f12SGeorge Liu asyncResp->res.jsonValue["Name"] = "Operating Config Collection"; 1038dba0c291SJonathan Doman 10397e860f15SJohn Edward Broadbent // First find the matching CPU object so we know how to 10407e860f15SJohn Edward Broadbent // constrain our search for related Config objects. 1041dba0c291SJonathan Doman crow::connections::systemBus->async_method_call( 1042002d39b4SEd Tanous [asyncResp, cpuName]( 1043002d39b4SEd Tanous const boost::system::error_code ec, 1044002d39b4SEd Tanous const dbus::utility::MapperGetSubTreePathsResponse& objects) { 1045dba0c291SJonathan Doman if (ec) 1046dba0c291SJonathan Doman { 1047dba0c291SJonathan Doman BMCWEB_LOG_WARNING << "D-Bus error: " << ec << ", " 1048dba0c291SJonathan Doman << ec.message(); 1049dba0c291SJonathan Doman messages::internalError(asyncResp->res); 1050dba0c291SJonathan Doman return; 1051dba0c291SJonathan Doman } 1052dba0c291SJonathan Doman 1053dba0c291SJonathan Doman for (const std::string& object : objects) 1054dba0c291SJonathan Doman { 105511ba3979SEd Tanous if (!object.ends_with(cpuName)) 1056dba0c291SJonathan Doman { 1057dba0c291SJonathan Doman continue; 1058dba0c291SJonathan Doman } 1059dba0c291SJonathan Doman 10607e860f15SJohn Edward Broadbent // Not expected that there will be multiple matching 10617e860f15SJohn Edward Broadbent // CPU objects, but if there are just use the first 10627e860f15SJohn Edward Broadbent // one. 1063dba0c291SJonathan Doman 10647e860f15SJohn Edward Broadbent // Use the common search routine to construct the 10657e860f15SJohn Edward Broadbent // Collection of all Config objects under this CPU. 1066dba0c291SJonathan Doman collection_util::getCollectionMembers( 1067dba0c291SJonathan Doman asyncResp, 10680fda0f12SGeorge Liu "/redfish/v1/Systems/system/Processors/" + cpuName + 10690fda0f12SGeorge Liu "/OperatingConfigs", 10700fda0f12SGeorge Liu {"xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig"}, 1071dba0c291SJonathan Doman object.c_str()); 1072dba0c291SJonathan Doman return; 1073dba0c291SJonathan Doman } 1074dba0c291SJonathan Doman }, 1075dba0c291SJonathan Doman "xyz.openbmc_project.ObjectMapper", 1076dba0c291SJonathan Doman "/xyz/openbmc_project/object_mapper", 1077dba0c291SJonathan Doman "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", 1078dba0c291SJonathan Doman "/xyz/openbmc_project/inventory", 0, 10797e860f15SJohn Edward Broadbent std::array<const char*, 1>{ 10800fda0f12SGeorge Liu "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig"}); 10817e860f15SJohn Edward Broadbent }); 1082dba0c291SJonathan Doman } 1083dba0c291SJonathan Doman 10847e860f15SJohn Edward Broadbent inline void requestRoutesOperatingConfig(App& app) 1085dba0c291SJonathan Doman { 10867e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 10877e860f15SJohn Edward Broadbent app, 10887e860f15SJohn Edward Broadbent "/redfish/v1/Systems/system/Processors/<str>/OperatingConfigs/<str>/") 1089ed398213SEd Tanous .privileges(redfish::privileges::getOperatingConfig) 1090002d39b4SEd Tanous .methods(boost::beast::http::verb::get)( 1091002d39b4SEd Tanous [&app](const crow::Request& req, 109245ca1b86SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1093002d39b4SEd Tanous const std::string& cpuName, const std::string& configName) { 10943ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 109545ca1b86SEd Tanous { 109645ca1b86SEd Tanous return; 109745ca1b86SEd Tanous } 10987e860f15SJohn Edward Broadbent // Ask for all objects implementing OperatingConfig so we can search 10997e860f15SJohn Edward Broadbent // for one with a matching name 1100dba0c291SJonathan Doman crow::connections::systemBus->async_method_call( 11015df6eda2SShantappa Teekappanavar [asyncResp, cpuName, configName, reqUrl{req.url}]( 11025df6eda2SShantappa Teekappanavar boost::system::error_code ec, 11035df6eda2SShantappa Teekappanavar const dbus::utility::MapperGetSubTreeResponse& subtree) { 1104dba0c291SJonathan Doman if (ec) 1105dba0c291SJonathan Doman { 1106dba0c291SJonathan Doman BMCWEB_LOG_WARNING << "D-Bus error: " << ec << ", " 1107dba0c291SJonathan Doman << ec.message(); 1108dba0c291SJonathan Doman messages::internalError(asyncResp->res); 1109dba0c291SJonathan Doman return; 1110dba0c291SJonathan Doman } 1111002d39b4SEd Tanous const std::string expectedEnding = cpuName + '/' + configName; 1112dba0c291SJonathan Doman for (const auto& [objectPath, serviceMap] : subtree) 1113dba0c291SJonathan Doman { 1114dba0c291SJonathan Doman // Ignore any configs without matching cpuX/configY 111511ba3979SEd Tanous if (!objectPath.ends_with(expectedEnding) || serviceMap.empty()) 1116dba0c291SJonathan Doman { 1117dba0c291SJonathan Doman continue; 1118dba0c291SJonathan Doman } 1119dba0c291SJonathan Doman 1120dba0c291SJonathan Doman nlohmann::json& json = asyncResp->res.jsonValue; 1121002d39b4SEd Tanous json["@odata.type"] = "#OperatingConfig.v1_0_0.OperatingConfig"; 1122dba0c291SJonathan Doman json["@odata.id"] = reqUrl; 1123dba0c291SJonathan Doman json["Name"] = "Processor Profile"; 1124dba0c291SJonathan Doman json["Id"] = configName; 1125dba0c291SJonathan Doman 1126dba0c291SJonathan Doman // Just use the first implementation of the object - not 11277e860f15SJohn Edward Broadbent // expected that there would be multiple matching 11287e860f15SJohn Edward Broadbent // services 1129002d39b4SEd Tanous getOperatingConfigData(asyncResp, serviceMap.begin()->first, 1130002d39b4SEd Tanous objectPath); 1131dba0c291SJonathan Doman return; 1132dba0c291SJonathan Doman } 1133002d39b4SEd Tanous messages::resourceNotFound(asyncResp->res, "OperatingConfig", 1134002d39b4SEd Tanous configName); 1135dba0c291SJonathan Doman }, 1136dba0c291SJonathan Doman "xyz.openbmc_project.ObjectMapper", 1137dba0c291SJonathan Doman "/xyz/openbmc_project/object_mapper", 1138dba0c291SJonathan Doman "xyz.openbmc_project.ObjectMapper", "GetSubTree", 1139dba0c291SJonathan Doman "/xyz/openbmc_project/inventory", 0, 1140dba0c291SJonathan Doman std::array<const char*, 1>{ 1141dba0c291SJonathan Doman "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig"}); 11427e860f15SJohn Edward Broadbent }); 1143ac6a4445SGunnar Mills } 1144ac6a4445SGunnar Mills 11457e860f15SJohn Edward Broadbent inline void requestRoutesProcessorCollection(App& app) 11467e860f15SJohn Edward Broadbent { 1147ac6a4445SGunnar Mills /** 1148ac6a4445SGunnar Mills * Functions triggers appropriate requests on DBus 1149ac6a4445SGunnar Mills */ 11507e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Processors/") 1151ed398213SEd Tanous .privileges(redfish::privileges::getProcessorCollection) 11527e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 115345ca1b86SEd Tanous [&app](const crow::Request& req, 11547e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 11553ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 115645ca1b86SEd Tanous { 115745ca1b86SEd Tanous return; 115845ca1b86SEd Tanous } 11598d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.type"] = 1160ac6a4445SGunnar Mills "#ProcessorCollection.ProcessorCollection"; 11618d1b46d7Szhanghch05 asyncResp->res.jsonValue["Name"] = "Processor Collection"; 1162ac6a4445SGunnar Mills 11638d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.id"] = 11648d1b46d7Szhanghch05 "/redfish/v1/Systems/system/Processors"; 1165ac6a4445SGunnar Mills 116605030b8eSGunnar Mills collection_util::getCollectionMembers( 116705030b8eSGunnar Mills asyncResp, "/redfish/v1/Systems/system/Processors", 1168c951448aSJonathan Doman std::vector<const char*>(processorInterfaces.begin(), 1169c951448aSJonathan Doman processorInterfaces.end())); 11707e860f15SJohn Edward Broadbent }); 1171ac6a4445SGunnar Mills } 1172ac6a4445SGunnar Mills 11737e860f15SJohn Edward Broadbent inline void requestRoutesProcessor(App& app) 11747e860f15SJohn Edward Broadbent { 1175ac6a4445SGunnar Mills /** 1176ac6a4445SGunnar Mills * Functions triggers appropriate requests on DBus 1177ac6a4445SGunnar Mills */ 11787e860f15SJohn Edward Broadbent 11797e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Processors/<str>/") 1180ed398213SEd Tanous .privileges(redfish::privileges::getProcessor) 11817e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 118245ca1b86SEd Tanous [&app](const crow::Request& req, 11837e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 11847e860f15SJohn Edward Broadbent const std::string& processorId) { 11853ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 118645ca1b86SEd Tanous { 118745ca1b86SEd Tanous return; 118845ca1b86SEd Tanous } 11898d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.type"] = 11908d1b46d7Szhanghch05 "#Processor.v1_11_0.Processor"; 11918d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.id"] = 1192ac6a4445SGunnar Mills "/redfish/v1/Systems/system/Processors/" + processorId; 1193ac6a4445SGunnar Mills 11948a592810SEd Tanous getProcessorObject( 11958a592810SEd Tanous asyncResp, processorId, 11968a592810SEd Tanous std::bind_front(getProcessorData, asyncResp, processorId)); 11977e860f15SJohn Edward Broadbent }); 11983cde86f1SJonathan Doman 11997e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Processors/<str>/") 1200ed398213SEd Tanous .privileges(redfish::privileges::patchProcessor) 12017e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::patch)( 120245ca1b86SEd Tanous [&app](const crow::Request& req, 12037e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 12047e860f15SJohn Edward Broadbent const std::string& processorId) { 12053ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 120645ca1b86SEd Tanous { 120745ca1b86SEd Tanous return; 120845ca1b86SEd Tanous } 12093cde86f1SJonathan Doman std::optional<nlohmann::json> appliedConfigJson; 121015ed6780SWilly Tu if (!json_util::readJsonPatch(req, asyncResp->res, 12117e860f15SJohn Edward Broadbent "AppliedOperatingConfig", 12123cde86f1SJonathan Doman appliedConfigJson)) 12133cde86f1SJonathan Doman { 12143cde86f1SJonathan Doman return; 12153cde86f1SJonathan Doman } 12163cde86f1SJonathan Doman 12173cde86f1SJonathan Doman std::string appliedConfigUri; 12183cde86f1SJonathan Doman if (appliedConfigJson) 12193cde86f1SJonathan Doman { 12203cde86f1SJonathan Doman if (!json_util::readJson(*appliedConfigJson, asyncResp->res, 12213cde86f1SJonathan Doman "@odata.id", appliedConfigUri)) 12223cde86f1SJonathan Doman { 12233cde86f1SJonathan Doman return; 12243cde86f1SJonathan Doman } 12257e860f15SJohn Edward Broadbent // Check for 404 and find matching D-Bus object, then run 12267e860f15SJohn Edward Broadbent // property patch handlers if that all succeeds. 12278a592810SEd Tanous getProcessorObject(asyncResp, processorId, 12288a592810SEd Tanous std::bind_front(patchAppliedOperatingConfig, 12297e860f15SJohn Edward Broadbent asyncResp, processorId, 12308a592810SEd Tanous appliedConfigUri)); 12313cde86f1SJonathan Doman } 12327e860f15SJohn Edward Broadbent }); 12333cde86f1SJonathan Doman } 1234ac6a4445SGunnar Mills 1235ac6a4445SGunnar Mills } // namespace redfish 1236