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> 29dba0c291SJonathan Doman #include <sdbusplus/utility/dedup_variant.hpp> 30ac6a4445SGunnar Mills #include <utils/collection.hpp> 31ac6a4445SGunnar Mills #include <utils/json_utils.hpp> 32ac6a4445SGunnar Mills 33ac6a4445SGunnar Mills namespace redfish 34ac6a4445SGunnar Mills { 35ac6a4445SGunnar Mills 36c951448aSJonathan Doman // Interfaces which imply a D-Bus object represents a Processor 37c951448aSJonathan Doman constexpr std::array<const char*, 2> processorInterfaces = { 38c951448aSJonathan Doman "xyz.openbmc_project.Inventory.Item.Cpu", 39c951448aSJonathan Doman "xyz.openbmc_project.Inventory.Item.Accelerator"}; 402bab9831SJonathan Doman 4171b82f26SSharad Yadav /** 4271b82f26SSharad Yadav * @brief Fill out uuid info of a processor by 4371b82f26SSharad Yadav * requesting data from the given D-Bus object. 4471b82f26SSharad Yadav * 4571b82f26SSharad Yadav * @param[in,out] aResp Async HTTP response. 4671b82f26SSharad Yadav * @param[in] service D-Bus service to query. 4771b82f26SSharad Yadav * @param[in] objPath D-Bus object to query. 4871b82f26SSharad Yadav */ 4971b82f26SSharad Yadav inline void getProcessorUUID(std::shared_ptr<bmcweb::AsyncResp> aResp, 5071b82f26SSharad Yadav const std::string& service, 5171b82f26SSharad Yadav const std::string& objPath) 5271b82f26SSharad Yadav { 5371b82f26SSharad Yadav BMCWEB_LOG_DEBUG << "Get Processor UUID"; 541e1e598dSJonathan Doman sdbusplus::asio::getProperty<std::string>( 551e1e598dSJonathan Doman *crow::connections::systemBus, service, objPath, 561e1e598dSJonathan Doman "xyz.openbmc_project.Common.UUID", "UUID", 571e1e598dSJonathan Doman [objPath, aResp{std::move(aResp)}](const boost::system::error_code ec, 581e1e598dSJonathan Doman const std::string& property) { 5971b82f26SSharad Yadav if (ec) 6071b82f26SSharad Yadav { 6171b82f26SSharad Yadav BMCWEB_LOG_DEBUG << "DBUS response error"; 6271b82f26SSharad Yadav messages::internalError(aResp->res); 6371b82f26SSharad Yadav return; 6471b82f26SSharad Yadav } 651e1e598dSJonathan Doman aResp->res.jsonValue["UUID"] = property; 661e1e598dSJonathan Doman }); 6771b82f26SSharad Yadav } 6871b82f26SSharad Yadav 69711ac7a9SEd Tanous inline void getCpuDataByInterface( 70711ac7a9SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& aResp, 71711ac7a9SEd Tanous const dbus::utility::DBusInteracesMap& cpuInterfacesProperties) 72ac6a4445SGunnar Mills { 73ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "Get CPU resources by interface."; 74ac6a4445SGunnar Mills 75a1649ec6SChicago Duan // Set the default value of state 76a1649ec6SChicago Duan aResp->res.jsonValue["Status"]["State"] = "Enabled"; 77a1649ec6SChicago Duan aResp->res.jsonValue["Status"]["Health"] = "OK"; 78ac6a4445SGunnar Mills 79ac6a4445SGunnar Mills for (const auto& interface : cpuInterfacesProperties) 80ac6a4445SGunnar Mills { 81ac6a4445SGunnar Mills for (const auto& property : interface.second) 82ac6a4445SGunnar Mills { 83a1649ec6SChicago Duan if (property.first == "Present") 84ac6a4445SGunnar Mills { 85a1649ec6SChicago Duan const bool* cpuPresent = std::get_if<bool>(&property.second); 86a1649ec6SChicago Duan if (cpuPresent == nullptr) 87ac6a4445SGunnar Mills { 88ac6a4445SGunnar Mills // Important property not in desired type 89ac6a4445SGunnar Mills messages::internalError(aResp->res); 90ac6a4445SGunnar Mills return; 91ac6a4445SGunnar Mills } 92e05aec50SEd Tanous if (!*cpuPresent) 93ac6a4445SGunnar Mills { 94a1649ec6SChicago Duan // Slot is not populated 95ac6a4445SGunnar Mills aResp->res.jsonValue["Status"]["State"] = "Absent"; 96a1649ec6SChicago Duan } 97a1649ec6SChicago Duan } 98a1649ec6SChicago Duan else if (property.first == "Functional") 99a1649ec6SChicago Duan { 100a1649ec6SChicago Duan const bool* cpuFunctional = std::get_if<bool>(&property.second); 101a1649ec6SChicago Duan if (cpuFunctional == nullptr) 102a1649ec6SChicago Duan { 103a1649ec6SChicago Duan messages::internalError(aResp->res); 104ac6a4445SGunnar Mills return; 105ac6a4445SGunnar Mills } 106e05aec50SEd Tanous if (!*cpuFunctional) 107a1649ec6SChicago Duan { 108a1649ec6SChicago Duan aResp->res.jsonValue["Status"]["Health"] = "Critical"; 109a1649ec6SChicago Duan } 110a1649ec6SChicago Duan } 111a1649ec6SChicago Duan else if (property.first == "CoreCount") 112a1649ec6SChicago Duan { 113a1649ec6SChicago Duan const uint16_t* coresCount = 114a1649ec6SChicago Duan std::get_if<uint16_t>(&property.second); 115a1649ec6SChicago Duan if (coresCount == nullptr) 116a1649ec6SChicago Duan { 117a1649ec6SChicago Duan messages::internalError(aResp->res); 118a1649ec6SChicago Duan return; 119a1649ec6SChicago Duan } 120ac6a4445SGunnar Mills aResp->res.jsonValue["TotalCores"] = *coresCount; 121ac6a4445SGunnar Mills } 122dc3fa667SJonathan Doman else if (property.first == "MaxSpeedInMhz") 123dc3fa667SJonathan Doman { 124dc3fa667SJonathan Doman const uint32_t* value = std::get_if<uint32_t>(&property.second); 125dc3fa667SJonathan Doman if (value != nullptr) 126dc3fa667SJonathan Doman { 127dc3fa667SJonathan Doman aResp->res.jsonValue["MaxSpeedMHz"] = *value; 128dc3fa667SJonathan Doman } 129dc3fa667SJonathan Doman } 130ac6a4445SGunnar Mills else if (property.first == "Socket") 131ac6a4445SGunnar Mills { 132ac6a4445SGunnar Mills const std::string* value = 133ac6a4445SGunnar Mills std::get_if<std::string>(&property.second); 134ac6a4445SGunnar Mills if (value != nullptr) 135ac6a4445SGunnar Mills { 136ac6a4445SGunnar Mills aResp->res.jsonValue["Socket"] = *value; 137ac6a4445SGunnar Mills } 138ac6a4445SGunnar Mills } 139ac6a4445SGunnar Mills else if (property.first == "ThreadCount") 140ac6a4445SGunnar Mills { 141dc3fa667SJonathan Doman const uint16_t* value = std::get_if<uint16_t>(&property.second); 142ac6a4445SGunnar Mills if (value != nullptr) 143ac6a4445SGunnar Mills { 144ac6a4445SGunnar Mills aResp->res.jsonValue["TotalThreads"] = *value; 145ac6a4445SGunnar Mills } 146ac6a4445SGunnar Mills } 1471930fbd4SBrandon Kim else if (property.first == "EffectiveFamily") 148ac6a4445SGunnar Mills { 1491930fbd4SBrandon Kim const uint16_t* value = std::get_if<uint16_t>(&property.second); 150ac6a4445SGunnar Mills if (value != nullptr) 151ac6a4445SGunnar Mills { 152ac6a4445SGunnar Mills aResp->res.jsonValue["ProcessorId"]["EffectiveFamily"] = 153866e4862SEd Tanous "0x" + intToHexString(*value, 4); 154ac6a4445SGunnar Mills } 155ac6a4445SGunnar Mills } 1561930fbd4SBrandon Kim else if (property.first == "EffectiveModel") 1571930fbd4SBrandon Kim { 1581930fbd4SBrandon Kim const uint16_t* value = std::get_if<uint16_t>(&property.second); 1591930fbd4SBrandon Kim if (value == nullptr) 1601930fbd4SBrandon Kim { 1611930fbd4SBrandon Kim messages::internalError(aResp->res); 1621930fbd4SBrandon Kim return; 1631930fbd4SBrandon Kim } 1641930fbd4SBrandon Kim aResp->res.jsonValue["ProcessorId"]["EffectiveModel"] = 165866e4862SEd Tanous "0x" + intToHexString(*value, 4); 1661930fbd4SBrandon Kim } 167ac6a4445SGunnar Mills else if (property.first == "Id") 168ac6a4445SGunnar Mills { 169ac6a4445SGunnar Mills const uint64_t* value = std::get_if<uint64_t>(&property.second); 170ac6a4445SGunnar Mills if (value != nullptr && *value != 0) 171ac6a4445SGunnar Mills { 172ac6a4445SGunnar Mills aResp->res 173ac6a4445SGunnar Mills .jsonValue["ProcessorId"]["IdentificationRegisters"] = 174866e4862SEd Tanous "0x" + intToHexString(*value, 16); 175ac6a4445SGunnar Mills } 176ac6a4445SGunnar Mills } 1771930fbd4SBrandon Kim else if (property.first == "Microcode") 1781930fbd4SBrandon Kim { 1791930fbd4SBrandon Kim const uint32_t* value = std::get_if<uint32_t>(&property.second); 1801930fbd4SBrandon Kim if (value == nullptr) 1811930fbd4SBrandon Kim { 1821930fbd4SBrandon Kim messages::internalError(aResp->res); 1831930fbd4SBrandon Kim return; 1841930fbd4SBrandon Kim } 1851930fbd4SBrandon Kim aResp->res.jsonValue["ProcessorId"]["MicrocodeInfo"] = 186866e4862SEd Tanous "0x" + intToHexString(*value, 8); 1871930fbd4SBrandon Kim } 1881930fbd4SBrandon Kim else if (property.first == "Step") 1891930fbd4SBrandon Kim { 1901930fbd4SBrandon Kim const uint16_t* value = std::get_if<uint16_t>(&property.second); 1911930fbd4SBrandon Kim if (value == nullptr) 1921930fbd4SBrandon Kim { 1931930fbd4SBrandon Kim messages::internalError(aResp->res); 1941930fbd4SBrandon Kim return; 1951930fbd4SBrandon Kim } 1961930fbd4SBrandon Kim aResp->res.jsonValue["ProcessorId"]["Step"] = 197866e4862SEd Tanous "0x" + intToHexString(*value, 4); 1981930fbd4SBrandon Kim } 199ac6a4445SGunnar Mills } 200ac6a4445SGunnar Mills } 201ac6a4445SGunnar Mills } 202ac6a4445SGunnar Mills 2038d1b46d7Szhanghch05 inline void getCpuDataByService(std::shared_ptr<bmcweb::AsyncResp> aResp, 204ac6a4445SGunnar Mills const std::string& cpuId, 205ac6a4445SGunnar Mills const std::string& service, 206ac6a4445SGunnar Mills const std::string& objPath) 207ac6a4445SGunnar Mills { 208ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "Get available system cpu resources by service."; 209ac6a4445SGunnar Mills 210ac6a4445SGunnar Mills crow::connections::systemBus->async_method_call( 211ac6a4445SGunnar Mills [cpuId, service, objPath, aResp{std::move(aResp)}]( 212ac6a4445SGunnar Mills const boost::system::error_code ec, 213ac6a4445SGunnar Mills const dbus::utility::ManagedObjectType& dbusData) { 214ac6a4445SGunnar Mills if (ec) 215ac6a4445SGunnar Mills { 216ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "DBUS response error"; 217ac6a4445SGunnar Mills messages::internalError(aResp->res); 218ac6a4445SGunnar Mills return; 219ac6a4445SGunnar Mills } 220ac6a4445SGunnar Mills aResp->res.jsonValue["Id"] = cpuId; 221ac6a4445SGunnar Mills aResp->res.jsonValue["Name"] = "Processor"; 222ac6a4445SGunnar Mills aResp->res.jsonValue["ProcessorType"] = "CPU"; 223ac6a4445SGunnar Mills 224ac6a4445SGunnar Mills bool slotPresent = false; 225ac6a4445SGunnar Mills std::string corePath = objPath + "/core"; 226ac6a4445SGunnar Mills size_t totalCores = 0; 227ac6a4445SGunnar Mills for (const auto& object : dbusData) 228ac6a4445SGunnar Mills { 229ac6a4445SGunnar Mills if (object.first.str == objPath) 230ac6a4445SGunnar Mills { 231ac6a4445SGunnar Mills getCpuDataByInterface(aResp, object.second); 232ac6a4445SGunnar Mills } 233ac6a4445SGunnar Mills else if (boost::starts_with(object.first.str, corePath)) 234ac6a4445SGunnar Mills { 235ac6a4445SGunnar Mills for (const auto& interface : object.second) 236ac6a4445SGunnar Mills { 237*002d39b4SEd Tanous if (interface.first == "xyz.openbmc_project.Inventory.Item") 238ac6a4445SGunnar Mills { 239ac6a4445SGunnar Mills for (const auto& property : interface.second) 240ac6a4445SGunnar Mills { 241ac6a4445SGunnar Mills if (property.first == "Present") 242ac6a4445SGunnar Mills { 243ac6a4445SGunnar Mills const bool* present = 244ac6a4445SGunnar Mills std::get_if<bool>(&property.second); 245ac6a4445SGunnar Mills if (present != nullptr) 246ac6a4445SGunnar Mills { 247e05aec50SEd Tanous if (*present) 248ac6a4445SGunnar Mills { 249ac6a4445SGunnar Mills slotPresent = true; 250ac6a4445SGunnar Mills totalCores++; 251ac6a4445SGunnar Mills } 252ac6a4445SGunnar Mills } 253ac6a4445SGunnar Mills } 254ac6a4445SGunnar Mills } 255ac6a4445SGunnar Mills } 256ac6a4445SGunnar Mills } 257ac6a4445SGunnar Mills } 258ac6a4445SGunnar Mills } 259ac6a4445SGunnar Mills // In getCpuDataByInterface(), state and health are set 260ac6a4445SGunnar Mills // based on the present and functional status. If core 261ac6a4445SGunnar Mills // count is zero, then it has a higher precedence. 262ac6a4445SGunnar Mills if (slotPresent) 263ac6a4445SGunnar Mills { 264ac6a4445SGunnar Mills if (totalCores == 0) 265ac6a4445SGunnar Mills { 266ac6a4445SGunnar Mills // Slot is not populated, set status end return 267ac6a4445SGunnar Mills aResp->res.jsonValue["Status"]["State"] = "Absent"; 268ac6a4445SGunnar Mills aResp->res.jsonValue["Status"]["Health"] = "OK"; 269ac6a4445SGunnar Mills } 270ac6a4445SGunnar Mills aResp->res.jsonValue["TotalCores"] = totalCores; 271ac6a4445SGunnar Mills } 272ac6a4445SGunnar Mills return; 273ac6a4445SGunnar Mills }, 274ac6a4445SGunnar Mills service, "/xyz/openbmc_project/inventory", 275ac6a4445SGunnar Mills "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 276ac6a4445SGunnar Mills } 277ac6a4445SGunnar Mills 2788d1b46d7Szhanghch05 inline void getCpuAssetData(std::shared_ptr<bmcweb::AsyncResp> aResp, 279ac6a4445SGunnar Mills const std::string& service, 280ac6a4445SGunnar Mills const std::string& objPath) 281ac6a4445SGunnar Mills { 282ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "Get Cpu Asset Data"; 283ac6a4445SGunnar Mills crow::connections::systemBus->async_method_call( 284ac6a4445SGunnar Mills [objPath, aResp{std::move(aResp)}]( 285ac6a4445SGunnar Mills const boost::system::error_code ec, 286ac6a4445SGunnar Mills const boost::container::flat_map< 287168e20c1SEd Tanous std::string, dbus::utility::DbusVariantType>& properties) { 288ac6a4445SGunnar Mills if (ec) 289ac6a4445SGunnar Mills { 290ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "DBUS response error"; 291ac6a4445SGunnar Mills messages::internalError(aResp->res); 292ac6a4445SGunnar Mills return; 293ac6a4445SGunnar Mills } 294ac6a4445SGunnar Mills 295ac6a4445SGunnar Mills for (const auto& property : properties) 296ac6a4445SGunnar Mills { 297ac6a4445SGunnar Mills if (property.first == "SerialNumber") 298ac6a4445SGunnar Mills { 299ac6a4445SGunnar Mills const std::string* sn = 300ac6a4445SGunnar Mills std::get_if<std::string>(&property.second); 301ac6a4445SGunnar Mills if (sn != nullptr && !sn->empty()) 302ac6a4445SGunnar Mills { 303ac6a4445SGunnar Mills aResp->res.jsonValue["SerialNumber"] = *sn; 304ac6a4445SGunnar Mills } 305ac6a4445SGunnar Mills } 306ac6a4445SGunnar Mills else if (property.first == "Model") 307ac6a4445SGunnar Mills { 308ac6a4445SGunnar Mills const std::string* model = 309ac6a4445SGunnar Mills std::get_if<std::string>(&property.second); 310ac6a4445SGunnar Mills if (model != nullptr && !model->empty()) 311ac6a4445SGunnar Mills { 312ac6a4445SGunnar Mills aResp->res.jsonValue["Model"] = *model; 313ac6a4445SGunnar Mills } 314ac6a4445SGunnar Mills } 315ac6a4445SGunnar Mills else if (property.first == "Manufacturer") 316ac6a4445SGunnar Mills { 317ac6a4445SGunnar Mills 318ac6a4445SGunnar Mills const std::string* mfg = 319ac6a4445SGunnar Mills std::get_if<std::string>(&property.second); 320ac6a4445SGunnar Mills if (mfg != nullptr) 321ac6a4445SGunnar Mills { 322ac6a4445SGunnar Mills aResp->res.jsonValue["Manufacturer"] = *mfg; 323ac6a4445SGunnar Mills 324ac6a4445SGunnar Mills // Otherwise would be unexpected. 325ac6a4445SGunnar Mills if (mfg->find("Intel") != std::string::npos) 326ac6a4445SGunnar Mills { 327*002d39b4SEd Tanous aResp->res.jsonValue["ProcessorArchitecture"] = "x86"; 328ac6a4445SGunnar Mills aResp->res.jsonValue["InstructionSet"] = "x86-64"; 329ac6a4445SGunnar Mills } 330ac6a4445SGunnar Mills else if (mfg->find("IBM") != std::string::npos) 331ac6a4445SGunnar Mills { 332*002d39b4SEd Tanous aResp->res.jsonValue["ProcessorArchitecture"] = "Power"; 333ac6a4445SGunnar Mills aResp->res.jsonValue["InstructionSet"] = "PowerISA"; 334ac6a4445SGunnar Mills } 335ac6a4445SGunnar Mills } 336ac6a4445SGunnar Mills } 337cba4f448SSunnySrivastava1984 else if (property.first == "PartNumber") 338cba4f448SSunnySrivastava1984 { 339cba4f448SSunnySrivastava1984 const std::string* partNumber = 340cba4f448SSunnySrivastava1984 std::get_if<std::string>(&property.second); 341cba4f448SSunnySrivastava1984 342cba4f448SSunnySrivastava1984 if (partNumber == nullptr) 343cba4f448SSunnySrivastava1984 { 344cba4f448SSunnySrivastava1984 messages::internalError(aResp->res); 345cba4f448SSunnySrivastava1984 return; 346cba4f448SSunnySrivastava1984 } 347cba4f448SSunnySrivastava1984 aResp->res.jsonValue["PartNumber"] = *partNumber; 348cba4f448SSunnySrivastava1984 } 349cba4f448SSunnySrivastava1984 else if (property.first == "SparePartNumber") 350cba4f448SSunnySrivastava1984 { 351cba4f448SSunnySrivastava1984 const std::string* sparePartNumber = 352cba4f448SSunnySrivastava1984 std::get_if<std::string>(&property.second); 353cba4f448SSunnySrivastava1984 354cba4f448SSunnySrivastava1984 if (sparePartNumber == nullptr) 355cba4f448SSunnySrivastava1984 { 356cba4f448SSunnySrivastava1984 messages::internalError(aResp->res); 357cba4f448SSunnySrivastava1984 return; 358cba4f448SSunnySrivastava1984 } 359cba4f448SSunnySrivastava1984 aResp->res.jsonValue["SparePartNumber"] = *sparePartNumber; 360cba4f448SSunnySrivastava1984 } 361ac6a4445SGunnar Mills } 362ac6a4445SGunnar Mills }, 363ac6a4445SGunnar Mills service, objPath, "org.freedesktop.DBus.Properties", "GetAll", 364ac6a4445SGunnar Mills "xyz.openbmc_project.Inventory.Decorator.Asset"); 365ac6a4445SGunnar Mills } 366ac6a4445SGunnar Mills 3678d1b46d7Szhanghch05 inline void getCpuRevisionData(std::shared_ptr<bmcweb::AsyncResp> aResp, 368ac6a4445SGunnar Mills const std::string& service, 369ac6a4445SGunnar Mills const std::string& objPath) 370ac6a4445SGunnar Mills { 371ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "Get Cpu Revision Data"; 372ac6a4445SGunnar Mills crow::connections::systemBus->async_method_call( 373ac6a4445SGunnar Mills [objPath, aResp{std::move(aResp)}]( 374ac6a4445SGunnar Mills const boost::system::error_code ec, 375ac6a4445SGunnar Mills const boost::container::flat_map< 376168e20c1SEd Tanous std::string, dbus::utility::DbusVariantType>& properties) { 377ac6a4445SGunnar Mills if (ec) 378ac6a4445SGunnar Mills { 379ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "DBUS response error"; 380ac6a4445SGunnar Mills messages::internalError(aResp->res); 381ac6a4445SGunnar Mills return; 382ac6a4445SGunnar Mills } 383ac6a4445SGunnar Mills 384ac6a4445SGunnar Mills for (const auto& property : properties) 385ac6a4445SGunnar Mills { 386ac6a4445SGunnar Mills if (property.first == "Version") 387ac6a4445SGunnar Mills { 388ac6a4445SGunnar Mills const std::string* ver = 389ac6a4445SGunnar Mills std::get_if<std::string>(&property.second); 390ac6a4445SGunnar Mills if (ver != nullptr) 391ac6a4445SGunnar Mills { 392ac6a4445SGunnar Mills aResp->res.jsonValue["Version"] = *ver; 393ac6a4445SGunnar Mills } 394ac6a4445SGunnar Mills break; 395ac6a4445SGunnar Mills } 396ac6a4445SGunnar Mills } 397ac6a4445SGunnar Mills }, 398ac6a4445SGunnar Mills service, objPath, "org.freedesktop.DBus.Properties", "GetAll", 399ac6a4445SGunnar Mills "xyz.openbmc_project.Inventory.Decorator.Revision"); 400ac6a4445SGunnar Mills } 401ac6a4445SGunnar Mills 4028d1b46d7Szhanghch05 inline void getAcceleratorDataByService( 4038d1b46d7Szhanghch05 std::shared_ptr<bmcweb::AsyncResp> aResp, const std::string& acclrtrId, 4048d1b46d7Szhanghch05 const std::string& service, const std::string& objPath) 405ac6a4445SGunnar Mills { 406ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG 407ac6a4445SGunnar Mills << "Get available system Accelerator resources by service."; 408ac6a4445SGunnar Mills crow::connections::systemBus->async_method_call( 409ac6a4445SGunnar Mills [acclrtrId, aResp{std::move(aResp)}]( 410ac6a4445SGunnar Mills const boost::system::error_code ec, 411ac6a4445SGunnar Mills const boost::container::flat_map< 412168e20c1SEd Tanous std::string, dbus::utility::DbusVariantType>& properties) { 413ac6a4445SGunnar Mills if (ec) 414ac6a4445SGunnar Mills { 415ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "DBUS response error"; 416ac6a4445SGunnar Mills messages::internalError(aResp->res); 417ac6a4445SGunnar Mills return; 418ac6a4445SGunnar Mills } 419ac6a4445SGunnar Mills aResp->res.jsonValue["Id"] = acclrtrId; 420ac6a4445SGunnar Mills aResp->res.jsonValue["Name"] = "Processor"; 421ac6a4445SGunnar Mills const bool* accPresent = nullptr; 422ac6a4445SGunnar Mills const bool* accFunctional = nullptr; 423ac6a4445SGunnar Mills 424ac6a4445SGunnar Mills for (const auto& property : properties) 425ac6a4445SGunnar Mills { 426ac6a4445SGunnar Mills if (property.first == "Functional") 427ac6a4445SGunnar Mills { 428ac6a4445SGunnar Mills accFunctional = std::get_if<bool>(&property.second); 429ac6a4445SGunnar Mills } 430ac6a4445SGunnar Mills else if (property.first == "Present") 431ac6a4445SGunnar Mills { 432ac6a4445SGunnar Mills accPresent = std::get_if<bool>(&property.second); 433ac6a4445SGunnar Mills } 434ac6a4445SGunnar Mills } 435ac6a4445SGunnar Mills 436ac6a4445SGunnar Mills std::string state = "Enabled"; 437ac6a4445SGunnar Mills std::string health = "OK"; 438ac6a4445SGunnar Mills 439e05aec50SEd Tanous if (accPresent != nullptr && !*accPresent) 440ac6a4445SGunnar Mills { 441ac6a4445SGunnar Mills state = "Absent"; 442ac6a4445SGunnar Mills } 443ac6a4445SGunnar Mills 444e05aec50SEd Tanous if ((accFunctional != nullptr) && !*accFunctional) 445ac6a4445SGunnar Mills { 446ac6a4445SGunnar Mills if (state == "Enabled") 447ac6a4445SGunnar Mills { 448ac6a4445SGunnar Mills health = "Critical"; 449ac6a4445SGunnar Mills } 450ac6a4445SGunnar Mills } 451ac6a4445SGunnar Mills 452ac6a4445SGunnar Mills aResp->res.jsonValue["Status"]["State"] = state; 453ac6a4445SGunnar Mills aResp->res.jsonValue["Status"]["Health"] = health; 454ac6a4445SGunnar Mills aResp->res.jsonValue["ProcessorType"] = "Accelerator"; 455ac6a4445SGunnar Mills }, 456ac6a4445SGunnar Mills service, objPath, "org.freedesktop.DBus.Properties", "GetAll", ""); 457ac6a4445SGunnar Mills } 458ac6a4445SGunnar Mills 459dba0c291SJonathan Doman // OperatingConfig D-Bus Types 460dba0c291SJonathan Doman using TurboProfileProperty = std::vector<std::tuple<uint32_t, size_t>>; 461dba0c291SJonathan Doman using BaseSpeedPrioritySettingsProperty = 462dba0c291SJonathan Doman std::vector<std::tuple<uint32_t, std::vector<uint32_t>>>; 463dba0c291SJonathan Doman // uint32_t and size_t may or may not be the same type, requiring a dedup'd 464dba0c291SJonathan Doman // variant 465168e20c1SEd Tanous using OperatingConfigProperties = 466168e20c1SEd Tanous std::vector<std::pair<std::string, dbus::utility::DbusVariantType>>; 467dba0c291SJonathan Doman 468dba0c291SJonathan Doman /** 469dba0c291SJonathan Doman * Fill out the HighSpeedCoreIDs in a Processor resource from the given 470dba0c291SJonathan Doman * OperatingConfig D-Bus property. 471dba0c291SJonathan Doman * 472dba0c291SJonathan Doman * @param[in,out] aResp Async HTTP response. 473dba0c291SJonathan Doman * @param[in] baseSpeedSettings Full list of base speed priority groups, 474dba0c291SJonathan Doman * to use to determine the list of high 475dba0c291SJonathan Doman * speed cores. 476dba0c291SJonathan Doman */ 477dba0c291SJonathan Doman inline void highSpeedCoreIdsHandler( 4788d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& aResp, 479dba0c291SJonathan Doman const BaseSpeedPrioritySettingsProperty& baseSpeedSettings) 480dba0c291SJonathan Doman { 481dba0c291SJonathan Doman // The D-Bus property does not indicate which bucket is the "high 482dba0c291SJonathan Doman // priority" group, so let's discern that by looking for the one with 483dba0c291SJonathan Doman // highest base frequency. 484dba0c291SJonathan Doman auto highPriorityGroup = baseSpeedSettings.cend(); 485dba0c291SJonathan Doman uint32_t highestBaseSpeed = 0; 486dba0c291SJonathan Doman for (auto it = baseSpeedSettings.cbegin(); it != baseSpeedSettings.cend(); 487dba0c291SJonathan Doman ++it) 488dba0c291SJonathan Doman { 489dba0c291SJonathan Doman const uint32_t baseFreq = std::get<uint32_t>(*it); 490dba0c291SJonathan Doman if (baseFreq > highestBaseSpeed) 491dba0c291SJonathan Doman { 492dba0c291SJonathan Doman highestBaseSpeed = baseFreq; 493dba0c291SJonathan Doman highPriorityGroup = it; 494dba0c291SJonathan Doman } 495dba0c291SJonathan Doman } 496dba0c291SJonathan Doman 497dba0c291SJonathan Doman nlohmann::json& jsonCoreIds = aResp->res.jsonValue["HighSpeedCoreIDs"]; 498dba0c291SJonathan Doman jsonCoreIds = nlohmann::json::array(); 499dba0c291SJonathan Doman 500dba0c291SJonathan Doman // There may not be any entries in the D-Bus property, so only populate 501dba0c291SJonathan Doman // if there was actually something there. 502dba0c291SJonathan Doman if (highPriorityGroup != baseSpeedSettings.cend()) 503dba0c291SJonathan Doman { 504dba0c291SJonathan Doman jsonCoreIds = std::get<std::vector<uint32_t>>(*highPriorityGroup); 505dba0c291SJonathan Doman } 506dba0c291SJonathan Doman } 507dba0c291SJonathan Doman 508dba0c291SJonathan Doman /** 509dba0c291SJonathan Doman * Fill out OperatingConfig related items in a Processor resource by requesting 510dba0c291SJonathan Doman * data from the given D-Bus object. 511dba0c291SJonathan Doman * 512dba0c291SJonathan Doman * @param[in,out] aResp Async HTTP response. 513dba0c291SJonathan Doman * @param[in] cpuId CPU D-Bus name. 514dba0c291SJonathan Doman * @param[in] service D-Bus service to query. 515dba0c291SJonathan Doman * @param[in] objPath D-Bus object to query. 516dba0c291SJonathan Doman */ 5178d1b46d7Szhanghch05 inline void getCpuConfigData(const std::shared_ptr<bmcweb::AsyncResp>& aResp, 518dba0c291SJonathan Doman const std::string& cpuId, 519dba0c291SJonathan Doman const std::string& service, 520dba0c291SJonathan Doman const std::string& objPath) 521dba0c291SJonathan Doman { 522dba0c291SJonathan Doman BMCWEB_LOG_INFO << "Getting CPU operating configs for " << cpuId; 523dba0c291SJonathan Doman 524dba0c291SJonathan Doman // First, GetAll CurrentOperatingConfig properties on the object 525dba0c291SJonathan Doman crow::connections::systemBus->async_method_call( 526dba0c291SJonathan Doman [aResp, cpuId, service]( 527dba0c291SJonathan Doman const boost::system::error_code ec, 528168e20c1SEd Tanous const std::vector<std::pair< 529168e20c1SEd Tanous std::string, dbus::utility::DbusVariantType>>& properties) { 530dba0c291SJonathan Doman if (ec) 531dba0c291SJonathan Doman { 532*002d39b4SEd Tanous BMCWEB_LOG_WARNING << "D-Bus error: " << ec << ", " << ec.message(); 533dba0c291SJonathan Doman messages::internalError(aResp->res); 534dba0c291SJonathan Doman return; 535dba0c291SJonathan Doman } 536dba0c291SJonathan Doman 537dba0c291SJonathan Doman nlohmann::json& json = aResp->res.jsonValue; 538dba0c291SJonathan Doman 539dba0c291SJonathan Doman for (const auto& [dbusPropName, variantVal] : properties) 540dba0c291SJonathan Doman { 541dba0c291SJonathan Doman if (dbusPropName == "AppliedConfig") 542dba0c291SJonathan Doman { 543dba0c291SJonathan Doman const sdbusplus::message::object_path* dbusPathWrapper = 544*002d39b4SEd Tanous std::get_if<sdbusplus::message::object_path>(&variantVal); 545dba0c291SJonathan Doman if (dbusPathWrapper == nullptr) 546dba0c291SJonathan Doman { 547dba0c291SJonathan Doman continue; 548dba0c291SJonathan Doman } 549dba0c291SJonathan Doman 550dba0c291SJonathan Doman const std::string& dbusPath = dbusPathWrapper->str; 551dba0c291SJonathan Doman std::string uri = "/redfish/v1/Systems/system/Processors/" + 552dba0c291SJonathan Doman cpuId + "/OperatingConfigs"; 5531476687dSEd Tanous nlohmann::json::object_t operatingConfig; 5541476687dSEd Tanous operatingConfig["@odata.id"] = uri; 5551476687dSEd Tanous json["OperatingConfigs"] = std::move(operatingConfig); 556dba0c291SJonathan Doman 557dba0c291SJonathan Doman // Reuse the D-Bus config object name for the Redfish 558dba0c291SJonathan Doman // URI 559dba0c291SJonathan Doman size_t baseNamePos = dbusPath.rfind('/'); 560dba0c291SJonathan Doman if (baseNamePos == std::string::npos || 561dba0c291SJonathan Doman baseNamePos == (dbusPath.size() - 1)) 562dba0c291SJonathan Doman { 563dba0c291SJonathan Doman // If the AppliedConfig was somehow not a valid path, 564dba0c291SJonathan Doman // skip adding any more properties, since everything 565dba0c291SJonathan Doman // else is tied to this applied config. 566dba0c291SJonathan Doman messages::internalError(aResp->res); 567dba0c291SJonathan Doman break; 568dba0c291SJonathan Doman } 569dba0c291SJonathan Doman uri += '/'; 570dba0c291SJonathan Doman uri += dbusPath.substr(baseNamePos + 1); 5711476687dSEd Tanous nlohmann::json::object_t appliedOperatingConfig; 5721476687dSEd Tanous appliedOperatingConfig["@odata.id"] = uri; 5731476687dSEd Tanous json["AppliedOperatingConfig"] = 5741476687dSEd Tanous std::move(appliedOperatingConfig); 575dba0c291SJonathan Doman 576dba0c291SJonathan Doman // Once we found the current applied config, queue another 577dba0c291SJonathan Doman // request to read the base freq core ids out of that 578dba0c291SJonathan Doman // config. 579*002d39b4SEd Tanous sdbusplus::asio::getProperty<BaseSpeedPrioritySettingsProperty>( 5801e1e598dSJonathan Doman *crow::connections::systemBus, service, dbusPath, 5811e1e598dSJonathan Doman "xyz.openbmc_project.Inventory.Item.Cpu." 5821e1e598dSJonathan Doman "OperatingConfig", 5831e1e598dSJonathan Doman "BaseSpeedPrioritySettings", 5841e1e598dSJonathan Doman [aResp](const boost::system::error_code ec, 5851e1e598dSJonathan Doman const BaseSpeedPrioritySettingsProperty& 5861e1e598dSJonathan Doman baseSpeedList) { 587dba0c291SJonathan Doman if (ec) 588dba0c291SJonathan Doman { 589*002d39b4SEd Tanous BMCWEB_LOG_WARNING << "D-Bus Property Get error: " 590*002d39b4SEd Tanous << ec; 591dba0c291SJonathan Doman messages::internalError(aResp->res); 592dba0c291SJonathan Doman return; 593dba0c291SJonathan Doman } 5941e1e598dSJonathan Doman 5951e1e598dSJonathan Doman highSpeedCoreIdsHandler(aResp, baseSpeedList); 5961e1e598dSJonathan Doman }); 597dba0c291SJonathan Doman } 598dba0c291SJonathan Doman else if (dbusPropName == "BaseSpeedPriorityEnabled") 599dba0c291SJonathan Doman { 600dba0c291SJonathan Doman const bool* state = std::get_if<bool>(&variantVal); 601dba0c291SJonathan Doman if (state != nullptr) 602dba0c291SJonathan Doman { 603dba0c291SJonathan Doman json["BaseSpeedPriorityState"] = 604dba0c291SJonathan Doman *state ? "Enabled" : "Disabled"; 605dba0c291SJonathan Doman } 606dba0c291SJonathan Doman } 607dba0c291SJonathan Doman } 608dba0c291SJonathan Doman }, 609dba0c291SJonathan Doman service, objPath, "org.freedesktop.DBus.Properties", "GetAll", 610dba0c291SJonathan Doman "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig"); 611dba0c291SJonathan Doman } 612dba0c291SJonathan Doman 613cba4f448SSunnySrivastava1984 /** 614cba4f448SSunnySrivastava1984 * @brief Fill out location info of a processor by 615cba4f448SSunnySrivastava1984 * requesting data from the given D-Bus object. 616cba4f448SSunnySrivastava1984 * 617cba4f448SSunnySrivastava1984 * @param[in,out] aResp Async HTTP response. 618cba4f448SSunnySrivastava1984 * @param[in] service D-Bus service to query. 619cba4f448SSunnySrivastava1984 * @param[in] objPath D-Bus object to query. 620cba4f448SSunnySrivastava1984 */ 6218d1b46d7Szhanghch05 inline void getCpuLocationCode(std::shared_ptr<bmcweb::AsyncResp> aResp, 622cba4f448SSunnySrivastava1984 const std::string& service, 623cba4f448SSunnySrivastava1984 const std::string& objPath) 624cba4f448SSunnySrivastava1984 { 625cba4f448SSunnySrivastava1984 BMCWEB_LOG_DEBUG << "Get Cpu Location Data"; 6261e1e598dSJonathan Doman sdbusplus::asio::getProperty<std::string>( 6271e1e598dSJonathan Doman *crow::connections::systemBus, service, objPath, 6281e1e598dSJonathan Doman "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode", 6291e1e598dSJonathan Doman [objPath, aResp{std::move(aResp)}](const boost::system::error_code ec, 6301e1e598dSJonathan Doman const std::string& property) { 631cba4f448SSunnySrivastava1984 if (ec) 632cba4f448SSunnySrivastava1984 { 633cba4f448SSunnySrivastava1984 BMCWEB_LOG_DEBUG << "DBUS response error"; 634cba4f448SSunnySrivastava1984 messages::internalError(aResp->res); 635cba4f448SSunnySrivastava1984 return; 636cba4f448SSunnySrivastava1984 } 637cba4f448SSunnySrivastava1984 638cba4f448SSunnySrivastava1984 aResp->res.jsonValue["Location"]["PartLocation"]["ServiceLabel"] = 6391e1e598dSJonathan Doman property; 6401e1e598dSJonathan Doman }); 641cba4f448SSunnySrivastava1984 } 642cba4f448SSunnySrivastava1984 643c951448aSJonathan Doman /** 64449e429caSJonathan Doman * Populate the unique identifier in a Processor resource by requesting data 64549e429caSJonathan Doman * from the given D-Bus object. 64649e429caSJonathan Doman * 64749e429caSJonathan Doman * @param[in,out] aResp Async HTTP response. 64849e429caSJonathan Doman * @param[in] service D-Bus service to query. 64949e429caSJonathan Doman * @param[in] objPath D-Bus object to query. 65049e429caSJonathan Doman */ 65149e429caSJonathan Doman inline void getCpuUniqueId(const std::shared_ptr<bmcweb::AsyncResp>& aResp, 65249e429caSJonathan Doman const std::string& service, 65349e429caSJonathan Doman const std::string& objectPath) 65449e429caSJonathan Doman { 65549e429caSJonathan Doman BMCWEB_LOG_DEBUG << "Get CPU UniqueIdentifier"; 6561e1e598dSJonathan Doman sdbusplus::asio::getProperty<std::string>( 6571e1e598dSJonathan Doman *crow::connections::systemBus, service, objectPath, 6581e1e598dSJonathan Doman "xyz.openbmc_project.Inventory.Decorator.UniqueIdentifier", 6591e1e598dSJonathan Doman "UniqueIdentifier", 6601e1e598dSJonathan Doman [aResp](boost::system::error_code ec, const std::string& id) { 6611e1e598dSJonathan Doman if (ec) 66249e429caSJonathan Doman { 66349e429caSJonathan Doman BMCWEB_LOG_ERROR << "Failed to read cpu unique id: " << ec; 66449e429caSJonathan Doman messages::internalError(aResp->res); 66549e429caSJonathan Doman return; 66649e429caSJonathan Doman } 667*002d39b4SEd Tanous aResp->res.jsonValue["ProcessorId"]["ProtectedIdentificationNumber"] = 668*002d39b4SEd Tanous id; 6691e1e598dSJonathan Doman }); 67049e429caSJonathan Doman } 67149e429caSJonathan Doman 67249e429caSJonathan Doman /** 673c951448aSJonathan Doman * Find the D-Bus object representing the requested Processor, and call the 674c951448aSJonathan Doman * handler with the results. If matching object is not found, add 404 error to 675c951448aSJonathan Doman * response and don't call the handler. 676c951448aSJonathan Doman * 677c951448aSJonathan Doman * @param[in,out] resp Async HTTP response. 678c951448aSJonathan Doman * @param[in] processorId Redfish Processor Id. 679c951448aSJonathan Doman * @param[in] handler Callback to continue processing request upon 680c951448aSJonathan Doman * successfully finding object. 681c951448aSJonathan Doman */ 682c951448aSJonathan Doman template <typename Handler> 6838d1b46d7Szhanghch05 inline void getProcessorObject(const std::shared_ptr<bmcweb::AsyncResp>& resp, 684c951448aSJonathan Doman const std::string& processorId, 685c951448aSJonathan Doman Handler&& handler) 686ac6a4445SGunnar Mills { 687ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "Get available system processor resources."; 688ac6a4445SGunnar Mills 689c951448aSJonathan Doman // GetSubTree on all interfaces which provide info about a Processor 690ac6a4445SGunnar Mills crow::connections::systemBus->async_method_call( 691c951448aSJonathan Doman [resp, processorId, handler = std::forward<Handler>(handler)]( 692c951448aSJonathan Doman boost::system::error_code ec, 6935df6eda2SShantappa Teekappanavar const dbus::utility::MapperGetSubTreeResponse& subtree) mutable { 694ac6a4445SGunnar Mills if (ec) 695ac6a4445SGunnar Mills { 696c951448aSJonathan Doman BMCWEB_LOG_DEBUG << "DBUS response error: " << ec; 697c951448aSJonathan Doman messages::internalError(resp->res); 698ac6a4445SGunnar Mills return; 699ac6a4445SGunnar Mills } 7002bab9831SJonathan Doman for (const auto& [objectPath, serviceMap] : subtree) 701ac6a4445SGunnar Mills { 7022bab9831SJonathan Doman // Ignore any objects which don't end with our desired cpu name 7032bab9831SJonathan Doman if (!boost::ends_with(objectPath, processorId)) 704ac6a4445SGunnar Mills { 7052bab9831SJonathan Doman continue; 706ac6a4445SGunnar Mills } 7072bab9831SJonathan Doman 708c951448aSJonathan Doman bool found = false; 709c951448aSJonathan Doman // Filter out objects that don't have the CPU-specific 710c951448aSJonathan Doman // interfaces to make sure we can return 404 on non-CPUs 711c951448aSJonathan Doman // (e.g. /redfish/../Processors/dimm0) 7122bab9831SJonathan Doman for (const auto& [serviceName, interfaceList] : serviceMap) 713ac6a4445SGunnar Mills { 714c951448aSJonathan Doman if (std::find_first_of( 715c951448aSJonathan Doman interfaceList.begin(), interfaceList.end(), 716c951448aSJonathan Doman processorInterfaces.begin(), 717c951448aSJonathan Doman processorInterfaces.end()) != interfaceList.end()) 7182bab9831SJonathan Doman { 719c951448aSJonathan Doman found = true; 720c951448aSJonathan Doman break; 721c951448aSJonathan Doman } 722c951448aSJonathan Doman } 723c951448aSJonathan Doman 724c951448aSJonathan Doman if (!found) 7252bab9831SJonathan Doman { 726c951448aSJonathan Doman continue; 727ac6a4445SGunnar Mills } 728c951448aSJonathan Doman 729c951448aSJonathan Doman // Process the first object which does match our cpu name and 730c951448aSJonathan Doman // required interfaces, and potentially ignore any other 731c951448aSJonathan Doman // matching objects. Assume all interfaces we want to process 732c951448aSJonathan Doman // must be on the same object path. 733c951448aSJonathan Doman 734c951448aSJonathan Doman handler(resp, processorId, objectPath, serviceMap); 735ac6a4445SGunnar Mills return; 736ac6a4445SGunnar Mills } 737c951448aSJonathan Doman messages::resourceNotFound(resp->res, "Processor", processorId); 738ac6a4445SGunnar Mills }, 739ac6a4445SGunnar Mills "xyz.openbmc_project.ObjectMapper", 740ac6a4445SGunnar Mills "/xyz/openbmc_project/object_mapper", 741ac6a4445SGunnar Mills "xyz.openbmc_project.ObjectMapper", "GetSubTree", 7422bab9831SJonathan Doman "/xyz/openbmc_project/inventory", 0, 74349e429caSJonathan Doman std::array<const char*, 8>{ 74471b82f26SSharad Yadav "xyz.openbmc_project.Common.UUID", 7452bab9831SJonathan Doman "xyz.openbmc_project.Inventory.Decorator.Asset", 7462bab9831SJonathan Doman "xyz.openbmc_project.Inventory.Decorator.Revision", 7472bab9831SJonathan Doman "xyz.openbmc_project.Inventory.Item.Cpu", 748cba4f448SSunnySrivastava1984 "xyz.openbmc_project.Inventory.Decorator.LocationCode", 749dba0c291SJonathan Doman "xyz.openbmc_project.Inventory.Item.Accelerator", 75049e429caSJonathan Doman "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig", 75149e429caSJonathan Doman "xyz.openbmc_project.Inventory.Decorator.UniqueIdentifier"}); 752ac6a4445SGunnar Mills } 753ac6a4445SGunnar Mills 7548d1b46d7Szhanghch05 inline void getProcessorData(const std::shared_ptr<bmcweb::AsyncResp>& aResp, 755c951448aSJonathan Doman const std::string& processorId, 756c951448aSJonathan Doman const std::string& objectPath, 7575df6eda2SShantappa Teekappanavar const dbus::utility::MapperServiceMap& serviceMap) 758c951448aSJonathan Doman { 759c951448aSJonathan Doman for (const auto& [serviceName, interfaceList] : serviceMap) 760c951448aSJonathan Doman { 761c951448aSJonathan Doman for (const auto& interface : interfaceList) 762c951448aSJonathan Doman { 763c951448aSJonathan Doman if (interface == "xyz.openbmc_project.Inventory.Decorator.Asset") 764c951448aSJonathan Doman { 765c951448aSJonathan Doman getCpuAssetData(aResp, serviceName, objectPath); 766c951448aSJonathan Doman } 7670fda0f12SGeorge Liu else if (interface == 7680fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.Revision") 769c951448aSJonathan Doman { 770c951448aSJonathan Doman getCpuRevisionData(aResp, serviceName, objectPath); 771c951448aSJonathan Doman } 772c951448aSJonathan Doman else if (interface == "xyz.openbmc_project.Inventory.Item.Cpu") 773c951448aSJonathan Doman { 774c951448aSJonathan Doman getCpuDataByService(aResp, processorId, serviceName, 775c951448aSJonathan Doman objectPath); 776c951448aSJonathan Doman } 7770fda0f12SGeorge Liu else if (interface == 7780fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Item.Accelerator") 779c951448aSJonathan Doman { 780c951448aSJonathan Doman getAcceleratorDataByService(aResp, processorId, serviceName, 781c951448aSJonathan Doman objectPath); 782c951448aSJonathan Doman } 7830fda0f12SGeorge Liu else if ( 7840fda0f12SGeorge Liu interface == 7850fda0f12SGeorge Liu "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig") 786c951448aSJonathan Doman { 787c951448aSJonathan Doman getCpuConfigData(aResp, processorId, serviceName, objectPath); 788c951448aSJonathan Doman } 7890fda0f12SGeorge Liu else if (interface == 7900fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.LocationCode") 791c951448aSJonathan Doman { 792c951448aSJonathan Doman getCpuLocationCode(aResp, serviceName, objectPath); 793c951448aSJonathan Doman } 79471b82f26SSharad Yadav else if (interface == "xyz.openbmc_project.Common.UUID") 79571b82f26SSharad Yadav { 79671b82f26SSharad Yadav getProcessorUUID(aResp, serviceName, objectPath); 79771b82f26SSharad Yadav } 7980fda0f12SGeorge Liu else if (interface == 7990fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.UniqueIdentifier") 80049e429caSJonathan Doman { 80149e429caSJonathan Doman getCpuUniqueId(aResp, serviceName, objectPath); 80249e429caSJonathan Doman } 803c951448aSJonathan Doman } 804c951448aSJonathan Doman } 805c951448aSJonathan Doman } 806c951448aSJonathan Doman 807dba0c291SJonathan Doman /** 808dba0c291SJonathan Doman * Request all the properties for the given D-Bus object and fill out the 809dba0c291SJonathan Doman * related entries in the Redfish OperatingConfig response. 810dba0c291SJonathan Doman * 811dba0c291SJonathan Doman * @param[in,out] aResp Async HTTP response. 812dba0c291SJonathan Doman * @param[in] service D-Bus service name to query. 813dba0c291SJonathan Doman * @param[in] objPath D-Bus object to query. 814dba0c291SJonathan Doman */ 8158d1b46d7Szhanghch05 inline void 8168d1b46d7Szhanghch05 getOperatingConfigData(const std::shared_ptr<bmcweb::AsyncResp>& aResp, 817dba0c291SJonathan Doman const std::string& service, 818dba0c291SJonathan Doman const std::string& objPath) 819dba0c291SJonathan Doman { 820dba0c291SJonathan Doman crow::connections::systemBus->async_method_call( 821914e2d5dSEd Tanous [aResp](const boost::system::error_code ec, 822dba0c291SJonathan Doman const OperatingConfigProperties& properties) { 823dba0c291SJonathan Doman if (ec) 824dba0c291SJonathan Doman { 825*002d39b4SEd Tanous BMCWEB_LOG_WARNING << "D-Bus error: " << ec << ", " << ec.message(); 826dba0c291SJonathan Doman messages::internalError(aResp->res); 827dba0c291SJonathan Doman return; 828dba0c291SJonathan Doman } 829dba0c291SJonathan Doman 830dba0c291SJonathan Doman nlohmann::json& json = aResp->res.jsonValue; 831dba0c291SJonathan Doman for (const auto& [key, variant] : properties) 832dba0c291SJonathan Doman { 833dba0c291SJonathan Doman if (key == "AvailableCoreCount") 834dba0c291SJonathan Doman { 835dba0c291SJonathan Doman const size_t* cores = std::get_if<size_t>(&variant); 836dba0c291SJonathan Doman if (cores != nullptr) 837dba0c291SJonathan Doman { 838dba0c291SJonathan Doman json["TotalAvailableCoreCount"] = *cores; 839dba0c291SJonathan Doman } 840dba0c291SJonathan Doman } 841dba0c291SJonathan Doman else if (key == "BaseSpeed") 842dba0c291SJonathan Doman { 843dba0c291SJonathan Doman const uint32_t* speed = std::get_if<uint32_t>(&variant); 844dba0c291SJonathan Doman if (speed != nullptr) 845dba0c291SJonathan Doman { 846dba0c291SJonathan Doman json["BaseSpeedMHz"] = *speed; 847dba0c291SJonathan Doman } 848dba0c291SJonathan Doman } 849dba0c291SJonathan Doman else if (key == "MaxJunctionTemperature") 850dba0c291SJonathan Doman { 851dba0c291SJonathan Doman const uint32_t* temp = std::get_if<uint32_t>(&variant); 852dba0c291SJonathan Doman if (temp != nullptr) 853dba0c291SJonathan Doman { 854dba0c291SJonathan Doman json["MaxJunctionTemperatureCelsius"] = *temp; 855dba0c291SJonathan Doman } 856dba0c291SJonathan Doman } 857dba0c291SJonathan Doman else if (key == "MaxSpeed") 858dba0c291SJonathan Doman { 859dba0c291SJonathan Doman const uint32_t* speed = std::get_if<uint32_t>(&variant); 860dba0c291SJonathan Doman if (speed != nullptr) 861dba0c291SJonathan Doman { 862dba0c291SJonathan Doman json["MaxSpeedMHz"] = *speed; 863dba0c291SJonathan Doman } 864dba0c291SJonathan Doman } 865dba0c291SJonathan Doman else if (key == "PowerLimit") 866dba0c291SJonathan Doman { 867dba0c291SJonathan Doman const uint32_t* tdp = std::get_if<uint32_t>(&variant); 868dba0c291SJonathan Doman if (tdp != nullptr) 869dba0c291SJonathan Doman { 870dba0c291SJonathan Doman json["TDPWatts"] = *tdp; 871dba0c291SJonathan Doman } 872dba0c291SJonathan Doman } 873dba0c291SJonathan Doman else if (key == "TurboProfile") 874dba0c291SJonathan Doman { 875dba0c291SJonathan Doman const auto* turboList = 876dba0c291SJonathan Doman std::get_if<TurboProfileProperty>(&variant); 877dba0c291SJonathan Doman if (turboList == nullptr) 878dba0c291SJonathan Doman { 879dba0c291SJonathan Doman continue; 880dba0c291SJonathan Doman } 881dba0c291SJonathan Doman 882dba0c291SJonathan Doman nlohmann::json& turboArray = json["TurboProfile"]; 883dba0c291SJonathan Doman turboArray = nlohmann::json::array(); 884dba0c291SJonathan Doman for (const auto& [turboSpeed, coreCount] : *turboList) 885dba0c291SJonathan Doman { 8861476687dSEd Tanous nlohmann::json::object_t turbo; 8871476687dSEd Tanous turbo["ActiveCoreCount"] = coreCount; 8881476687dSEd Tanous turbo["MaxSpeedMHz"] = turboSpeed; 8891476687dSEd Tanous turboArray.push_back(std::move(turbo)); 890dba0c291SJonathan Doman } 891dba0c291SJonathan Doman } 892dba0c291SJonathan Doman else if (key == "BaseSpeedPrioritySettings") 893dba0c291SJonathan Doman { 894dba0c291SJonathan Doman const auto* baseSpeedList = 895*002d39b4SEd Tanous std::get_if<BaseSpeedPrioritySettingsProperty>(&variant); 896dba0c291SJonathan Doman if (baseSpeedList == nullptr) 897dba0c291SJonathan Doman { 898dba0c291SJonathan Doman continue; 899dba0c291SJonathan Doman } 900dba0c291SJonathan Doman 901dba0c291SJonathan Doman nlohmann::json& baseSpeedArray = 902dba0c291SJonathan Doman json["BaseSpeedPrioritySettings"]; 903dba0c291SJonathan Doman baseSpeedArray = nlohmann::json::array(); 904dba0c291SJonathan Doman for (const auto& [baseSpeed, coreList] : *baseSpeedList) 905dba0c291SJonathan Doman { 9061476687dSEd Tanous nlohmann::json::object_t speed; 9071476687dSEd Tanous speed["CoreCount"] = coreList.size(); 9081476687dSEd Tanous speed["CoreIDs"] = coreList; 9091476687dSEd Tanous speed["BaseSpeedMHz"] = baseSpeed; 9101476687dSEd Tanous baseSpeedArray.push_back(std::move(speed)); 911dba0c291SJonathan Doman } 912dba0c291SJonathan Doman } 913dba0c291SJonathan Doman } 914dba0c291SJonathan Doman }, 915dba0c291SJonathan Doman service, objPath, "org.freedesktop.DBus.Properties", "GetAll", 916dba0c291SJonathan Doman "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig"); 917dba0c291SJonathan Doman } 918dba0c291SJonathan Doman 9193cde86f1SJonathan Doman /** 9203cde86f1SJonathan Doman * Handle the D-Bus response from attempting to set the CPU's AppliedConfig 9213cde86f1SJonathan Doman * property. Main task is to translate error messages into Redfish errors. 9223cde86f1SJonathan Doman * 9233cde86f1SJonathan Doman * @param[in,out] resp HTTP response. 9243cde86f1SJonathan Doman * @param[in] setPropVal Value which we attempted to set. 9253cde86f1SJonathan Doman * @param[in] ec D-Bus response error code. 9263cde86f1SJonathan Doman * @param[in] msg D-Bus response message. 9273cde86f1SJonathan Doman */ 9283cde86f1SJonathan Doman inline void 9293cde86f1SJonathan Doman handleAppliedConfigResponse(const std::shared_ptr<bmcweb::AsyncResp>& resp, 9303cde86f1SJonathan Doman const std::string& setPropVal, 9313cde86f1SJonathan Doman boost::system::error_code ec, 9323cde86f1SJonathan Doman const sdbusplus::message::message& msg) 9333cde86f1SJonathan Doman { 9343cde86f1SJonathan Doman if (!ec) 9353cde86f1SJonathan Doman { 9363cde86f1SJonathan Doman BMCWEB_LOG_DEBUG << "Set Property succeeded"; 9373cde86f1SJonathan Doman return; 9383cde86f1SJonathan Doman } 9393cde86f1SJonathan Doman 9403cde86f1SJonathan Doman BMCWEB_LOG_DEBUG << "Set Property failed: " << ec; 9413cde86f1SJonathan Doman 9423cde86f1SJonathan Doman const sd_bus_error* dbusError = msg.get_error(); 9433cde86f1SJonathan Doman if (dbusError == nullptr) 9443cde86f1SJonathan Doman { 9453cde86f1SJonathan Doman messages::internalError(resp->res); 9463cde86f1SJonathan Doman return; 9473cde86f1SJonathan Doman } 9483cde86f1SJonathan Doman 9493cde86f1SJonathan Doman // The asio error code doesn't know about our custom errors, so we have to 9503cde86f1SJonathan Doman // parse the error string. Some of these D-Bus -> Redfish translations are a 9513cde86f1SJonathan Doman // stretch, but it's good to try to communicate something vaguely useful. 9523cde86f1SJonathan Doman if (strcmp(dbusError->name, 9533cde86f1SJonathan Doman "xyz.openbmc_project.Common.Error.InvalidArgument") == 0) 9543cde86f1SJonathan Doman { 9553cde86f1SJonathan Doman // Service did not like the object_path we tried to set. 9563cde86f1SJonathan Doman messages::propertyValueIncorrect( 9573cde86f1SJonathan Doman resp->res, "AppliedOperatingConfig/@odata.id", setPropVal); 9583cde86f1SJonathan Doman } 9593cde86f1SJonathan Doman else if (strcmp(dbusError->name, 9603cde86f1SJonathan Doman "xyz.openbmc_project.Common.Error.NotAllowed") == 0) 9613cde86f1SJonathan Doman { 9623cde86f1SJonathan Doman // Service indicates we can never change the config for this processor. 9633cde86f1SJonathan Doman messages::propertyNotWritable(resp->res, "AppliedOperatingConfig"); 9643cde86f1SJonathan Doman } 9653cde86f1SJonathan Doman else if (strcmp(dbusError->name, 9663cde86f1SJonathan Doman "xyz.openbmc_project.Common.Error.Unavailable") == 0) 9673cde86f1SJonathan Doman { 9683cde86f1SJonathan Doman // Service indicates the config cannot be changed right now, but maybe 9693cde86f1SJonathan Doman // in a different system state. 9703cde86f1SJonathan Doman messages::resourceInStandby(resp->res); 9713cde86f1SJonathan Doman } 9723cde86f1SJonathan Doman else 9733cde86f1SJonathan Doman { 9743cde86f1SJonathan Doman messages::internalError(resp->res); 9753cde86f1SJonathan Doman } 9763cde86f1SJonathan Doman } 9773cde86f1SJonathan Doman 9783cde86f1SJonathan Doman /** 9793cde86f1SJonathan Doman * Handle the PATCH operation of the AppliedOperatingConfig property. Do basic 9803cde86f1SJonathan Doman * validation of the input data, and then set the D-Bus property. 9813cde86f1SJonathan Doman * 9823cde86f1SJonathan Doman * @param[in,out] resp Async HTTP response. 9833cde86f1SJonathan Doman * @param[in] processorId Processor's Id. 9843cde86f1SJonathan Doman * @param[in] appliedConfigUri New property value to apply. 9853cde86f1SJonathan Doman * @param[in] cpuObjectPath Path of CPU object to modify. 9863cde86f1SJonathan Doman * @param[in] serviceMap Service map for CPU object. 9873cde86f1SJonathan Doman */ 9883cde86f1SJonathan Doman inline void patchAppliedOperatingConfig( 9893cde86f1SJonathan Doman const std::shared_ptr<bmcweb::AsyncResp>& resp, 9903cde86f1SJonathan Doman const std::string& processorId, const std::string& appliedConfigUri, 9915df6eda2SShantappa Teekappanavar const std::string& cpuObjectPath, 9925df6eda2SShantappa Teekappanavar const dbus::utility::MapperServiceMap& serviceMap) 9933cde86f1SJonathan Doman { 9943cde86f1SJonathan Doman // Check that the property even exists by checking for the interface 9953cde86f1SJonathan Doman const std::string* controlService = nullptr; 9963cde86f1SJonathan Doman for (const auto& [serviceName, interfaceList] : serviceMap) 9973cde86f1SJonathan Doman { 9983cde86f1SJonathan Doman if (std::find(interfaceList.begin(), interfaceList.end(), 9993cde86f1SJonathan Doman "xyz.openbmc_project.Control.Processor." 10003cde86f1SJonathan Doman "CurrentOperatingConfig") != interfaceList.end()) 10013cde86f1SJonathan Doman { 10023cde86f1SJonathan Doman controlService = &serviceName; 10033cde86f1SJonathan Doman break; 10043cde86f1SJonathan Doman } 10053cde86f1SJonathan Doman } 10063cde86f1SJonathan Doman 10073cde86f1SJonathan Doman if (controlService == nullptr) 10083cde86f1SJonathan Doman { 10093cde86f1SJonathan Doman messages::internalError(resp->res); 10103cde86f1SJonathan Doman return; 10113cde86f1SJonathan Doman } 10123cde86f1SJonathan Doman 10133cde86f1SJonathan Doman // Check that the config URI is a child of the cpu URI being patched. 10143cde86f1SJonathan Doman std::string expectedPrefix("/redfish/v1/Systems/system/Processors/"); 10153cde86f1SJonathan Doman expectedPrefix += processorId; 10163cde86f1SJonathan Doman expectedPrefix += "/OperatingConfigs/"; 10173cde86f1SJonathan Doman if (!boost::starts_with(appliedConfigUri, expectedPrefix) || 10183cde86f1SJonathan Doman expectedPrefix.size() == appliedConfigUri.size()) 10193cde86f1SJonathan Doman { 10203cde86f1SJonathan Doman messages::propertyValueIncorrect( 10213cde86f1SJonathan Doman resp->res, "AppliedOperatingConfig/@odata.id", appliedConfigUri); 10223cde86f1SJonathan Doman return; 10233cde86f1SJonathan Doman } 10243cde86f1SJonathan Doman 10253cde86f1SJonathan Doman // Generate the D-Bus path of the OperatingConfig object, by assuming it's a 10263cde86f1SJonathan Doman // direct child of the CPU object. 10273cde86f1SJonathan Doman // Strip the expectedPrefix from the config URI to get the "filename", and 10283cde86f1SJonathan Doman // append to the CPU's path. 10293cde86f1SJonathan Doman std::string configBaseName = appliedConfigUri.substr(expectedPrefix.size()); 10303cde86f1SJonathan Doman sdbusplus::message::object_path configPath(cpuObjectPath); 10313cde86f1SJonathan Doman configPath /= configBaseName; 10323cde86f1SJonathan Doman 10333cde86f1SJonathan Doman BMCWEB_LOG_INFO << "Setting config to " << configPath.str; 10343cde86f1SJonathan Doman 10353cde86f1SJonathan Doman // Set the property, with handler to check error responses 10363cde86f1SJonathan Doman crow::connections::systemBus->async_method_call( 1037914e2d5dSEd Tanous [resp, appliedConfigUri](const boost::system::error_code ec, 1038914e2d5dSEd Tanous const sdbusplus::message::message& msg) { 10393cde86f1SJonathan Doman handleAppliedConfigResponse(resp, appliedConfigUri, ec, msg); 10403cde86f1SJonathan Doman }, 10413cde86f1SJonathan Doman *controlService, cpuObjectPath, "org.freedesktop.DBus.Properties", 10423cde86f1SJonathan Doman "Set", "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig", 1043168e20c1SEd Tanous "AppliedConfig", dbus::utility::DbusVariantType(std::move(configPath))); 10443cde86f1SJonathan Doman } 10453cde86f1SJonathan Doman 10467e860f15SJohn Edward Broadbent inline void requestRoutesOperatingConfigCollection(App& app) 1047dba0c291SJonathan Doman { 1048dba0c291SJonathan Doman 10497e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 10507e860f15SJohn Edward Broadbent app, "/redfish/v1/Systems/system/Processors/<str>/OperatingConfigs/") 1051ed398213SEd Tanous .privileges(redfish::privileges::getOperatingConfigCollection) 1052*002d39b4SEd Tanous .methods(boost::beast::http::verb::get)( 1053*002d39b4SEd Tanous [&app](const crow::Request& req, 105445ca1b86SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 10557e860f15SJohn Edward Broadbent const std::string& cpuName) { 105645ca1b86SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) 105745ca1b86SEd Tanous { 105845ca1b86SEd Tanous return; 105945ca1b86SEd Tanous } 10608d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.type"] = 1061dba0c291SJonathan Doman "#OperatingConfigCollection.OperatingConfigCollection"; 10628d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.id"] = req.url; 10630fda0f12SGeorge Liu asyncResp->res.jsonValue["Name"] = "Operating Config Collection"; 1064dba0c291SJonathan Doman 10657e860f15SJohn Edward Broadbent // First find the matching CPU object so we know how to 10667e860f15SJohn Edward Broadbent // constrain our search for related Config objects. 1067dba0c291SJonathan Doman crow::connections::systemBus->async_method_call( 1068*002d39b4SEd Tanous [asyncResp, cpuName]( 1069*002d39b4SEd Tanous const boost::system::error_code ec, 1070*002d39b4SEd Tanous const dbus::utility::MapperGetSubTreePathsResponse& objects) { 1071dba0c291SJonathan Doman if (ec) 1072dba0c291SJonathan Doman { 1073dba0c291SJonathan Doman BMCWEB_LOG_WARNING << "D-Bus error: " << ec << ", " 1074dba0c291SJonathan Doman << ec.message(); 1075dba0c291SJonathan Doman messages::internalError(asyncResp->res); 1076dba0c291SJonathan Doman return; 1077dba0c291SJonathan Doman } 1078dba0c291SJonathan Doman 1079dba0c291SJonathan Doman for (const std::string& object : objects) 1080dba0c291SJonathan Doman { 1081dba0c291SJonathan Doman if (!boost::ends_with(object, cpuName)) 1082dba0c291SJonathan Doman { 1083dba0c291SJonathan Doman continue; 1084dba0c291SJonathan Doman } 1085dba0c291SJonathan Doman 10867e860f15SJohn Edward Broadbent // Not expected that there will be multiple matching 10877e860f15SJohn Edward Broadbent // CPU objects, but if there are just use the first 10887e860f15SJohn Edward Broadbent // one. 1089dba0c291SJonathan Doman 10907e860f15SJohn Edward Broadbent // Use the common search routine to construct the 10917e860f15SJohn Edward Broadbent // Collection of all Config objects under this CPU. 1092dba0c291SJonathan Doman collection_util::getCollectionMembers( 1093dba0c291SJonathan Doman asyncResp, 10940fda0f12SGeorge Liu "/redfish/v1/Systems/system/Processors/" + cpuName + 10950fda0f12SGeorge Liu "/OperatingConfigs", 10960fda0f12SGeorge Liu {"xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig"}, 1097dba0c291SJonathan Doman object.c_str()); 1098dba0c291SJonathan Doman return; 1099dba0c291SJonathan Doman } 1100dba0c291SJonathan Doman }, 1101dba0c291SJonathan Doman "xyz.openbmc_project.ObjectMapper", 1102dba0c291SJonathan Doman "/xyz/openbmc_project/object_mapper", 1103dba0c291SJonathan Doman "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", 1104dba0c291SJonathan Doman "/xyz/openbmc_project/inventory", 0, 11057e860f15SJohn Edward Broadbent std::array<const char*, 1>{ 11060fda0f12SGeorge Liu "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig"}); 11077e860f15SJohn Edward Broadbent }); 1108dba0c291SJonathan Doman } 1109dba0c291SJonathan Doman 11107e860f15SJohn Edward Broadbent inline void requestRoutesOperatingConfig(App& app) 1111dba0c291SJonathan Doman { 11127e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 11137e860f15SJohn Edward Broadbent app, 11147e860f15SJohn Edward Broadbent "/redfish/v1/Systems/system/Processors/<str>/OperatingConfigs/<str>/") 1115ed398213SEd Tanous .privileges(redfish::privileges::getOperatingConfig) 1116*002d39b4SEd Tanous .methods(boost::beast::http::verb::get)( 1117*002d39b4SEd Tanous [&app](const crow::Request& req, 111845ca1b86SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1119*002d39b4SEd Tanous const std::string& cpuName, const std::string& configName) { 112045ca1b86SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) 112145ca1b86SEd Tanous { 112245ca1b86SEd Tanous return; 112345ca1b86SEd Tanous } 11247e860f15SJohn Edward Broadbent // Ask for all objects implementing OperatingConfig so we can search 11257e860f15SJohn Edward Broadbent // for one with a matching name 1126dba0c291SJonathan Doman crow::connections::systemBus->async_method_call( 11275df6eda2SShantappa Teekappanavar [asyncResp, cpuName, configName, reqUrl{req.url}]( 11285df6eda2SShantappa Teekappanavar boost::system::error_code ec, 11295df6eda2SShantappa Teekappanavar const dbus::utility::MapperGetSubTreeResponse& subtree) { 1130dba0c291SJonathan Doman if (ec) 1131dba0c291SJonathan Doman { 1132dba0c291SJonathan Doman BMCWEB_LOG_WARNING << "D-Bus error: " << ec << ", " 1133dba0c291SJonathan Doman << ec.message(); 1134dba0c291SJonathan Doman messages::internalError(asyncResp->res); 1135dba0c291SJonathan Doman return; 1136dba0c291SJonathan Doman } 1137*002d39b4SEd Tanous const std::string expectedEnding = cpuName + '/' + configName; 1138dba0c291SJonathan Doman for (const auto& [objectPath, serviceMap] : subtree) 1139dba0c291SJonathan Doman { 1140dba0c291SJonathan Doman // Ignore any configs without matching cpuX/configY 1141dba0c291SJonathan Doman if (!boost::ends_with(objectPath, expectedEnding) || 1142dba0c291SJonathan Doman serviceMap.empty()) 1143dba0c291SJonathan Doman { 1144dba0c291SJonathan Doman continue; 1145dba0c291SJonathan Doman } 1146dba0c291SJonathan Doman 1147dba0c291SJonathan Doman nlohmann::json& json = asyncResp->res.jsonValue; 1148*002d39b4SEd Tanous json["@odata.type"] = "#OperatingConfig.v1_0_0.OperatingConfig"; 1149dba0c291SJonathan Doman json["@odata.id"] = reqUrl; 1150dba0c291SJonathan Doman json["Name"] = "Processor Profile"; 1151dba0c291SJonathan Doman json["Id"] = configName; 1152dba0c291SJonathan Doman 1153dba0c291SJonathan Doman // Just use the first implementation of the object - not 11547e860f15SJohn Edward Broadbent // expected that there would be multiple matching 11557e860f15SJohn Edward Broadbent // services 1156*002d39b4SEd Tanous getOperatingConfigData(asyncResp, serviceMap.begin()->first, 1157*002d39b4SEd Tanous objectPath); 1158dba0c291SJonathan Doman return; 1159dba0c291SJonathan Doman } 1160*002d39b4SEd Tanous messages::resourceNotFound(asyncResp->res, "OperatingConfig", 1161*002d39b4SEd Tanous configName); 1162dba0c291SJonathan Doman }, 1163dba0c291SJonathan Doman "xyz.openbmc_project.ObjectMapper", 1164dba0c291SJonathan Doman "/xyz/openbmc_project/object_mapper", 1165dba0c291SJonathan Doman "xyz.openbmc_project.ObjectMapper", "GetSubTree", 1166dba0c291SJonathan Doman "/xyz/openbmc_project/inventory", 0, 1167dba0c291SJonathan Doman std::array<const char*, 1>{ 1168dba0c291SJonathan Doman "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig"}); 11697e860f15SJohn Edward Broadbent }); 1170ac6a4445SGunnar Mills } 1171ac6a4445SGunnar Mills 11727e860f15SJohn Edward Broadbent inline void requestRoutesProcessorCollection(App& app) 11737e860f15SJohn Edward Broadbent { 1174ac6a4445SGunnar Mills /** 1175ac6a4445SGunnar Mills * Functions triggers appropriate requests on DBus 1176ac6a4445SGunnar Mills */ 11777e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Processors/") 1178ed398213SEd Tanous .privileges(redfish::privileges::getProcessorCollection) 11797e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 118045ca1b86SEd Tanous [&app](const crow::Request& req, 11817e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 118245ca1b86SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) 118345ca1b86SEd Tanous { 118445ca1b86SEd Tanous return; 118545ca1b86SEd Tanous } 11868d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.type"] = 1187ac6a4445SGunnar Mills "#ProcessorCollection.ProcessorCollection"; 11888d1b46d7Szhanghch05 asyncResp->res.jsonValue["Name"] = "Processor Collection"; 1189ac6a4445SGunnar Mills 11908d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.id"] = 11918d1b46d7Szhanghch05 "/redfish/v1/Systems/system/Processors"; 1192ac6a4445SGunnar Mills 119305030b8eSGunnar Mills collection_util::getCollectionMembers( 119405030b8eSGunnar Mills asyncResp, "/redfish/v1/Systems/system/Processors", 1195c951448aSJonathan Doman std::vector<const char*>(processorInterfaces.begin(), 1196c951448aSJonathan Doman processorInterfaces.end())); 11977e860f15SJohn Edward Broadbent }); 1198ac6a4445SGunnar Mills } 1199ac6a4445SGunnar Mills 12007e860f15SJohn Edward Broadbent inline void requestRoutesProcessor(App& app) 12017e860f15SJohn Edward Broadbent { 1202ac6a4445SGunnar Mills /** 1203ac6a4445SGunnar Mills * Functions triggers appropriate requests on DBus 1204ac6a4445SGunnar Mills */ 12057e860f15SJohn Edward Broadbent 12067e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Processors/<str>/") 1207ed398213SEd Tanous .privileges(redfish::privileges::getProcessor) 12087e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 120945ca1b86SEd Tanous [&app](const crow::Request& req, 12107e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 12117e860f15SJohn Edward Broadbent const std::string& processorId) { 121245ca1b86SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) 121345ca1b86SEd Tanous { 121445ca1b86SEd Tanous return; 121545ca1b86SEd Tanous } 12168d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.type"] = 12178d1b46d7Szhanghch05 "#Processor.v1_11_0.Processor"; 12188d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.id"] = 1219ac6a4445SGunnar Mills "/redfish/v1/Systems/system/Processors/" + processorId; 1220ac6a4445SGunnar Mills 1221c951448aSJonathan Doman getProcessorObject(asyncResp, processorId, getProcessorData); 12227e860f15SJohn Edward Broadbent }); 12233cde86f1SJonathan Doman 12247e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Processors/<str>/") 1225ed398213SEd Tanous .privileges(redfish::privileges::patchProcessor) 12267e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::patch)( 122745ca1b86SEd Tanous [&app](const crow::Request& req, 12287e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 12297e860f15SJohn Edward Broadbent const std::string& processorId) { 123045ca1b86SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) 123145ca1b86SEd Tanous { 123245ca1b86SEd Tanous return; 123345ca1b86SEd Tanous } 12343cde86f1SJonathan Doman std::optional<nlohmann::json> appliedConfigJson; 123515ed6780SWilly Tu if (!json_util::readJsonPatch(req, asyncResp->res, 12367e860f15SJohn Edward Broadbent "AppliedOperatingConfig", 12373cde86f1SJonathan Doman appliedConfigJson)) 12383cde86f1SJonathan Doman { 12393cde86f1SJonathan Doman return; 12403cde86f1SJonathan Doman } 12413cde86f1SJonathan Doman 12423cde86f1SJonathan Doman std::string appliedConfigUri; 12433cde86f1SJonathan Doman if (appliedConfigJson) 12443cde86f1SJonathan Doman { 12453cde86f1SJonathan Doman if (!json_util::readJson(*appliedConfigJson, asyncResp->res, 12463cde86f1SJonathan Doman "@odata.id", appliedConfigUri)) 12473cde86f1SJonathan Doman { 12483cde86f1SJonathan Doman return; 12493cde86f1SJonathan Doman } 12507e860f15SJohn Edward Broadbent // Check for 404 and find matching D-Bus object, then run 12517e860f15SJohn Edward Broadbent // property patch handlers if that all succeeds. 12523cde86f1SJonathan Doman getProcessorObject( 12537e860f15SJohn Edward Broadbent asyncResp, processorId, 12543cde86f1SJonathan Doman [appliedConfigUri = std::move(appliedConfigUri)]( 12553cde86f1SJonathan Doman const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 12563cde86f1SJonathan Doman const std::string& processorId, 12573cde86f1SJonathan Doman const std::string& objectPath, 12585df6eda2SShantappa Teekappanavar const dbus::utility::MapperServiceMap& serviceMap) { 12593cde86f1SJonathan Doman patchAppliedOperatingConfig(asyncResp, processorId, 1260*002d39b4SEd Tanous appliedConfigUri, objectPath, 1261*002d39b4SEd Tanous serviceMap); 12623cde86f1SJonathan Doman }); 12633cde86f1SJonathan Doman } 12647e860f15SJohn Edward Broadbent }); 12653cde86f1SJonathan Doman } 1266ac6a4445SGunnar Mills 1267ac6a4445SGunnar Mills } // namespace redfish 1268