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 18ac6a4445SGunnar Mills #include "health.hpp" 19ac6a4445SGunnar Mills 207e860f15SJohn Edward Broadbent #include <app.hpp> 21ac6a4445SGunnar Mills #include <boost/container/flat_map.hpp> 22ed398213SEd Tanous #include <registries/privilege_registry.hpp> 23dba0c291SJonathan Doman #include <sdbusplus/message/native_types.hpp> 24dba0c291SJonathan Doman #include <sdbusplus/utility/dedup_variant.hpp> 25ac6a4445SGunnar Mills #include <utils/collection.hpp> 26ac6a4445SGunnar Mills #include <utils/json_utils.hpp> 27ac6a4445SGunnar Mills 28ac6a4445SGunnar Mills namespace redfish 29ac6a4445SGunnar Mills { 30ac6a4445SGunnar Mills 31ac6a4445SGunnar Mills using InterfacesProperties = boost::container::flat_map< 32ac6a4445SGunnar Mills std::string, 33ac6a4445SGunnar Mills boost::container::flat_map<std::string, dbus::utility::DbusVariantType>>; 34ac6a4445SGunnar Mills 35c951448aSJonathan Doman // Map of service name to list of interfaces 36c951448aSJonathan Doman using MapperServiceMap = 37c951448aSJonathan Doman std::vector<std::pair<std::string, std::vector<std::string>>>; 38c951448aSJonathan Doman 39c951448aSJonathan Doman // Map of object paths to MapperServiceMaps 40c951448aSJonathan Doman using MapperGetSubTreeResponse = 41c951448aSJonathan Doman std::vector<std::pair<std::string, MapperServiceMap>>; 42c951448aSJonathan Doman 43c951448aSJonathan Doman // Interfaces which imply a D-Bus object represents a Processor 44c951448aSJonathan Doman constexpr std::array<const char*, 2> processorInterfaces = { 45c951448aSJonathan Doman "xyz.openbmc_project.Inventory.Item.Cpu", 46c951448aSJonathan Doman "xyz.openbmc_project.Inventory.Item.Accelerator"}; 472bab9831SJonathan Doman 4871b82f26SSharad Yadav /** 4971b82f26SSharad Yadav * @brief Fill out uuid info of a processor by 5071b82f26SSharad Yadav * requesting data from the given D-Bus object. 5171b82f26SSharad Yadav * 5271b82f26SSharad Yadav * @param[in,out] aResp Async HTTP response. 5371b82f26SSharad Yadav * @param[in] service D-Bus service to query. 5471b82f26SSharad Yadav * @param[in] objPath D-Bus object to query. 5571b82f26SSharad Yadav */ 5671b82f26SSharad Yadav inline void getProcessorUUID(std::shared_ptr<bmcweb::AsyncResp> aResp, 5771b82f26SSharad Yadav const std::string& service, 5871b82f26SSharad Yadav const std::string& objPath) 5971b82f26SSharad Yadav { 6071b82f26SSharad Yadav BMCWEB_LOG_DEBUG << "Get Processor UUID"; 6171b82f26SSharad Yadav crow::connections::systemBus->async_method_call( 6271b82f26SSharad Yadav [objPath, 6371b82f26SSharad Yadav aResp{std::move(aResp)}](const boost::system::error_code ec, 6471b82f26SSharad Yadav const std::variant<std::string>& property) { 6571b82f26SSharad Yadav if (ec) 6671b82f26SSharad Yadav { 6771b82f26SSharad Yadav BMCWEB_LOG_DEBUG << "DBUS response error"; 6871b82f26SSharad Yadav messages::internalError(aResp->res); 6971b82f26SSharad Yadav return; 7071b82f26SSharad Yadav } 7171b82f26SSharad Yadav const std::string* value = std::get_if<std::string>(&property); 7271b82f26SSharad Yadav if (value == nullptr) 7371b82f26SSharad Yadav { 7471b82f26SSharad Yadav BMCWEB_LOG_DEBUG << "Null value returned " 7571b82f26SSharad Yadav "for UUID"; 7671b82f26SSharad Yadav messages::internalError(aResp->res); 7771b82f26SSharad Yadav return; 7871b82f26SSharad Yadav } 7971b82f26SSharad Yadav aResp->res.jsonValue["UUID"] = *value; 8071b82f26SSharad Yadav }, 8171b82f26SSharad Yadav service, objPath, "org.freedesktop.DBus.Properties", "Get", 8271b82f26SSharad Yadav "xyz.openbmc_project.Common.UUID", "UUID"); 8371b82f26SSharad Yadav } 8471b82f26SSharad Yadav 85ac6a4445SGunnar Mills inline void 868d1b46d7Szhanghch05 getCpuDataByInterface(const std::shared_ptr<bmcweb::AsyncResp>& aResp, 87ac6a4445SGunnar Mills const InterfacesProperties& cpuInterfacesProperties) 88ac6a4445SGunnar Mills { 89ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "Get CPU resources by interface."; 90ac6a4445SGunnar Mills 91a1649ec6SChicago Duan // Set the default value of state 92a1649ec6SChicago Duan aResp->res.jsonValue["Status"]["State"] = "Enabled"; 93a1649ec6SChicago Duan aResp->res.jsonValue["Status"]["Health"] = "OK"; 94ac6a4445SGunnar Mills 95ac6a4445SGunnar Mills for (const auto& interface : cpuInterfacesProperties) 96ac6a4445SGunnar Mills { 97ac6a4445SGunnar Mills for (const auto& property : interface.second) 98ac6a4445SGunnar Mills { 99a1649ec6SChicago Duan if (property.first == "Present") 100ac6a4445SGunnar Mills { 101a1649ec6SChicago Duan const bool* cpuPresent = std::get_if<bool>(&property.second); 102a1649ec6SChicago Duan if (cpuPresent == nullptr) 103ac6a4445SGunnar Mills { 104ac6a4445SGunnar Mills // Important property not in desired type 105ac6a4445SGunnar Mills messages::internalError(aResp->res); 106ac6a4445SGunnar Mills return; 107ac6a4445SGunnar Mills } 108a1649ec6SChicago Duan if (*cpuPresent == false) 109ac6a4445SGunnar Mills { 110a1649ec6SChicago Duan // Slot is not populated 111ac6a4445SGunnar Mills aResp->res.jsonValue["Status"]["State"] = "Absent"; 112a1649ec6SChicago Duan } 113a1649ec6SChicago Duan } 114a1649ec6SChicago Duan else if (property.first == "Functional") 115a1649ec6SChicago Duan { 116a1649ec6SChicago Duan const bool* cpuFunctional = std::get_if<bool>(&property.second); 117a1649ec6SChicago Duan if (cpuFunctional == nullptr) 118a1649ec6SChicago Duan { 119a1649ec6SChicago Duan messages::internalError(aResp->res); 120ac6a4445SGunnar Mills return; 121ac6a4445SGunnar Mills } 122a1649ec6SChicago Duan if (*cpuFunctional == false) 123a1649ec6SChicago Duan { 124a1649ec6SChicago Duan aResp->res.jsonValue["Status"]["Health"] = "Critical"; 125a1649ec6SChicago Duan } 126a1649ec6SChicago Duan } 127a1649ec6SChicago Duan else if (property.first == "CoreCount") 128a1649ec6SChicago Duan { 129a1649ec6SChicago Duan const uint16_t* coresCount = 130a1649ec6SChicago Duan std::get_if<uint16_t>(&property.second); 131a1649ec6SChicago Duan if (coresCount == nullptr) 132a1649ec6SChicago Duan { 133a1649ec6SChicago Duan messages::internalError(aResp->res); 134a1649ec6SChicago Duan return; 135a1649ec6SChicago Duan } 136ac6a4445SGunnar Mills aResp->res.jsonValue["TotalCores"] = *coresCount; 137ac6a4445SGunnar Mills } 138dc3fa667SJonathan Doman else if (property.first == "MaxSpeedInMhz") 139dc3fa667SJonathan Doman { 140dc3fa667SJonathan Doman const uint32_t* value = std::get_if<uint32_t>(&property.second); 141dc3fa667SJonathan Doman if (value != nullptr) 142dc3fa667SJonathan Doman { 143dc3fa667SJonathan Doman aResp->res.jsonValue["MaxSpeedMHz"] = *value; 144dc3fa667SJonathan Doman } 145dc3fa667SJonathan Doman } 146ac6a4445SGunnar Mills else if (property.first == "Socket") 147ac6a4445SGunnar Mills { 148ac6a4445SGunnar Mills const std::string* value = 149ac6a4445SGunnar Mills std::get_if<std::string>(&property.second); 150ac6a4445SGunnar Mills if (value != nullptr) 151ac6a4445SGunnar Mills { 152ac6a4445SGunnar Mills aResp->res.jsonValue["Socket"] = *value; 153ac6a4445SGunnar Mills } 154ac6a4445SGunnar Mills } 155ac6a4445SGunnar Mills else if (property.first == "ThreadCount") 156ac6a4445SGunnar Mills { 157dc3fa667SJonathan Doman const uint16_t* value = std::get_if<uint16_t>(&property.second); 158ac6a4445SGunnar Mills if (value != nullptr) 159ac6a4445SGunnar Mills { 160ac6a4445SGunnar Mills aResp->res.jsonValue["TotalThreads"] = *value; 161ac6a4445SGunnar Mills } 162ac6a4445SGunnar Mills } 163*1930fbd4SBrandon Kim else if (property.first == "EffectiveFamily") 164ac6a4445SGunnar Mills { 165*1930fbd4SBrandon Kim const uint16_t* value = std::get_if<uint16_t>(&property.second); 166ac6a4445SGunnar Mills if (value != nullptr) 167ac6a4445SGunnar Mills { 168ac6a4445SGunnar Mills aResp->res.jsonValue["ProcessorId"]["EffectiveFamily"] = 169*1930fbd4SBrandon Kim "0x" + intToHexString(*value); 170ac6a4445SGunnar Mills } 171ac6a4445SGunnar Mills } 172*1930fbd4SBrandon Kim else if (property.first == "EffectiveModel") 173*1930fbd4SBrandon Kim { 174*1930fbd4SBrandon Kim const uint16_t* value = std::get_if<uint16_t>(&property.second); 175*1930fbd4SBrandon Kim if (value == nullptr) 176*1930fbd4SBrandon Kim { 177*1930fbd4SBrandon Kim messages::internalError(aResp->res); 178*1930fbd4SBrandon Kim return; 179*1930fbd4SBrandon Kim } 180*1930fbd4SBrandon Kim aResp->res.jsonValue["ProcessorId"]["EffectiveModel"] = 181*1930fbd4SBrandon Kim "0x" + intToHexString(*value); 182*1930fbd4SBrandon Kim } 183ac6a4445SGunnar Mills else if (property.first == "Id") 184ac6a4445SGunnar Mills { 185ac6a4445SGunnar Mills const uint64_t* value = std::get_if<uint64_t>(&property.second); 186ac6a4445SGunnar Mills if (value != nullptr && *value != 0) 187ac6a4445SGunnar Mills { 188ac6a4445SGunnar Mills aResp->res 189ac6a4445SGunnar Mills .jsonValue["ProcessorId"]["IdentificationRegisters"] = 190f201ffb4SEd Tanous "0x" + intToHexString(*value); 191ac6a4445SGunnar Mills } 192ac6a4445SGunnar Mills } 193*1930fbd4SBrandon Kim else if (property.first == "Microcode") 194*1930fbd4SBrandon Kim { 195*1930fbd4SBrandon Kim const uint32_t* value = std::get_if<uint32_t>(&property.second); 196*1930fbd4SBrandon Kim if (value == nullptr) 197*1930fbd4SBrandon Kim { 198*1930fbd4SBrandon Kim messages::internalError(aResp->res); 199*1930fbd4SBrandon Kim return; 200*1930fbd4SBrandon Kim } 201*1930fbd4SBrandon Kim aResp->res.jsonValue["ProcessorId"]["MicrocodeInfo"] = 202*1930fbd4SBrandon Kim "0x" + intToHexString(*value); 203*1930fbd4SBrandon Kim } 204*1930fbd4SBrandon Kim else if (property.first == "Step") 205*1930fbd4SBrandon Kim { 206*1930fbd4SBrandon Kim const uint16_t* value = std::get_if<uint16_t>(&property.second); 207*1930fbd4SBrandon Kim if (value == nullptr) 208*1930fbd4SBrandon Kim { 209*1930fbd4SBrandon Kim messages::internalError(aResp->res); 210*1930fbd4SBrandon Kim return; 211*1930fbd4SBrandon Kim } 212*1930fbd4SBrandon Kim aResp->res.jsonValue["ProcessorId"]["Step"] = 213*1930fbd4SBrandon Kim "0x" + intToHexString(*value); 214*1930fbd4SBrandon Kim } 215ac6a4445SGunnar Mills } 216ac6a4445SGunnar Mills } 217ac6a4445SGunnar Mills 218ac6a4445SGunnar Mills return; 219ac6a4445SGunnar Mills } 220ac6a4445SGunnar Mills 2218d1b46d7Szhanghch05 inline void getCpuDataByService(std::shared_ptr<bmcweb::AsyncResp> aResp, 222ac6a4445SGunnar Mills const std::string& cpuId, 223ac6a4445SGunnar Mills const std::string& service, 224ac6a4445SGunnar Mills const std::string& objPath) 225ac6a4445SGunnar Mills { 226ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "Get available system cpu resources by service."; 227ac6a4445SGunnar Mills 228ac6a4445SGunnar Mills crow::connections::systemBus->async_method_call( 229ac6a4445SGunnar Mills [cpuId, service, objPath, aResp{std::move(aResp)}]( 230ac6a4445SGunnar Mills const boost::system::error_code ec, 231ac6a4445SGunnar Mills const dbus::utility::ManagedObjectType& dbusData) { 232ac6a4445SGunnar Mills if (ec) 233ac6a4445SGunnar Mills { 234ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "DBUS response error"; 235ac6a4445SGunnar Mills messages::internalError(aResp->res); 236ac6a4445SGunnar Mills return; 237ac6a4445SGunnar Mills } 238ac6a4445SGunnar Mills aResp->res.jsonValue["Id"] = cpuId; 239ac6a4445SGunnar Mills aResp->res.jsonValue["Name"] = "Processor"; 240ac6a4445SGunnar Mills aResp->res.jsonValue["ProcessorType"] = "CPU"; 241ac6a4445SGunnar Mills 242ac6a4445SGunnar Mills bool slotPresent = false; 243ac6a4445SGunnar Mills std::string corePath = objPath + "/core"; 244ac6a4445SGunnar Mills size_t totalCores = 0; 245ac6a4445SGunnar Mills for (const auto& object : dbusData) 246ac6a4445SGunnar Mills { 247ac6a4445SGunnar Mills if (object.first.str == objPath) 248ac6a4445SGunnar Mills { 249ac6a4445SGunnar Mills getCpuDataByInterface(aResp, object.second); 250ac6a4445SGunnar Mills } 251ac6a4445SGunnar Mills else if (boost::starts_with(object.first.str, corePath)) 252ac6a4445SGunnar Mills { 253ac6a4445SGunnar Mills for (const auto& interface : object.second) 254ac6a4445SGunnar Mills { 255ac6a4445SGunnar Mills if (interface.first == 256ac6a4445SGunnar Mills "xyz.openbmc_project.Inventory.Item") 257ac6a4445SGunnar Mills { 258ac6a4445SGunnar Mills for (const auto& property : interface.second) 259ac6a4445SGunnar Mills { 260ac6a4445SGunnar Mills if (property.first == "Present") 261ac6a4445SGunnar Mills { 262ac6a4445SGunnar Mills const bool* present = 263ac6a4445SGunnar Mills std::get_if<bool>(&property.second); 264ac6a4445SGunnar Mills if (present != nullptr) 265ac6a4445SGunnar Mills { 266ac6a4445SGunnar Mills if (*present == true) 267ac6a4445SGunnar Mills { 268ac6a4445SGunnar Mills slotPresent = true; 269ac6a4445SGunnar Mills totalCores++; 270ac6a4445SGunnar Mills } 271ac6a4445SGunnar Mills } 272ac6a4445SGunnar Mills } 273ac6a4445SGunnar Mills } 274ac6a4445SGunnar Mills } 275ac6a4445SGunnar Mills } 276ac6a4445SGunnar Mills } 277ac6a4445SGunnar Mills } 278ac6a4445SGunnar Mills // In getCpuDataByInterface(), state and health are set 279ac6a4445SGunnar Mills // based on the present and functional status. If core 280ac6a4445SGunnar Mills // count is zero, then it has a higher precedence. 281ac6a4445SGunnar Mills if (slotPresent) 282ac6a4445SGunnar Mills { 283ac6a4445SGunnar Mills if (totalCores == 0) 284ac6a4445SGunnar Mills { 285ac6a4445SGunnar Mills // Slot is not populated, set status end return 286ac6a4445SGunnar Mills aResp->res.jsonValue["Status"]["State"] = "Absent"; 287ac6a4445SGunnar Mills aResp->res.jsonValue["Status"]["Health"] = "OK"; 288ac6a4445SGunnar Mills } 289ac6a4445SGunnar Mills aResp->res.jsonValue["TotalCores"] = totalCores; 290ac6a4445SGunnar Mills } 291ac6a4445SGunnar Mills return; 292ac6a4445SGunnar Mills }, 293ac6a4445SGunnar Mills service, "/xyz/openbmc_project/inventory", 294ac6a4445SGunnar Mills "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 295ac6a4445SGunnar Mills } 296ac6a4445SGunnar Mills 2978d1b46d7Szhanghch05 inline void getCpuAssetData(std::shared_ptr<bmcweb::AsyncResp> aResp, 298ac6a4445SGunnar Mills const std::string& service, 299ac6a4445SGunnar Mills const std::string& objPath) 300ac6a4445SGunnar Mills { 301ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "Get Cpu Asset Data"; 302ac6a4445SGunnar Mills crow::connections::systemBus->async_method_call( 303ac6a4445SGunnar Mills [objPath, aResp{std::move(aResp)}]( 304ac6a4445SGunnar Mills const boost::system::error_code ec, 305ac6a4445SGunnar Mills const boost::container::flat_map< 306ac6a4445SGunnar Mills std::string, std::variant<std::string, uint32_t, uint16_t, 307ac6a4445SGunnar Mills bool>>& properties) { 308ac6a4445SGunnar Mills if (ec) 309ac6a4445SGunnar Mills { 310ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "DBUS response error"; 311ac6a4445SGunnar Mills messages::internalError(aResp->res); 312ac6a4445SGunnar Mills return; 313ac6a4445SGunnar Mills } 314ac6a4445SGunnar Mills 315ac6a4445SGunnar Mills for (const auto& property : properties) 316ac6a4445SGunnar Mills { 317ac6a4445SGunnar Mills if (property.first == "SerialNumber") 318ac6a4445SGunnar Mills { 319ac6a4445SGunnar Mills const std::string* sn = 320ac6a4445SGunnar Mills std::get_if<std::string>(&property.second); 321ac6a4445SGunnar Mills if (sn != nullptr && !sn->empty()) 322ac6a4445SGunnar Mills { 323ac6a4445SGunnar Mills aResp->res.jsonValue["SerialNumber"] = *sn; 324ac6a4445SGunnar Mills } 325ac6a4445SGunnar Mills } 326ac6a4445SGunnar Mills else if (property.first == "Model") 327ac6a4445SGunnar Mills { 328ac6a4445SGunnar Mills const std::string* model = 329ac6a4445SGunnar Mills std::get_if<std::string>(&property.second); 330ac6a4445SGunnar Mills if (model != nullptr && !model->empty()) 331ac6a4445SGunnar Mills { 332ac6a4445SGunnar Mills aResp->res.jsonValue["Model"] = *model; 333ac6a4445SGunnar Mills } 334ac6a4445SGunnar Mills } 335ac6a4445SGunnar Mills else if (property.first == "Manufacturer") 336ac6a4445SGunnar Mills { 337ac6a4445SGunnar Mills 338ac6a4445SGunnar Mills const std::string* mfg = 339ac6a4445SGunnar Mills std::get_if<std::string>(&property.second); 340ac6a4445SGunnar Mills if (mfg != nullptr) 341ac6a4445SGunnar Mills { 342ac6a4445SGunnar Mills aResp->res.jsonValue["Manufacturer"] = *mfg; 343ac6a4445SGunnar Mills 344ac6a4445SGunnar Mills // Otherwise would be unexpected. 345ac6a4445SGunnar Mills if (mfg->find("Intel") != std::string::npos) 346ac6a4445SGunnar Mills { 347ac6a4445SGunnar Mills aResp->res.jsonValue["ProcessorArchitecture"] = 348ac6a4445SGunnar Mills "x86"; 349ac6a4445SGunnar Mills aResp->res.jsonValue["InstructionSet"] = "x86-64"; 350ac6a4445SGunnar Mills } 351ac6a4445SGunnar Mills else if (mfg->find("IBM") != std::string::npos) 352ac6a4445SGunnar Mills { 353ac6a4445SGunnar Mills aResp->res.jsonValue["ProcessorArchitecture"] = 354ac6a4445SGunnar Mills "Power"; 355ac6a4445SGunnar Mills aResp->res.jsonValue["InstructionSet"] = "PowerISA"; 356ac6a4445SGunnar Mills } 357ac6a4445SGunnar Mills } 358ac6a4445SGunnar Mills } 359cba4f448SSunnySrivastava1984 else if (property.first == "PartNumber") 360cba4f448SSunnySrivastava1984 { 361cba4f448SSunnySrivastava1984 const std::string* partNumber = 362cba4f448SSunnySrivastava1984 std::get_if<std::string>(&property.second); 363cba4f448SSunnySrivastava1984 364cba4f448SSunnySrivastava1984 if (partNumber == nullptr) 365cba4f448SSunnySrivastava1984 { 366cba4f448SSunnySrivastava1984 messages::internalError(aResp->res); 367cba4f448SSunnySrivastava1984 return; 368cba4f448SSunnySrivastava1984 } 369cba4f448SSunnySrivastava1984 aResp->res.jsonValue["PartNumber"] = *partNumber; 370cba4f448SSunnySrivastava1984 } 371cba4f448SSunnySrivastava1984 else if (property.first == "SparePartNumber") 372cba4f448SSunnySrivastava1984 { 373cba4f448SSunnySrivastava1984 const std::string* sparePartNumber = 374cba4f448SSunnySrivastava1984 std::get_if<std::string>(&property.second); 375cba4f448SSunnySrivastava1984 376cba4f448SSunnySrivastava1984 if (sparePartNumber == nullptr) 377cba4f448SSunnySrivastava1984 { 378cba4f448SSunnySrivastava1984 messages::internalError(aResp->res); 379cba4f448SSunnySrivastava1984 return; 380cba4f448SSunnySrivastava1984 } 381cba4f448SSunnySrivastava1984 aResp->res.jsonValue["SparePartNumber"] = *sparePartNumber; 382cba4f448SSunnySrivastava1984 } 383ac6a4445SGunnar Mills } 384ac6a4445SGunnar Mills }, 385ac6a4445SGunnar Mills service, objPath, "org.freedesktop.DBus.Properties", "GetAll", 386ac6a4445SGunnar Mills "xyz.openbmc_project.Inventory.Decorator.Asset"); 387ac6a4445SGunnar Mills } 388ac6a4445SGunnar Mills 3898d1b46d7Szhanghch05 inline void getCpuRevisionData(std::shared_ptr<bmcweb::AsyncResp> aResp, 390ac6a4445SGunnar Mills const std::string& service, 391ac6a4445SGunnar Mills const std::string& objPath) 392ac6a4445SGunnar Mills { 393ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "Get Cpu Revision Data"; 394ac6a4445SGunnar Mills crow::connections::systemBus->async_method_call( 395ac6a4445SGunnar Mills [objPath, aResp{std::move(aResp)}]( 396ac6a4445SGunnar Mills const boost::system::error_code ec, 397ac6a4445SGunnar Mills const boost::container::flat_map< 398ac6a4445SGunnar Mills std::string, std::variant<std::string, uint32_t, uint16_t, 399ac6a4445SGunnar Mills bool>>& properties) { 400ac6a4445SGunnar Mills if (ec) 401ac6a4445SGunnar Mills { 402ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "DBUS response error"; 403ac6a4445SGunnar Mills messages::internalError(aResp->res); 404ac6a4445SGunnar Mills return; 405ac6a4445SGunnar Mills } 406ac6a4445SGunnar Mills 407ac6a4445SGunnar Mills for (const auto& property : properties) 408ac6a4445SGunnar Mills { 409ac6a4445SGunnar Mills if (property.first == "Version") 410ac6a4445SGunnar Mills { 411ac6a4445SGunnar Mills const std::string* ver = 412ac6a4445SGunnar Mills std::get_if<std::string>(&property.second); 413ac6a4445SGunnar Mills if (ver != nullptr) 414ac6a4445SGunnar Mills { 415ac6a4445SGunnar Mills aResp->res.jsonValue["Version"] = *ver; 416ac6a4445SGunnar Mills } 417ac6a4445SGunnar Mills break; 418ac6a4445SGunnar Mills } 419ac6a4445SGunnar Mills } 420ac6a4445SGunnar Mills }, 421ac6a4445SGunnar Mills service, objPath, "org.freedesktop.DBus.Properties", "GetAll", 422ac6a4445SGunnar Mills "xyz.openbmc_project.Inventory.Decorator.Revision"); 423ac6a4445SGunnar Mills } 424ac6a4445SGunnar Mills 4258d1b46d7Szhanghch05 inline void getAcceleratorDataByService( 4268d1b46d7Szhanghch05 std::shared_ptr<bmcweb::AsyncResp> aResp, const std::string& acclrtrId, 4278d1b46d7Szhanghch05 const std::string& service, const std::string& objPath) 428ac6a4445SGunnar Mills { 429ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG 430ac6a4445SGunnar Mills << "Get available system Accelerator resources by service."; 431ac6a4445SGunnar Mills crow::connections::systemBus->async_method_call( 432ac6a4445SGunnar Mills [acclrtrId, aResp{std::move(aResp)}]( 433ac6a4445SGunnar Mills const boost::system::error_code ec, 434ac6a4445SGunnar Mills const boost::container::flat_map< 435ac6a4445SGunnar Mills std::string, std::variant<std::string, uint32_t, uint16_t, 436ac6a4445SGunnar Mills bool>>& properties) { 437ac6a4445SGunnar Mills if (ec) 438ac6a4445SGunnar Mills { 439ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "DBUS response error"; 440ac6a4445SGunnar Mills messages::internalError(aResp->res); 441ac6a4445SGunnar Mills return; 442ac6a4445SGunnar Mills } 443ac6a4445SGunnar Mills aResp->res.jsonValue["Id"] = acclrtrId; 444ac6a4445SGunnar Mills aResp->res.jsonValue["Name"] = "Processor"; 445ac6a4445SGunnar Mills const bool* accPresent = nullptr; 446ac6a4445SGunnar Mills const bool* accFunctional = nullptr; 447ac6a4445SGunnar Mills 448ac6a4445SGunnar Mills for (const auto& property : properties) 449ac6a4445SGunnar Mills { 450ac6a4445SGunnar Mills if (property.first == "Functional") 451ac6a4445SGunnar Mills { 452ac6a4445SGunnar Mills accFunctional = std::get_if<bool>(&property.second); 453ac6a4445SGunnar Mills } 454ac6a4445SGunnar Mills else if (property.first == "Present") 455ac6a4445SGunnar Mills { 456ac6a4445SGunnar Mills accPresent = std::get_if<bool>(&property.second); 457ac6a4445SGunnar Mills } 458ac6a4445SGunnar Mills } 459ac6a4445SGunnar Mills 460ac6a4445SGunnar Mills std::string state = "Enabled"; 461ac6a4445SGunnar Mills std::string health = "OK"; 462ac6a4445SGunnar Mills 463ac6a4445SGunnar Mills if (accPresent != nullptr && *accPresent == false) 464ac6a4445SGunnar Mills { 465ac6a4445SGunnar Mills state = "Absent"; 466ac6a4445SGunnar Mills } 467ac6a4445SGunnar Mills 468ac6a4445SGunnar Mills if ((accFunctional != nullptr) && (*accFunctional == false)) 469ac6a4445SGunnar Mills { 470ac6a4445SGunnar Mills if (state == "Enabled") 471ac6a4445SGunnar Mills { 472ac6a4445SGunnar Mills health = "Critical"; 473ac6a4445SGunnar Mills } 474ac6a4445SGunnar Mills } 475ac6a4445SGunnar Mills 476ac6a4445SGunnar Mills aResp->res.jsonValue["Status"]["State"] = state; 477ac6a4445SGunnar Mills aResp->res.jsonValue["Status"]["Health"] = health; 478ac6a4445SGunnar Mills aResp->res.jsonValue["ProcessorType"] = "Accelerator"; 479ac6a4445SGunnar Mills }, 480ac6a4445SGunnar Mills service, objPath, "org.freedesktop.DBus.Properties", "GetAll", ""); 481ac6a4445SGunnar Mills } 482ac6a4445SGunnar Mills 483dba0c291SJonathan Doman // OperatingConfig D-Bus Types 484dba0c291SJonathan Doman using TurboProfileProperty = std::vector<std::tuple<uint32_t, size_t>>; 485dba0c291SJonathan Doman using BaseSpeedPrioritySettingsProperty = 486dba0c291SJonathan Doman std::vector<std::tuple<uint32_t, std::vector<uint32_t>>>; 487dba0c291SJonathan Doman // uint32_t and size_t may or may not be the same type, requiring a dedup'd 488dba0c291SJonathan Doman // variant 489dba0c291SJonathan Doman using OperatingConfigProperties = std::vector<std::pair< 490dba0c291SJonathan Doman std::string, 4914f9637faSPatrick Williams sdbusplus::utility::dedup_variant_t<uint32_t, size_t, TurboProfileProperty, 492dba0c291SJonathan Doman BaseSpeedPrioritySettingsProperty>>>; 493dba0c291SJonathan Doman 494dba0c291SJonathan Doman /** 495dba0c291SJonathan Doman * Fill out the HighSpeedCoreIDs in a Processor resource from the given 496dba0c291SJonathan Doman * OperatingConfig D-Bus property. 497dba0c291SJonathan Doman * 498dba0c291SJonathan Doman * @param[in,out] aResp Async HTTP response. 499dba0c291SJonathan Doman * @param[in] baseSpeedSettings Full list of base speed priority groups, 500dba0c291SJonathan Doman * to use to determine the list of high 501dba0c291SJonathan Doman * speed cores. 502dba0c291SJonathan Doman */ 503dba0c291SJonathan Doman inline void highSpeedCoreIdsHandler( 5048d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& aResp, 505dba0c291SJonathan Doman const BaseSpeedPrioritySettingsProperty& baseSpeedSettings) 506dba0c291SJonathan Doman { 507dba0c291SJonathan Doman // The D-Bus property does not indicate which bucket is the "high 508dba0c291SJonathan Doman // priority" group, so let's discern that by looking for the one with 509dba0c291SJonathan Doman // highest base frequency. 510dba0c291SJonathan Doman auto highPriorityGroup = baseSpeedSettings.cend(); 511dba0c291SJonathan Doman uint32_t highestBaseSpeed = 0; 512dba0c291SJonathan Doman for (auto it = baseSpeedSettings.cbegin(); it != baseSpeedSettings.cend(); 513dba0c291SJonathan Doman ++it) 514dba0c291SJonathan Doman { 515dba0c291SJonathan Doman const uint32_t baseFreq = std::get<uint32_t>(*it); 516dba0c291SJonathan Doman if (baseFreq > highestBaseSpeed) 517dba0c291SJonathan Doman { 518dba0c291SJonathan Doman highestBaseSpeed = baseFreq; 519dba0c291SJonathan Doman highPriorityGroup = it; 520dba0c291SJonathan Doman } 521dba0c291SJonathan Doman } 522dba0c291SJonathan Doman 523dba0c291SJonathan Doman nlohmann::json& jsonCoreIds = aResp->res.jsonValue["HighSpeedCoreIDs"]; 524dba0c291SJonathan Doman jsonCoreIds = nlohmann::json::array(); 525dba0c291SJonathan Doman 526dba0c291SJonathan Doman // There may not be any entries in the D-Bus property, so only populate 527dba0c291SJonathan Doman // if there was actually something there. 528dba0c291SJonathan Doman if (highPriorityGroup != baseSpeedSettings.cend()) 529dba0c291SJonathan Doman { 530dba0c291SJonathan Doman jsonCoreIds = std::get<std::vector<uint32_t>>(*highPriorityGroup); 531dba0c291SJonathan Doman } 532dba0c291SJonathan Doman } 533dba0c291SJonathan Doman 534dba0c291SJonathan Doman /** 535dba0c291SJonathan Doman * Fill out OperatingConfig related items in a Processor resource by requesting 536dba0c291SJonathan Doman * data from the given D-Bus object. 537dba0c291SJonathan Doman * 538dba0c291SJonathan Doman * @param[in,out] aResp Async HTTP response. 539dba0c291SJonathan Doman * @param[in] cpuId CPU D-Bus name. 540dba0c291SJonathan Doman * @param[in] service D-Bus service to query. 541dba0c291SJonathan Doman * @param[in] objPath D-Bus object to query. 542dba0c291SJonathan Doman */ 5438d1b46d7Szhanghch05 inline void getCpuConfigData(const std::shared_ptr<bmcweb::AsyncResp>& aResp, 544dba0c291SJonathan Doman const std::string& cpuId, 545dba0c291SJonathan Doman const std::string& service, 546dba0c291SJonathan Doman const std::string& objPath) 547dba0c291SJonathan Doman { 548dba0c291SJonathan Doman BMCWEB_LOG_INFO << "Getting CPU operating configs for " << cpuId; 549dba0c291SJonathan Doman 550dba0c291SJonathan Doman // First, GetAll CurrentOperatingConfig properties on the object 551dba0c291SJonathan Doman crow::connections::systemBus->async_method_call( 552dba0c291SJonathan Doman [aResp, cpuId, service]( 553dba0c291SJonathan Doman const boost::system::error_code ec, 554dba0c291SJonathan Doman const std::vector< 555dba0c291SJonathan Doman std::pair<std::string, 556dba0c291SJonathan Doman std::variant<sdbusplus::message::object_path, bool>>>& 557dba0c291SJonathan Doman properties) { 558dba0c291SJonathan Doman if (ec) 559dba0c291SJonathan Doman { 560dba0c291SJonathan Doman BMCWEB_LOG_WARNING << "D-Bus error: " << ec << ", " 561dba0c291SJonathan Doman << ec.message(); 562dba0c291SJonathan Doman messages::internalError(aResp->res); 563dba0c291SJonathan Doman return; 564dba0c291SJonathan Doman } 565dba0c291SJonathan Doman 566dba0c291SJonathan Doman nlohmann::json& json = aResp->res.jsonValue; 567dba0c291SJonathan Doman 568dba0c291SJonathan Doman for (const auto& [dbusPropName, variantVal] : properties) 569dba0c291SJonathan Doman { 570dba0c291SJonathan Doman if (dbusPropName == "AppliedConfig") 571dba0c291SJonathan Doman { 572dba0c291SJonathan Doman const sdbusplus::message::object_path* dbusPathWrapper = 573dba0c291SJonathan Doman std::get_if<sdbusplus::message::object_path>( 574dba0c291SJonathan Doman &variantVal); 575dba0c291SJonathan Doman if (dbusPathWrapper == nullptr) 576dba0c291SJonathan Doman { 577dba0c291SJonathan Doman continue; 578dba0c291SJonathan Doman } 579dba0c291SJonathan Doman 580dba0c291SJonathan Doman const std::string& dbusPath = dbusPathWrapper->str; 581dba0c291SJonathan Doman std::string uri = "/redfish/v1/Systems/system/Processors/" + 582dba0c291SJonathan Doman cpuId + "/OperatingConfigs"; 583dba0c291SJonathan Doman json["OperatingConfigs"] = {{"@odata.id", uri}}; 584dba0c291SJonathan Doman 585dba0c291SJonathan Doman // Reuse the D-Bus config object name for the Redfish 586dba0c291SJonathan Doman // URI 587dba0c291SJonathan Doman size_t baseNamePos = dbusPath.rfind('/'); 588dba0c291SJonathan Doman if (baseNamePos == std::string::npos || 589dba0c291SJonathan Doman baseNamePos == (dbusPath.size() - 1)) 590dba0c291SJonathan Doman { 591dba0c291SJonathan Doman // If the AppliedConfig was somehow not a valid path, 592dba0c291SJonathan Doman // skip adding any more properties, since everything 593dba0c291SJonathan Doman // else is tied to this applied config. 594dba0c291SJonathan Doman messages::internalError(aResp->res); 595dba0c291SJonathan Doman break; 596dba0c291SJonathan Doman } 597dba0c291SJonathan Doman uri += '/'; 598dba0c291SJonathan Doman uri += dbusPath.substr(baseNamePos + 1); 599dba0c291SJonathan Doman json["AppliedOperatingConfig"] = {{"@odata.id", uri}}; 600dba0c291SJonathan Doman 601dba0c291SJonathan Doman // Once we found the current applied config, queue another 602dba0c291SJonathan Doman // request to read the base freq core ids out of that 603dba0c291SJonathan Doman // config. 604dba0c291SJonathan Doman crow::connections::systemBus->async_method_call( 605dba0c291SJonathan Doman [aResp]( 606dba0c291SJonathan Doman const boost::system::error_code ec, 607dba0c291SJonathan Doman const std::variant< 608dba0c291SJonathan Doman BaseSpeedPrioritySettingsProperty>& property) { 609dba0c291SJonathan Doman if (ec) 610dba0c291SJonathan Doman { 611dba0c291SJonathan Doman BMCWEB_LOG_WARNING 612dba0c291SJonathan Doman << "D-Bus Property Get error: " << ec; 613dba0c291SJonathan Doman messages::internalError(aResp->res); 614dba0c291SJonathan Doman return; 615dba0c291SJonathan Doman } 616dba0c291SJonathan Doman auto baseSpeedList = 617dba0c291SJonathan Doman std::get_if<BaseSpeedPrioritySettingsProperty>( 618dba0c291SJonathan Doman &property); 619dba0c291SJonathan Doman if (baseSpeedList != nullptr) 620dba0c291SJonathan Doman { 621dba0c291SJonathan Doman highSpeedCoreIdsHandler(aResp, *baseSpeedList); 622dba0c291SJonathan Doman } 623dba0c291SJonathan Doman }, 624dba0c291SJonathan Doman service, dbusPath, "org.freedesktop.DBus.Properties", 625dba0c291SJonathan Doman "Get", 6260fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig", 627dba0c291SJonathan Doman "BaseSpeedPrioritySettings"); 628dba0c291SJonathan Doman } 629dba0c291SJonathan Doman else if (dbusPropName == "BaseSpeedPriorityEnabled") 630dba0c291SJonathan Doman { 631dba0c291SJonathan Doman const bool* state = std::get_if<bool>(&variantVal); 632dba0c291SJonathan Doman if (state != nullptr) 633dba0c291SJonathan Doman { 634dba0c291SJonathan Doman json["BaseSpeedPriorityState"] = 635dba0c291SJonathan Doman *state ? "Enabled" : "Disabled"; 636dba0c291SJonathan Doman } 637dba0c291SJonathan Doman } 638dba0c291SJonathan Doman } 639dba0c291SJonathan Doman }, 640dba0c291SJonathan Doman service, objPath, "org.freedesktop.DBus.Properties", "GetAll", 641dba0c291SJonathan Doman "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig"); 642dba0c291SJonathan Doman } 643dba0c291SJonathan Doman 644cba4f448SSunnySrivastava1984 /** 645cba4f448SSunnySrivastava1984 * @brief Fill out location info of a processor by 646cba4f448SSunnySrivastava1984 * requesting data from the given D-Bus object. 647cba4f448SSunnySrivastava1984 * 648cba4f448SSunnySrivastava1984 * @param[in,out] aResp Async HTTP response. 649cba4f448SSunnySrivastava1984 * @param[in] service D-Bus service to query. 650cba4f448SSunnySrivastava1984 * @param[in] objPath D-Bus object to query. 651cba4f448SSunnySrivastava1984 */ 6528d1b46d7Szhanghch05 inline void getCpuLocationCode(std::shared_ptr<bmcweb::AsyncResp> aResp, 653cba4f448SSunnySrivastava1984 const std::string& service, 654cba4f448SSunnySrivastava1984 const std::string& objPath) 655cba4f448SSunnySrivastava1984 { 656cba4f448SSunnySrivastava1984 BMCWEB_LOG_DEBUG << "Get Cpu Location Data"; 657cba4f448SSunnySrivastava1984 crow::connections::systemBus->async_method_call( 658cba4f448SSunnySrivastava1984 [objPath, 659cba4f448SSunnySrivastava1984 aResp{std::move(aResp)}](const boost::system::error_code ec, 660cba4f448SSunnySrivastava1984 const std::variant<std::string>& property) { 661cba4f448SSunnySrivastava1984 if (ec) 662cba4f448SSunnySrivastava1984 { 663cba4f448SSunnySrivastava1984 BMCWEB_LOG_DEBUG << "DBUS response error"; 664cba4f448SSunnySrivastava1984 messages::internalError(aResp->res); 665cba4f448SSunnySrivastava1984 return; 666cba4f448SSunnySrivastava1984 } 667cba4f448SSunnySrivastava1984 668cba4f448SSunnySrivastava1984 const std::string* value = std::get_if<std::string>(&property); 669cba4f448SSunnySrivastava1984 670cba4f448SSunnySrivastava1984 if (value == nullptr) 671cba4f448SSunnySrivastava1984 { 672cba4f448SSunnySrivastava1984 // illegal value 673cba4f448SSunnySrivastava1984 BMCWEB_LOG_DEBUG << "Location code value error"; 674cba4f448SSunnySrivastava1984 messages::internalError(aResp->res); 675cba4f448SSunnySrivastava1984 return; 676cba4f448SSunnySrivastava1984 } 677cba4f448SSunnySrivastava1984 678cba4f448SSunnySrivastava1984 aResp->res.jsonValue["Location"]["PartLocation"]["ServiceLabel"] = 679cba4f448SSunnySrivastava1984 *value; 680cba4f448SSunnySrivastava1984 }, 681cba4f448SSunnySrivastava1984 service, objPath, "org.freedesktop.DBus.Properties", "Get", 682cba4f448SSunnySrivastava1984 "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode"); 683cba4f448SSunnySrivastava1984 } 684cba4f448SSunnySrivastava1984 685c951448aSJonathan Doman /** 68649e429caSJonathan Doman * Populate the unique identifier in a Processor resource by requesting data 68749e429caSJonathan Doman * from the given D-Bus object. 68849e429caSJonathan Doman * 68949e429caSJonathan Doman * @param[in,out] aResp Async HTTP response. 69049e429caSJonathan Doman * @param[in] service D-Bus service to query. 69149e429caSJonathan Doman * @param[in] objPath D-Bus object to query. 69249e429caSJonathan Doman */ 69349e429caSJonathan Doman inline void getCpuUniqueId(const std::shared_ptr<bmcweb::AsyncResp>& aResp, 69449e429caSJonathan Doman const std::string& service, 69549e429caSJonathan Doman const std::string& objectPath) 69649e429caSJonathan Doman { 69749e429caSJonathan Doman BMCWEB_LOG_DEBUG << "Get CPU UniqueIdentifier"; 69849e429caSJonathan Doman crow::connections::systemBus->async_method_call( 69949e429caSJonathan Doman [aResp](boost::system::error_code ec, 70049e429caSJonathan Doman const std::variant<std::string>& property) { 70149e429caSJonathan Doman const std::string* id = std::get_if<std::string>(&property); 70249e429caSJonathan Doman if (ec || id == nullptr) 70349e429caSJonathan Doman { 70449e429caSJonathan Doman BMCWEB_LOG_ERROR << "Failed to read cpu unique id: " << ec; 70549e429caSJonathan Doman messages::internalError(aResp->res); 70649e429caSJonathan Doman return; 70749e429caSJonathan Doman } 70849e429caSJonathan Doman aResp->res 70949e429caSJonathan Doman .jsonValue["ProcessorId"]["ProtectedIdentificationNumber"] = 71049e429caSJonathan Doman *id; 71149e429caSJonathan Doman }, 71249e429caSJonathan Doman service, objectPath, "org.freedesktop.DBus.Properties", "Get", 71349e429caSJonathan Doman "xyz.openbmc_project.Inventory.Decorator.UniqueIdentifier", 71449e429caSJonathan Doman "UniqueIdentifier"); 71549e429caSJonathan Doman } 71649e429caSJonathan Doman 71749e429caSJonathan Doman /** 718c951448aSJonathan Doman * Find the D-Bus object representing the requested Processor, and call the 719c951448aSJonathan Doman * handler with the results. If matching object is not found, add 404 error to 720c951448aSJonathan Doman * response and don't call the handler. 721c951448aSJonathan Doman * 722c951448aSJonathan Doman * @param[in,out] resp Async HTTP response. 723c951448aSJonathan Doman * @param[in] processorId Redfish Processor Id. 724c951448aSJonathan Doman * @param[in] handler Callback to continue processing request upon 725c951448aSJonathan Doman * successfully finding object. 726c951448aSJonathan Doman */ 727c951448aSJonathan Doman template <typename Handler> 7288d1b46d7Szhanghch05 inline void getProcessorObject(const std::shared_ptr<bmcweb::AsyncResp>& resp, 729c951448aSJonathan Doman const std::string& processorId, 730c951448aSJonathan Doman Handler&& handler) 731ac6a4445SGunnar Mills { 732ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "Get available system processor resources."; 733ac6a4445SGunnar Mills 734c951448aSJonathan Doman // GetSubTree on all interfaces which provide info about a Processor 735ac6a4445SGunnar Mills crow::connections::systemBus->async_method_call( 736c951448aSJonathan Doman [resp, processorId, handler = std::forward<Handler>(handler)]( 737c951448aSJonathan Doman boost::system::error_code ec, 738c951448aSJonathan Doman const MapperGetSubTreeResponse& subtree) mutable { 739ac6a4445SGunnar Mills if (ec) 740ac6a4445SGunnar Mills { 741c951448aSJonathan Doman BMCWEB_LOG_DEBUG << "DBUS response error: " << ec; 742c951448aSJonathan Doman messages::internalError(resp->res); 743ac6a4445SGunnar Mills return; 744ac6a4445SGunnar Mills } 7452bab9831SJonathan Doman for (const auto& [objectPath, serviceMap] : subtree) 746ac6a4445SGunnar Mills { 7472bab9831SJonathan Doman // Ignore any objects which don't end with our desired cpu name 7482bab9831SJonathan Doman if (!boost::ends_with(objectPath, processorId)) 749ac6a4445SGunnar Mills { 7502bab9831SJonathan Doman continue; 751ac6a4445SGunnar Mills } 7522bab9831SJonathan Doman 753c951448aSJonathan Doman bool found = false; 754c951448aSJonathan Doman // Filter out objects that don't have the CPU-specific 755c951448aSJonathan Doman // interfaces to make sure we can return 404 on non-CPUs 756c951448aSJonathan Doman // (e.g. /redfish/../Processors/dimm0) 7572bab9831SJonathan Doman for (const auto& [serviceName, interfaceList] : serviceMap) 758ac6a4445SGunnar Mills { 759c951448aSJonathan Doman if (std::find_first_of( 760c951448aSJonathan Doman interfaceList.begin(), interfaceList.end(), 761c951448aSJonathan Doman processorInterfaces.begin(), 762c951448aSJonathan Doman processorInterfaces.end()) != interfaceList.end()) 7632bab9831SJonathan Doman { 764c951448aSJonathan Doman found = true; 765c951448aSJonathan Doman break; 766c951448aSJonathan Doman } 767c951448aSJonathan Doman } 768c951448aSJonathan Doman 769c951448aSJonathan Doman if (!found) 7702bab9831SJonathan Doman { 771c951448aSJonathan Doman continue; 772ac6a4445SGunnar Mills } 773c951448aSJonathan Doman 774c951448aSJonathan Doman // Process the first object which does match our cpu name and 775c951448aSJonathan Doman // required interfaces, and potentially ignore any other 776c951448aSJonathan Doman // matching objects. Assume all interfaces we want to process 777c951448aSJonathan Doman // must be on the same object path. 778c951448aSJonathan Doman 779c951448aSJonathan Doman handler(resp, processorId, objectPath, serviceMap); 780ac6a4445SGunnar Mills return; 781ac6a4445SGunnar Mills } 782c951448aSJonathan Doman messages::resourceNotFound(resp->res, "Processor", processorId); 783ac6a4445SGunnar Mills }, 784ac6a4445SGunnar Mills "xyz.openbmc_project.ObjectMapper", 785ac6a4445SGunnar Mills "/xyz/openbmc_project/object_mapper", 786ac6a4445SGunnar Mills "xyz.openbmc_project.ObjectMapper", "GetSubTree", 7872bab9831SJonathan Doman "/xyz/openbmc_project/inventory", 0, 78849e429caSJonathan Doman std::array<const char*, 8>{ 78971b82f26SSharad Yadav "xyz.openbmc_project.Common.UUID", 7902bab9831SJonathan Doman "xyz.openbmc_project.Inventory.Decorator.Asset", 7912bab9831SJonathan Doman "xyz.openbmc_project.Inventory.Decorator.Revision", 7922bab9831SJonathan Doman "xyz.openbmc_project.Inventory.Item.Cpu", 793cba4f448SSunnySrivastava1984 "xyz.openbmc_project.Inventory.Decorator.LocationCode", 794dba0c291SJonathan Doman "xyz.openbmc_project.Inventory.Item.Accelerator", 79549e429caSJonathan Doman "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig", 79649e429caSJonathan Doman "xyz.openbmc_project.Inventory.Decorator.UniqueIdentifier"}); 797ac6a4445SGunnar Mills } 798ac6a4445SGunnar Mills 7998d1b46d7Szhanghch05 inline void getProcessorData(const std::shared_ptr<bmcweb::AsyncResp>& aResp, 800c951448aSJonathan Doman const std::string& processorId, 801c951448aSJonathan Doman const std::string& objectPath, 802c951448aSJonathan Doman const MapperServiceMap& serviceMap) 803c951448aSJonathan Doman { 804c951448aSJonathan Doman for (const auto& [serviceName, interfaceList] : serviceMap) 805c951448aSJonathan Doman { 806c951448aSJonathan Doman for (const auto& interface : interfaceList) 807c951448aSJonathan Doman { 808c951448aSJonathan Doman if (interface == "xyz.openbmc_project.Inventory.Decorator.Asset") 809c951448aSJonathan Doman { 810c951448aSJonathan Doman getCpuAssetData(aResp, serviceName, objectPath); 811c951448aSJonathan Doman } 8120fda0f12SGeorge Liu else if (interface == 8130fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.Revision") 814c951448aSJonathan Doman { 815c951448aSJonathan Doman getCpuRevisionData(aResp, serviceName, objectPath); 816c951448aSJonathan Doman } 817c951448aSJonathan Doman else if (interface == "xyz.openbmc_project.Inventory.Item.Cpu") 818c951448aSJonathan Doman { 819c951448aSJonathan Doman getCpuDataByService(aResp, processorId, serviceName, 820c951448aSJonathan Doman objectPath); 821c951448aSJonathan Doman } 8220fda0f12SGeorge Liu else if (interface == 8230fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Item.Accelerator") 824c951448aSJonathan Doman { 825c951448aSJonathan Doman getAcceleratorDataByService(aResp, processorId, serviceName, 826c951448aSJonathan Doman objectPath); 827c951448aSJonathan Doman } 8280fda0f12SGeorge Liu else if ( 8290fda0f12SGeorge Liu interface == 8300fda0f12SGeorge Liu "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig") 831c951448aSJonathan Doman { 832c951448aSJonathan Doman getCpuConfigData(aResp, processorId, serviceName, objectPath); 833c951448aSJonathan Doman } 8340fda0f12SGeorge Liu else if (interface == 8350fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.LocationCode") 836c951448aSJonathan Doman { 837c951448aSJonathan Doman getCpuLocationCode(aResp, serviceName, objectPath); 838c951448aSJonathan Doman } 83971b82f26SSharad Yadav else if (interface == "xyz.openbmc_project.Common.UUID") 84071b82f26SSharad Yadav { 84171b82f26SSharad Yadav getProcessorUUID(aResp, serviceName, objectPath); 84271b82f26SSharad Yadav } 8430fda0f12SGeorge Liu else if (interface == 8440fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.UniqueIdentifier") 84549e429caSJonathan Doman { 84649e429caSJonathan Doman getCpuUniqueId(aResp, serviceName, objectPath); 84749e429caSJonathan Doman } 848c951448aSJonathan Doman } 849c951448aSJonathan Doman } 850c951448aSJonathan Doman } 851c951448aSJonathan Doman 852dba0c291SJonathan Doman /** 853dba0c291SJonathan Doman * Request all the properties for the given D-Bus object and fill out the 854dba0c291SJonathan Doman * related entries in the Redfish OperatingConfig response. 855dba0c291SJonathan Doman * 856dba0c291SJonathan Doman * @param[in,out] aResp Async HTTP response. 857dba0c291SJonathan Doman * @param[in] service D-Bus service name to query. 858dba0c291SJonathan Doman * @param[in] objPath D-Bus object to query. 859dba0c291SJonathan Doman */ 8608d1b46d7Szhanghch05 inline void 8618d1b46d7Szhanghch05 getOperatingConfigData(const std::shared_ptr<bmcweb::AsyncResp>& aResp, 862dba0c291SJonathan Doman const std::string& service, 863dba0c291SJonathan Doman const std::string& objPath) 864dba0c291SJonathan Doman { 865dba0c291SJonathan Doman crow::connections::systemBus->async_method_call( 866dba0c291SJonathan Doman [aResp](boost::system::error_code ec, 867dba0c291SJonathan Doman const OperatingConfigProperties& properties) { 868dba0c291SJonathan Doman if (ec) 869dba0c291SJonathan Doman { 870dba0c291SJonathan Doman BMCWEB_LOG_WARNING << "D-Bus error: " << ec << ", " 871dba0c291SJonathan Doman << ec.message(); 872dba0c291SJonathan Doman messages::internalError(aResp->res); 873dba0c291SJonathan Doman return; 874dba0c291SJonathan Doman } 875dba0c291SJonathan Doman 876dba0c291SJonathan Doman nlohmann::json& json = aResp->res.jsonValue; 877dba0c291SJonathan Doman for (const auto& [key, variant] : properties) 878dba0c291SJonathan Doman { 879dba0c291SJonathan Doman if (key == "AvailableCoreCount") 880dba0c291SJonathan Doman { 881dba0c291SJonathan Doman const size_t* cores = std::get_if<size_t>(&variant); 882dba0c291SJonathan Doman if (cores != nullptr) 883dba0c291SJonathan Doman { 884dba0c291SJonathan Doman json["TotalAvailableCoreCount"] = *cores; 885dba0c291SJonathan Doman } 886dba0c291SJonathan Doman } 887dba0c291SJonathan Doman else if (key == "BaseSpeed") 888dba0c291SJonathan Doman { 889dba0c291SJonathan Doman const uint32_t* speed = std::get_if<uint32_t>(&variant); 890dba0c291SJonathan Doman if (speed != nullptr) 891dba0c291SJonathan Doman { 892dba0c291SJonathan Doman json["BaseSpeedMHz"] = *speed; 893dba0c291SJonathan Doman } 894dba0c291SJonathan Doman } 895dba0c291SJonathan Doman else if (key == "MaxJunctionTemperature") 896dba0c291SJonathan Doman { 897dba0c291SJonathan Doman const uint32_t* temp = std::get_if<uint32_t>(&variant); 898dba0c291SJonathan Doman if (temp != nullptr) 899dba0c291SJonathan Doman { 900dba0c291SJonathan Doman json["MaxJunctionTemperatureCelsius"] = *temp; 901dba0c291SJonathan Doman } 902dba0c291SJonathan Doman } 903dba0c291SJonathan Doman else if (key == "MaxSpeed") 904dba0c291SJonathan Doman { 905dba0c291SJonathan Doman const uint32_t* speed = std::get_if<uint32_t>(&variant); 906dba0c291SJonathan Doman if (speed != nullptr) 907dba0c291SJonathan Doman { 908dba0c291SJonathan Doman json["MaxSpeedMHz"] = *speed; 909dba0c291SJonathan Doman } 910dba0c291SJonathan Doman } 911dba0c291SJonathan Doman else if (key == "PowerLimit") 912dba0c291SJonathan Doman { 913dba0c291SJonathan Doman const uint32_t* tdp = std::get_if<uint32_t>(&variant); 914dba0c291SJonathan Doman if (tdp != nullptr) 915dba0c291SJonathan Doman { 916dba0c291SJonathan Doman json["TDPWatts"] = *tdp; 917dba0c291SJonathan Doman } 918dba0c291SJonathan Doman } 919dba0c291SJonathan Doman else if (key == "TurboProfile") 920dba0c291SJonathan Doman { 921dba0c291SJonathan Doman const auto* turboList = 922dba0c291SJonathan Doman std::get_if<TurboProfileProperty>(&variant); 923dba0c291SJonathan Doman if (turboList == nullptr) 924dba0c291SJonathan Doman { 925dba0c291SJonathan Doman continue; 926dba0c291SJonathan Doman } 927dba0c291SJonathan Doman 928dba0c291SJonathan Doman nlohmann::json& turboArray = json["TurboProfile"]; 929dba0c291SJonathan Doman turboArray = nlohmann::json::array(); 930dba0c291SJonathan Doman for (const auto& [turboSpeed, coreCount] : *turboList) 931dba0c291SJonathan Doman { 932dba0c291SJonathan Doman turboArray.push_back({{"ActiveCoreCount", coreCount}, 933dba0c291SJonathan Doman {"MaxSpeedMHz", turboSpeed}}); 934dba0c291SJonathan Doman } 935dba0c291SJonathan Doman } 936dba0c291SJonathan Doman else if (key == "BaseSpeedPrioritySettings") 937dba0c291SJonathan Doman { 938dba0c291SJonathan Doman const auto* baseSpeedList = 939dba0c291SJonathan Doman std::get_if<BaseSpeedPrioritySettingsProperty>( 940dba0c291SJonathan Doman &variant); 941dba0c291SJonathan Doman if (baseSpeedList == nullptr) 942dba0c291SJonathan Doman { 943dba0c291SJonathan Doman continue; 944dba0c291SJonathan Doman } 945dba0c291SJonathan Doman 946dba0c291SJonathan Doman nlohmann::json& baseSpeedArray = 947dba0c291SJonathan Doman json["BaseSpeedPrioritySettings"]; 948dba0c291SJonathan Doman baseSpeedArray = nlohmann::json::array(); 949dba0c291SJonathan Doman for (const auto& [baseSpeed, coreList] : *baseSpeedList) 950dba0c291SJonathan Doman { 951dba0c291SJonathan Doman baseSpeedArray.push_back( 952dba0c291SJonathan Doman {{"CoreCount", coreList.size()}, 953dba0c291SJonathan Doman {"CoreIDs", coreList}, 954dba0c291SJonathan Doman {"BaseSpeedMHz", baseSpeed}}); 955dba0c291SJonathan Doman } 956dba0c291SJonathan Doman } 957dba0c291SJonathan Doman } 958dba0c291SJonathan Doman }, 959dba0c291SJonathan Doman service, objPath, "org.freedesktop.DBus.Properties", "GetAll", 960dba0c291SJonathan Doman "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig"); 961dba0c291SJonathan Doman } 962dba0c291SJonathan Doman 9633cde86f1SJonathan Doman /** 9643cde86f1SJonathan Doman * Handle the D-Bus response from attempting to set the CPU's AppliedConfig 9653cde86f1SJonathan Doman * property. Main task is to translate error messages into Redfish errors. 9663cde86f1SJonathan Doman * 9673cde86f1SJonathan Doman * @param[in,out] resp HTTP response. 9683cde86f1SJonathan Doman * @param[in] setPropVal Value which we attempted to set. 9693cde86f1SJonathan Doman * @param[in] ec D-Bus response error code. 9703cde86f1SJonathan Doman * @param[in] msg D-Bus response message. 9713cde86f1SJonathan Doman */ 9723cde86f1SJonathan Doman inline void 9733cde86f1SJonathan Doman handleAppliedConfigResponse(const std::shared_ptr<bmcweb::AsyncResp>& resp, 9743cde86f1SJonathan Doman const std::string& setPropVal, 9753cde86f1SJonathan Doman boost::system::error_code ec, 9763cde86f1SJonathan Doman const sdbusplus::message::message& msg) 9773cde86f1SJonathan Doman { 9783cde86f1SJonathan Doman if (!ec) 9793cde86f1SJonathan Doman { 9803cde86f1SJonathan Doman BMCWEB_LOG_DEBUG << "Set Property succeeded"; 9813cde86f1SJonathan Doman return; 9823cde86f1SJonathan Doman } 9833cde86f1SJonathan Doman 9843cde86f1SJonathan Doman BMCWEB_LOG_DEBUG << "Set Property failed: " << ec; 9853cde86f1SJonathan Doman 9863cde86f1SJonathan Doman const sd_bus_error* dbusError = msg.get_error(); 9873cde86f1SJonathan Doman if (dbusError == nullptr) 9883cde86f1SJonathan Doman { 9893cde86f1SJonathan Doman messages::internalError(resp->res); 9903cde86f1SJonathan Doman return; 9913cde86f1SJonathan Doman } 9923cde86f1SJonathan Doman 9933cde86f1SJonathan Doman // The asio error code doesn't know about our custom errors, so we have to 9943cde86f1SJonathan Doman // parse the error string. Some of these D-Bus -> Redfish translations are a 9953cde86f1SJonathan Doman // stretch, but it's good to try to communicate something vaguely useful. 9963cde86f1SJonathan Doman if (strcmp(dbusError->name, 9973cde86f1SJonathan Doman "xyz.openbmc_project.Common.Error.InvalidArgument") == 0) 9983cde86f1SJonathan Doman { 9993cde86f1SJonathan Doman // Service did not like the object_path we tried to set. 10003cde86f1SJonathan Doman messages::propertyValueIncorrect( 10013cde86f1SJonathan Doman resp->res, "AppliedOperatingConfig/@odata.id", setPropVal); 10023cde86f1SJonathan Doman } 10033cde86f1SJonathan Doman else if (strcmp(dbusError->name, 10043cde86f1SJonathan Doman "xyz.openbmc_project.Common.Error.NotAllowed") == 0) 10053cde86f1SJonathan Doman { 10063cde86f1SJonathan Doman // Service indicates we can never change the config for this processor. 10073cde86f1SJonathan Doman messages::propertyNotWritable(resp->res, "AppliedOperatingConfig"); 10083cde86f1SJonathan Doman } 10093cde86f1SJonathan Doman else if (strcmp(dbusError->name, 10103cde86f1SJonathan Doman "xyz.openbmc_project.Common.Error.Unavailable") == 0) 10113cde86f1SJonathan Doman { 10123cde86f1SJonathan Doman // Service indicates the config cannot be changed right now, but maybe 10133cde86f1SJonathan Doman // in a different system state. 10143cde86f1SJonathan Doman messages::resourceInStandby(resp->res); 10153cde86f1SJonathan Doman } 10163cde86f1SJonathan Doman else if (strcmp(dbusError->name, 10173cde86f1SJonathan Doman "xyz.openbmc_project.Common.Device.Error.WriteFailure") == 10183cde86f1SJonathan Doman 0) 10193cde86f1SJonathan Doman { 10203cde86f1SJonathan Doman // Service tried to change the config, but it failed. 10213cde86f1SJonathan Doman messages::operationFailed(resp->res); 10223cde86f1SJonathan Doman } 10233cde86f1SJonathan Doman else 10243cde86f1SJonathan Doman { 10253cde86f1SJonathan Doman messages::internalError(resp->res); 10263cde86f1SJonathan Doman } 10273cde86f1SJonathan Doman } 10283cde86f1SJonathan Doman 10293cde86f1SJonathan Doman /** 10303cde86f1SJonathan Doman * Handle the PATCH operation of the AppliedOperatingConfig property. Do basic 10313cde86f1SJonathan Doman * validation of the input data, and then set the D-Bus property. 10323cde86f1SJonathan Doman * 10333cde86f1SJonathan Doman * @param[in,out] resp Async HTTP response. 10343cde86f1SJonathan Doman * @param[in] processorId Processor's Id. 10353cde86f1SJonathan Doman * @param[in] appliedConfigUri New property value to apply. 10363cde86f1SJonathan Doman * @param[in] cpuObjectPath Path of CPU object to modify. 10373cde86f1SJonathan Doman * @param[in] serviceMap Service map for CPU object. 10383cde86f1SJonathan Doman */ 10393cde86f1SJonathan Doman inline void patchAppliedOperatingConfig( 10403cde86f1SJonathan Doman const std::shared_ptr<bmcweb::AsyncResp>& resp, 10413cde86f1SJonathan Doman const std::string& processorId, const std::string& appliedConfigUri, 10423cde86f1SJonathan Doman const std::string& cpuObjectPath, const MapperServiceMap& serviceMap) 10433cde86f1SJonathan Doman { 10443cde86f1SJonathan Doman // Check that the property even exists by checking for the interface 10453cde86f1SJonathan Doman const std::string* controlService = nullptr; 10463cde86f1SJonathan Doman for (const auto& [serviceName, interfaceList] : serviceMap) 10473cde86f1SJonathan Doman { 10483cde86f1SJonathan Doman if (std::find(interfaceList.begin(), interfaceList.end(), 10493cde86f1SJonathan Doman "xyz.openbmc_project.Control.Processor." 10503cde86f1SJonathan Doman "CurrentOperatingConfig") != interfaceList.end()) 10513cde86f1SJonathan Doman { 10523cde86f1SJonathan Doman controlService = &serviceName; 10533cde86f1SJonathan Doman break; 10543cde86f1SJonathan Doman } 10553cde86f1SJonathan Doman } 10563cde86f1SJonathan Doman 10573cde86f1SJonathan Doman if (controlService == nullptr) 10583cde86f1SJonathan Doman { 10593cde86f1SJonathan Doman messages::internalError(resp->res); 10603cde86f1SJonathan Doman return; 10613cde86f1SJonathan Doman } 10623cde86f1SJonathan Doman 10633cde86f1SJonathan Doman // Check that the config URI is a child of the cpu URI being patched. 10643cde86f1SJonathan Doman std::string expectedPrefix("/redfish/v1/Systems/system/Processors/"); 10653cde86f1SJonathan Doman expectedPrefix += processorId; 10663cde86f1SJonathan Doman expectedPrefix += "/OperatingConfigs/"; 10673cde86f1SJonathan Doman if (!boost::starts_with(appliedConfigUri, expectedPrefix) || 10683cde86f1SJonathan Doman expectedPrefix.size() == appliedConfigUri.size()) 10693cde86f1SJonathan Doman { 10703cde86f1SJonathan Doman messages::propertyValueIncorrect( 10713cde86f1SJonathan Doman resp->res, "AppliedOperatingConfig/@odata.id", appliedConfigUri); 10723cde86f1SJonathan Doman return; 10733cde86f1SJonathan Doman } 10743cde86f1SJonathan Doman 10753cde86f1SJonathan Doman // Generate the D-Bus path of the OperatingConfig object, by assuming it's a 10763cde86f1SJonathan Doman // direct child of the CPU object. 10773cde86f1SJonathan Doman // Strip the expectedPrefix from the config URI to get the "filename", and 10783cde86f1SJonathan Doman // append to the CPU's path. 10793cde86f1SJonathan Doman std::string configBaseName = appliedConfigUri.substr(expectedPrefix.size()); 10803cde86f1SJonathan Doman sdbusplus::message::object_path configPath(cpuObjectPath); 10813cde86f1SJonathan Doman configPath /= configBaseName; 10823cde86f1SJonathan Doman 10833cde86f1SJonathan Doman BMCWEB_LOG_INFO << "Setting config to " << configPath.str; 10843cde86f1SJonathan Doman 10853cde86f1SJonathan Doman // Set the property, with handler to check error responses 10863cde86f1SJonathan Doman crow::connections::systemBus->async_method_call( 10873cde86f1SJonathan Doman [resp, appliedConfigUri](boost::system::error_code ec, 10883cde86f1SJonathan Doman sdbusplus::message::message& msg) { 10893cde86f1SJonathan Doman handleAppliedConfigResponse(resp, appliedConfigUri, ec, msg); 10903cde86f1SJonathan Doman }, 10913cde86f1SJonathan Doman *controlService, cpuObjectPath, "org.freedesktop.DBus.Properties", 10923cde86f1SJonathan Doman "Set", "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig", 10933cde86f1SJonathan Doman "AppliedConfig", 10943cde86f1SJonathan Doman std::variant<sdbusplus::message::object_path>(std::move(configPath))); 10953cde86f1SJonathan Doman } 10963cde86f1SJonathan Doman 10977e860f15SJohn Edward Broadbent inline void requestRoutesOperatingConfigCollection(App& app) 1098dba0c291SJonathan Doman { 1099dba0c291SJonathan Doman 11007e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 11017e860f15SJohn Edward Broadbent app, "/redfish/v1/Systems/system/Processors/<str>/OperatingConfigs/") 1102ed398213SEd Tanous .privileges(redfish::privileges::getOperatingConfigCollection) 11030fda0f12SGeorge Liu .methods( 11040fda0f12SGeorge Liu boost::beast::http::verb::get)([](const crow::Request& req, 11050fda0f12SGeorge Liu const std::shared_ptr< 11060fda0f12SGeorge Liu bmcweb::AsyncResp>& asyncResp, 11077e860f15SJohn Edward Broadbent const std::string& cpuName) { 11088d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.type"] = 1109dba0c291SJonathan Doman "#OperatingConfigCollection.OperatingConfigCollection"; 11108d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.id"] = req.url; 11110fda0f12SGeorge Liu asyncResp->res.jsonValue["Name"] = "Operating Config Collection"; 1112dba0c291SJonathan Doman 11137e860f15SJohn Edward Broadbent // First find the matching CPU object so we know how to 11147e860f15SJohn Edward Broadbent // constrain our search for related Config objects. 1115dba0c291SJonathan Doman crow::connections::systemBus->async_method_call( 11160fda0f12SGeorge Liu [asyncResp, cpuName](const boost::system::error_code ec, 1117dba0c291SJonathan Doman const std::vector<std::string>& objects) { 1118dba0c291SJonathan Doman if (ec) 1119dba0c291SJonathan Doman { 1120dba0c291SJonathan Doman BMCWEB_LOG_WARNING << "D-Bus error: " << ec << ", " 1121dba0c291SJonathan Doman << ec.message(); 1122dba0c291SJonathan Doman messages::internalError(asyncResp->res); 1123dba0c291SJonathan Doman return; 1124dba0c291SJonathan Doman } 1125dba0c291SJonathan Doman 1126dba0c291SJonathan Doman for (const std::string& object : objects) 1127dba0c291SJonathan Doman { 1128dba0c291SJonathan Doman if (!boost::ends_with(object, cpuName)) 1129dba0c291SJonathan Doman { 1130dba0c291SJonathan Doman continue; 1131dba0c291SJonathan Doman } 1132dba0c291SJonathan Doman 11337e860f15SJohn Edward Broadbent // Not expected that there will be multiple matching 11347e860f15SJohn Edward Broadbent // CPU objects, but if there are just use the first 11357e860f15SJohn Edward Broadbent // one. 1136dba0c291SJonathan Doman 11377e860f15SJohn Edward Broadbent // Use the common search routine to construct the 11387e860f15SJohn Edward Broadbent // Collection of all Config objects under this CPU. 1139dba0c291SJonathan Doman collection_util::getCollectionMembers( 1140dba0c291SJonathan Doman asyncResp, 11410fda0f12SGeorge Liu "/redfish/v1/Systems/system/Processors/" + cpuName + 11420fda0f12SGeorge Liu "/OperatingConfigs", 11430fda0f12SGeorge Liu {"xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig"}, 1144dba0c291SJonathan Doman object.c_str()); 1145dba0c291SJonathan Doman return; 1146dba0c291SJonathan Doman } 1147dba0c291SJonathan Doman }, 1148dba0c291SJonathan Doman "xyz.openbmc_project.ObjectMapper", 1149dba0c291SJonathan Doman "/xyz/openbmc_project/object_mapper", 1150dba0c291SJonathan Doman "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", 1151dba0c291SJonathan Doman "/xyz/openbmc_project/inventory", 0, 11527e860f15SJohn Edward Broadbent std::array<const char*, 1>{ 11530fda0f12SGeorge Liu "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig"}); 11547e860f15SJohn Edward Broadbent }); 1155dba0c291SJonathan Doman } 1156dba0c291SJonathan Doman 11577e860f15SJohn Edward Broadbent inline void requestRoutesOperatingConfig(App& app) 1158dba0c291SJonathan Doman { 11597e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 11607e860f15SJohn Edward Broadbent app, 11617e860f15SJohn Edward Broadbent "/redfish/v1/Systems/system/Processors/<str>/OperatingConfigs/<str>/") 1162ed398213SEd Tanous .privileges(redfish::privileges::getOperatingConfig) 11637e860f15SJohn Edward Broadbent .methods( 11647e860f15SJohn Edward Broadbent boost::beast::http::verb::get)([](const crow::Request& req, 11657e860f15SJohn Edward Broadbent const std::shared_ptr< 11667e860f15SJohn Edward Broadbent bmcweb::AsyncResp>& asyncResp, 11677e860f15SJohn Edward Broadbent const std::string& cpuName, 11687e860f15SJohn Edward Broadbent const std::string& configName) { 11697e860f15SJohn Edward Broadbent // Ask for all objects implementing OperatingConfig so we can search 11707e860f15SJohn Edward Broadbent // for one with a matching name 1171dba0c291SJonathan Doman crow::connections::systemBus->async_method_call( 1172dba0c291SJonathan Doman [asyncResp, cpuName, configName, 1173dba0c291SJonathan Doman reqUrl{req.url}](boost::system::error_code ec, 1174dba0c291SJonathan Doman const MapperGetSubTreeResponse& subtree) { 1175dba0c291SJonathan Doman if (ec) 1176dba0c291SJonathan Doman { 1177dba0c291SJonathan Doman BMCWEB_LOG_WARNING << "D-Bus error: " << ec << ", " 1178dba0c291SJonathan Doman << ec.message(); 1179dba0c291SJonathan Doman messages::internalError(asyncResp->res); 1180dba0c291SJonathan Doman return; 1181dba0c291SJonathan Doman } 11827e860f15SJohn Edward Broadbent const std::string expectedEnding = 11837e860f15SJohn Edward Broadbent cpuName + '/' + configName; 1184dba0c291SJonathan Doman for (const auto& [objectPath, serviceMap] : subtree) 1185dba0c291SJonathan Doman { 1186dba0c291SJonathan Doman // Ignore any configs without matching cpuX/configY 1187dba0c291SJonathan Doman if (!boost::ends_with(objectPath, expectedEnding) || 1188dba0c291SJonathan Doman serviceMap.empty()) 1189dba0c291SJonathan Doman { 1190dba0c291SJonathan Doman continue; 1191dba0c291SJonathan Doman } 1192dba0c291SJonathan Doman 1193dba0c291SJonathan Doman nlohmann::json& json = asyncResp->res.jsonValue; 1194dba0c291SJonathan Doman json["@odata.type"] = 1195dba0c291SJonathan Doman "#OperatingConfig.v1_0_0.OperatingConfig"; 1196dba0c291SJonathan Doman json["@odata.id"] = reqUrl; 1197dba0c291SJonathan Doman json["Name"] = "Processor Profile"; 1198dba0c291SJonathan Doman json["Id"] = configName; 1199dba0c291SJonathan Doman 1200dba0c291SJonathan Doman // Just use the first implementation of the object - not 12017e860f15SJohn Edward Broadbent // expected that there would be multiple matching 12027e860f15SJohn Edward Broadbent // services 12037e860f15SJohn Edward Broadbent getOperatingConfigData( 12047e860f15SJohn Edward Broadbent asyncResp, serviceMap.begin()->first, objectPath); 1205dba0c291SJonathan Doman return; 1206dba0c291SJonathan Doman } 12077e860f15SJohn Edward Broadbent messages::resourceNotFound(asyncResp->res, 12087e860f15SJohn Edward Broadbent "OperatingConfig", configName); 1209dba0c291SJonathan Doman }, 1210dba0c291SJonathan Doman "xyz.openbmc_project.ObjectMapper", 1211dba0c291SJonathan Doman "/xyz/openbmc_project/object_mapper", 1212dba0c291SJonathan Doman "xyz.openbmc_project.ObjectMapper", "GetSubTree", 1213dba0c291SJonathan Doman "/xyz/openbmc_project/inventory", 0, 1214dba0c291SJonathan Doman std::array<const char*, 1>{ 1215dba0c291SJonathan Doman "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig"}); 12167e860f15SJohn Edward Broadbent }); 1217ac6a4445SGunnar Mills } 1218ac6a4445SGunnar Mills 12197e860f15SJohn Edward Broadbent inline void requestRoutesProcessorCollection(App& app) 12207e860f15SJohn Edward Broadbent { 1221ac6a4445SGunnar Mills /** 1222ac6a4445SGunnar Mills * Functions triggers appropriate requests on DBus 1223ac6a4445SGunnar Mills */ 12247e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Processors/") 1225ed398213SEd Tanous .privileges(redfish::privileges::getProcessorCollection) 12267e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 12277e860f15SJohn Edward Broadbent [](const crow::Request&, 12287e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 12298d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.type"] = 1230ac6a4445SGunnar Mills "#ProcessorCollection.ProcessorCollection"; 12318d1b46d7Szhanghch05 asyncResp->res.jsonValue["Name"] = "Processor Collection"; 1232ac6a4445SGunnar Mills 12338d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.id"] = 12348d1b46d7Szhanghch05 "/redfish/v1/Systems/system/Processors"; 1235ac6a4445SGunnar Mills 123605030b8eSGunnar Mills collection_util::getCollectionMembers( 123705030b8eSGunnar Mills asyncResp, "/redfish/v1/Systems/system/Processors", 1238c951448aSJonathan Doman std::vector<const char*>(processorInterfaces.begin(), 1239c951448aSJonathan Doman processorInterfaces.end())); 12407e860f15SJohn Edward Broadbent }); 1241ac6a4445SGunnar Mills } 1242ac6a4445SGunnar Mills 12437e860f15SJohn Edward Broadbent inline void requestRoutesProcessor(App& app) 12447e860f15SJohn Edward Broadbent { 1245ac6a4445SGunnar Mills /** 1246ac6a4445SGunnar Mills * Functions triggers appropriate requests on DBus 1247ac6a4445SGunnar Mills */ 12487e860f15SJohn Edward Broadbent 12497e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Processors/<str>/") 1250ed398213SEd Tanous .privileges(redfish::privileges::getProcessor) 12517e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 12527e860f15SJohn Edward Broadbent [](const crow::Request&, 12537e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 12547e860f15SJohn Edward Broadbent const std::string& processorId) { 12558d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.type"] = 12568d1b46d7Szhanghch05 "#Processor.v1_11_0.Processor"; 12578d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.id"] = 1258ac6a4445SGunnar Mills "/redfish/v1/Systems/system/Processors/" + processorId; 1259ac6a4445SGunnar Mills 1260c951448aSJonathan Doman getProcessorObject(asyncResp, processorId, getProcessorData); 12617e860f15SJohn Edward Broadbent }); 12623cde86f1SJonathan Doman 12637e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Processors/<str>/") 1264ed398213SEd Tanous .privileges(redfish::privileges::patchProcessor) 12657e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::patch)( 12667e860f15SJohn Edward Broadbent [](const crow::Request& req, 12677e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 12687e860f15SJohn Edward Broadbent const std::string& processorId) { 12693cde86f1SJonathan Doman std::optional<nlohmann::json> appliedConfigJson; 12707e860f15SJohn Edward Broadbent if (!json_util::readJson(req, asyncResp->res, 12717e860f15SJohn Edward Broadbent "AppliedOperatingConfig", 12723cde86f1SJonathan Doman appliedConfigJson)) 12733cde86f1SJonathan Doman { 12743cde86f1SJonathan Doman return; 12753cde86f1SJonathan Doman } 12763cde86f1SJonathan Doman 12773cde86f1SJonathan Doman std::string appliedConfigUri; 12783cde86f1SJonathan Doman if (appliedConfigJson) 12793cde86f1SJonathan Doman { 12803cde86f1SJonathan Doman if (!json_util::readJson(*appliedConfigJson, asyncResp->res, 12813cde86f1SJonathan Doman "@odata.id", appliedConfigUri)) 12823cde86f1SJonathan Doman { 12833cde86f1SJonathan Doman return; 12843cde86f1SJonathan Doman } 12857e860f15SJohn Edward Broadbent // Check for 404 and find matching D-Bus object, then run 12867e860f15SJohn Edward Broadbent // property patch handlers if that all succeeds. 12873cde86f1SJonathan Doman getProcessorObject( 12887e860f15SJohn Edward Broadbent asyncResp, processorId, 12893cde86f1SJonathan Doman [appliedConfigUri = std::move(appliedConfigUri)]( 12903cde86f1SJonathan Doman const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 12913cde86f1SJonathan Doman const std::string& processorId, 12923cde86f1SJonathan Doman const std::string& objectPath, 12933cde86f1SJonathan Doman const MapperServiceMap& serviceMap) { 12943cde86f1SJonathan Doman patchAppliedOperatingConfig(asyncResp, processorId, 12957e860f15SJohn Edward Broadbent appliedConfigUri, 12967e860f15SJohn Edward Broadbent objectPath, serviceMap); 12973cde86f1SJonathan Doman }); 12983cde86f1SJonathan Doman } 12997e860f15SJohn Edward Broadbent }); 13003cde86f1SJonathan Doman } 1301ac6a4445SGunnar Mills 1302ac6a4445SGunnar Mills } // namespace redfish 1303