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 20*7e860f15SJohn Edward Broadbent #include <app.hpp> 21ac6a4445SGunnar Mills #include <boost/container/flat_map.hpp> 22dba0c291SJonathan Doman #include <sdbusplus/message/native_types.hpp> 23dba0c291SJonathan Doman #include <sdbusplus/utility/dedup_variant.hpp> 24ac6a4445SGunnar Mills #include <utils/collection.hpp> 25ac6a4445SGunnar Mills #include <utils/json_utils.hpp> 26ac6a4445SGunnar Mills 27ac6a4445SGunnar Mills namespace redfish 28ac6a4445SGunnar Mills { 29ac6a4445SGunnar Mills 30ac6a4445SGunnar Mills using InterfacesProperties = boost::container::flat_map< 31ac6a4445SGunnar Mills std::string, 32ac6a4445SGunnar Mills boost::container::flat_map<std::string, dbus::utility::DbusVariantType>>; 33ac6a4445SGunnar Mills 34c951448aSJonathan Doman // Map of service name to list of interfaces 35c951448aSJonathan Doman using MapperServiceMap = 36c951448aSJonathan Doman std::vector<std::pair<std::string, std::vector<std::string>>>; 37c951448aSJonathan Doman 38c951448aSJonathan Doman // Map of object paths to MapperServiceMaps 39c951448aSJonathan Doman using MapperGetSubTreeResponse = 40c951448aSJonathan Doman std::vector<std::pair<std::string, MapperServiceMap>>; 41c951448aSJonathan Doman 42c951448aSJonathan Doman // Interfaces which imply a D-Bus object represents a Processor 43c951448aSJonathan Doman constexpr std::array<const char*, 2> processorInterfaces = { 44c951448aSJonathan Doman "xyz.openbmc_project.Inventory.Item.Cpu", 45c951448aSJonathan Doman "xyz.openbmc_project.Inventory.Item.Accelerator"}; 462bab9831SJonathan Doman 47ac6a4445SGunnar Mills inline void 488d1b46d7Szhanghch05 getCpuDataByInterface(const std::shared_ptr<bmcweb::AsyncResp>& aResp, 49ac6a4445SGunnar Mills const InterfacesProperties& cpuInterfacesProperties) 50ac6a4445SGunnar Mills { 51ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "Get CPU resources by interface."; 52ac6a4445SGunnar Mills 53a1649ec6SChicago Duan // Set the default value of state 54a1649ec6SChicago Duan aResp->res.jsonValue["Status"]["State"] = "Enabled"; 55a1649ec6SChicago Duan aResp->res.jsonValue["Status"]["Health"] = "OK"; 56ac6a4445SGunnar Mills 57ac6a4445SGunnar Mills for (const auto& interface : cpuInterfacesProperties) 58ac6a4445SGunnar Mills { 59ac6a4445SGunnar Mills for (const auto& property : interface.second) 60ac6a4445SGunnar Mills { 61a1649ec6SChicago Duan if (property.first == "Present") 62ac6a4445SGunnar Mills { 63a1649ec6SChicago Duan const bool* cpuPresent = std::get_if<bool>(&property.second); 64a1649ec6SChicago Duan if (cpuPresent == nullptr) 65ac6a4445SGunnar Mills { 66ac6a4445SGunnar Mills // Important property not in desired type 67ac6a4445SGunnar Mills messages::internalError(aResp->res); 68ac6a4445SGunnar Mills return; 69ac6a4445SGunnar Mills } 70a1649ec6SChicago Duan if (*cpuPresent == false) 71ac6a4445SGunnar Mills { 72a1649ec6SChicago Duan // Slot is not populated 73ac6a4445SGunnar Mills aResp->res.jsonValue["Status"]["State"] = "Absent"; 74a1649ec6SChicago Duan } 75a1649ec6SChicago Duan } 76a1649ec6SChicago Duan else if (property.first == "Functional") 77a1649ec6SChicago Duan { 78a1649ec6SChicago Duan const bool* cpuFunctional = std::get_if<bool>(&property.second); 79a1649ec6SChicago Duan if (cpuFunctional == nullptr) 80a1649ec6SChicago Duan { 81a1649ec6SChicago Duan messages::internalError(aResp->res); 82ac6a4445SGunnar Mills return; 83ac6a4445SGunnar Mills } 84a1649ec6SChicago Duan if (*cpuFunctional == false) 85a1649ec6SChicago Duan { 86a1649ec6SChicago Duan aResp->res.jsonValue["Status"]["Health"] = "Critical"; 87a1649ec6SChicago Duan } 88a1649ec6SChicago Duan } 89a1649ec6SChicago Duan else if (property.first == "CoreCount") 90a1649ec6SChicago Duan { 91a1649ec6SChicago Duan const uint16_t* coresCount = 92a1649ec6SChicago Duan std::get_if<uint16_t>(&property.second); 93a1649ec6SChicago Duan if (coresCount == nullptr) 94a1649ec6SChicago Duan { 95a1649ec6SChicago Duan messages::internalError(aResp->res); 96a1649ec6SChicago Duan return; 97a1649ec6SChicago Duan } 98ac6a4445SGunnar Mills aResp->res.jsonValue["TotalCores"] = *coresCount; 99ac6a4445SGunnar Mills } 100dc3fa667SJonathan Doman else if (property.first == "MaxSpeedInMhz") 101dc3fa667SJonathan Doman { 102dc3fa667SJonathan Doman const uint32_t* value = std::get_if<uint32_t>(&property.second); 103dc3fa667SJonathan Doman if (value != nullptr) 104dc3fa667SJonathan Doman { 105dc3fa667SJonathan Doman aResp->res.jsonValue["MaxSpeedMHz"] = *value; 106dc3fa667SJonathan Doman } 107dc3fa667SJonathan Doman } 108ac6a4445SGunnar Mills else if (property.first == "Socket") 109ac6a4445SGunnar Mills { 110ac6a4445SGunnar Mills const std::string* value = 111ac6a4445SGunnar Mills std::get_if<std::string>(&property.second); 112ac6a4445SGunnar Mills if (value != nullptr) 113ac6a4445SGunnar Mills { 114ac6a4445SGunnar Mills aResp->res.jsonValue["Socket"] = *value; 115ac6a4445SGunnar Mills } 116ac6a4445SGunnar Mills } 117ac6a4445SGunnar Mills else if (property.first == "ThreadCount") 118ac6a4445SGunnar Mills { 119dc3fa667SJonathan Doman const uint16_t* value = std::get_if<uint16_t>(&property.second); 120ac6a4445SGunnar Mills if (value != nullptr) 121ac6a4445SGunnar Mills { 122ac6a4445SGunnar Mills aResp->res.jsonValue["TotalThreads"] = *value; 123ac6a4445SGunnar Mills } 124ac6a4445SGunnar Mills } 125ac6a4445SGunnar Mills else if (property.first == "Family") 126ac6a4445SGunnar Mills { 127ac6a4445SGunnar Mills const std::string* value = 128ac6a4445SGunnar Mills std::get_if<std::string>(&property.second); 129ac6a4445SGunnar Mills if (value != nullptr) 130ac6a4445SGunnar Mills { 131ac6a4445SGunnar Mills aResp->res.jsonValue["ProcessorId"]["EffectiveFamily"] = 132ac6a4445SGunnar Mills *value; 133ac6a4445SGunnar Mills } 134ac6a4445SGunnar Mills } 135ac6a4445SGunnar Mills else if (property.first == "Id") 136ac6a4445SGunnar Mills { 137ac6a4445SGunnar Mills const uint64_t* value = std::get_if<uint64_t>(&property.second); 138ac6a4445SGunnar Mills if (value != nullptr && *value != 0) 139ac6a4445SGunnar Mills { 140ac6a4445SGunnar Mills aResp->res 141ac6a4445SGunnar Mills .jsonValue["ProcessorId"]["IdentificationRegisters"] = 142ac6a4445SGunnar Mills boost::lexical_cast<std::string>(*value); 143ac6a4445SGunnar Mills } 144ac6a4445SGunnar Mills } 145ac6a4445SGunnar Mills } 146ac6a4445SGunnar Mills } 147ac6a4445SGunnar Mills 148ac6a4445SGunnar Mills return; 149ac6a4445SGunnar Mills } 150ac6a4445SGunnar Mills 1518d1b46d7Szhanghch05 inline void getCpuDataByService(std::shared_ptr<bmcweb::AsyncResp> aResp, 152ac6a4445SGunnar Mills const std::string& cpuId, 153ac6a4445SGunnar Mills const std::string& service, 154ac6a4445SGunnar Mills const std::string& objPath) 155ac6a4445SGunnar Mills { 156ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "Get available system cpu resources by service."; 157ac6a4445SGunnar Mills 158ac6a4445SGunnar Mills crow::connections::systemBus->async_method_call( 159ac6a4445SGunnar Mills [cpuId, service, objPath, aResp{std::move(aResp)}]( 160ac6a4445SGunnar Mills const boost::system::error_code ec, 161ac6a4445SGunnar Mills const dbus::utility::ManagedObjectType& dbusData) { 162ac6a4445SGunnar Mills if (ec) 163ac6a4445SGunnar Mills { 164ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "DBUS response error"; 165ac6a4445SGunnar Mills messages::internalError(aResp->res); 166ac6a4445SGunnar Mills return; 167ac6a4445SGunnar Mills } 168ac6a4445SGunnar Mills aResp->res.jsonValue["Id"] = cpuId; 169ac6a4445SGunnar Mills aResp->res.jsonValue["Name"] = "Processor"; 170ac6a4445SGunnar Mills aResp->res.jsonValue["ProcessorType"] = "CPU"; 171ac6a4445SGunnar Mills 172ac6a4445SGunnar Mills bool slotPresent = false; 173ac6a4445SGunnar Mills std::string corePath = objPath + "/core"; 174ac6a4445SGunnar Mills size_t totalCores = 0; 175ac6a4445SGunnar Mills for (const auto& object : dbusData) 176ac6a4445SGunnar Mills { 177ac6a4445SGunnar Mills if (object.first.str == objPath) 178ac6a4445SGunnar Mills { 179ac6a4445SGunnar Mills getCpuDataByInterface(aResp, object.second); 180ac6a4445SGunnar Mills } 181ac6a4445SGunnar Mills else if (boost::starts_with(object.first.str, corePath)) 182ac6a4445SGunnar Mills { 183ac6a4445SGunnar Mills for (const auto& interface : object.second) 184ac6a4445SGunnar Mills { 185ac6a4445SGunnar Mills if (interface.first == 186ac6a4445SGunnar Mills "xyz.openbmc_project.Inventory.Item") 187ac6a4445SGunnar Mills { 188ac6a4445SGunnar Mills for (const auto& property : interface.second) 189ac6a4445SGunnar Mills { 190ac6a4445SGunnar Mills if (property.first == "Present") 191ac6a4445SGunnar Mills { 192ac6a4445SGunnar Mills const bool* present = 193ac6a4445SGunnar Mills std::get_if<bool>(&property.second); 194ac6a4445SGunnar Mills if (present != nullptr) 195ac6a4445SGunnar Mills { 196ac6a4445SGunnar Mills if (*present == true) 197ac6a4445SGunnar Mills { 198ac6a4445SGunnar Mills slotPresent = true; 199ac6a4445SGunnar Mills totalCores++; 200ac6a4445SGunnar Mills } 201ac6a4445SGunnar Mills } 202ac6a4445SGunnar Mills } 203ac6a4445SGunnar Mills } 204ac6a4445SGunnar Mills } 205ac6a4445SGunnar Mills } 206ac6a4445SGunnar Mills } 207ac6a4445SGunnar Mills } 208ac6a4445SGunnar Mills // In getCpuDataByInterface(), state and health are set 209ac6a4445SGunnar Mills // based on the present and functional status. If core 210ac6a4445SGunnar Mills // count is zero, then it has a higher precedence. 211ac6a4445SGunnar Mills if (slotPresent) 212ac6a4445SGunnar Mills { 213ac6a4445SGunnar Mills if (totalCores == 0) 214ac6a4445SGunnar Mills { 215ac6a4445SGunnar Mills // Slot is not populated, set status end return 216ac6a4445SGunnar Mills aResp->res.jsonValue["Status"]["State"] = "Absent"; 217ac6a4445SGunnar Mills aResp->res.jsonValue["Status"]["Health"] = "OK"; 218ac6a4445SGunnar Mills } 219ac6a4445SGunnar Mills aResp->res.jsonValue["TotalCores"] = totalCores; 220ac6a4445SGunnar Mills } 221ac6a4445SGunnar Mills return; 222ac6a4445SGunnar Mills }, 223ac6a4445SGunnar Mills service, "/xyz/openbmc_project/inventory", 224ac6a4445SGunnar Mills "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 225ac6a4445SGunnar Mills } 226ac6a4445SGunnar Mills 2278d1b46d7Szhanghch05 inline void getCpuAssetData(std::shared_ptr<bmcweb::AsyncResp> aResp, 228ac6a4445SGunnar Mills const std::string& service, 229ac6a4445SGunnar Mills const std::string& objPath) 230ac6a4445SGunnar Mills { 231ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "Get Cpu Asset Data"; 232ac6a4445SGunnar Mills crow::connections::systemBus->async_method_call( 233ac6a4445SGunnar Mills [objPath, aResp{std::move(aResp)}]( 234ac6a4445SGunnar Mills const boost::system::error_code ec, 235ac6a4445SGunnar Mills const boost::container::flat_map< 236ac6a4445SGunnar Mills std::string, std::variant<std::string, uint32_t, uint16_t, 237ac6a4445SGunnar Mills bool>>& properties) { 238ac6a4445SGunnar Mills if (ec) 239ac6a4445SGunnar Mills { 240ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "DBUS response error"; 241ac6a4445SGunnar Mills messages::internalError(aResp->res); 242ac6a4445SGunnar Mills return; 243ac6a4445SGunnar Mills } 244ac6a4445SGunnar Mills 245ac6a4445SGunnar Mills for (const auto& property : properties) 246ac6a4445SGunnar Mills { 247ac6a4445SGunnar Mills if (property.first == "SerialNumber") 248ac6a4445SGunnar Mills { 249ac6a4445SGunnar Mills const std::string* sn = 250ac6a4445SGunnar Mills std::get_if<std::string>(&property.second); 251ac6a4445SGunnar Mills if (sn != nullptr && !sn->empty()) 252ac6a4445SGunnar Mills { 253ac6a4445SGunnar Mills aResp->res.jsonValue["SerialNumber"] = *sn; 254ac6a4445SGunnar Mills } 255ac6a4445SGunnar Mills } 256ac6a4445SGunnar Mills else if (property.first == "Model") 257ac6a4445SGunnar Mills { 258ac6a4445SGunnar Mills const std::string* model = 259ac6a4445SGunnar Mills std::get_if<std::string>(&property.second); 260ac6a4445SGunnar Mills if (model != nullptr && !model->empty()) 261ac6a4445SGunnar Mills { 262ac6a4445SGunnar Mills aResp->res.jsonValue["Model"] = *model; 263ac6a4445SGunnar Mills } 264ac6a4445SGunnar Mills } 265ac6a4445SGunnar Mills else if (property.first == "Manufacturer") 266ac6a4445SGunnar Mills { 267ac6a4445SGunnar Mills 268ac6a4445SGunnar Mills const std::string* mfg = 269ac6a4445SGunnar Mills std::get_if<std::string>(&property.second); 270ac6a4445SGunnar Mills if (mfg != nullptr) 271ac6a4445SGunnar Mills { 272ac6a4445SGunnar Mills aResp->res.jsonValue["Manufacturer"] = *mfg; 273ac6a4445SGunnar Mills 274ac6a4445SGunnar Mills // Otherwise would be unexpected. 275ac6a4445SGunnar Mills if (mfg->find("Intel") != std::string::npos) 276ac6a4445SGunnar Mills { 277ac6a4445SGunnar Mills aResp->res.jsonValue["ProcessorArchitecture"] = 278ac6a4445SGunnar Mills "x86"; 279ac6a4445SGunnar Mills aResp->res.jsonValue["InstructionSet"] = "x86-64"; 280ac6a4445SGunnar Mills } 281ac6a4445SGunnar Mills else if (mfg->find("IBM") != std::string::npos) 282ac6a4445SGunnar Mills { 283ac6a4445SGunnar Mills aResp->res.jsonValue["ProcessorArchitecture"] = 284ac6a4445SGunnar Mills "Power"; 285ac6a4445SGunnar Mills aResp->res.jsonValue["InstructionSet"] = "PowerISA"; 286ac6a4445SGunnar Mills } 287ac6a4445SGunnar Mills } 288ac6a4445SGunnar Mills } 289cba4f448SSunnySrivastava1984 else if (property.first == "PartNumber") 290cba4f448SSunnySrivastava1984 { 291cba4f448SSunnySrivastava1984 const std::string* partNumber = 292cba4f448SSunnySrivastava1984 std::get_if<std::string>(&property.second); 293cba4f448SSunnySrivastava1984 294cba4f448SSunnySrivastava1984 if (partNumber == nullptr) 295cba4f448SSunnySrivastava1984 { 296cba4f448SSunnySrivastava1984 messages::internalError(aResp->res); 297cba4f448SSunnySrivastava1984 return; 298cba4f448SSunnySrivastava1984 } 299cba4f448SSunnySrivastava1984 aResp->res.jsonValue["PartNumber"] = *partNumber; 300cba4f448SSunnySrivastava1984 } 301cba4f448SSunnySrivastava1984 else if (property.first == "SparePartNumber") 302cba4f448SSunnySrivastava1984 { 303cba4f448SSunnySrivastava1984 const std::string* sparePartNumber = 304cba4f448SSunnySrivastava1984 std::get_if<std::string>(&property.second); 305cba4f448SSunnySrivastava1984 306cba4f448SSunnySrivastava1984 if (sparePartNumber == nullptr) 307cba4f448SSunnySrivastava1984 { 308cba4f448SSunnySrivastava1984 messages::internalError(aResp->res); 309cba4f448SSunnySrivastava1984 return; 310cba4f448SSunnySrivastava1984 } 311cba4f448SSunnySrivastava1984 aResp->res.jsonValue["SparePartNumber"] = *sparePartNumber; 312cba4f448SSunnySrivastava1984 } 313ac6a4445SGunnar Mills } 314ac6a4445SGunnar Mills }, 315ac6a4445SGunnar Mills service, objPath, "org.freedesktop.DBus.Properties", "GetAll", 316ac6a4445SGunnar Mills "xyz.openbmc_project.Inventory.Decorator.Asset"); 317ac6a4445SGunnar Mills } 318ac6a4445SGunnar Mills 3198d1b46d7Szhanghch05 inline void getCpuRevisionData(std::shared_ptr<bmcweb::AsyncResp> aResp, 320ac6a4445SGunnar Mills const std::string& service, 321ac6a4445SGunnar Mills const std::string& objPath) 322ac6a4445SGunnar Mills { 323ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "Get Cpu Revision Data"; 324ac6a4445SGunnar Mills crow::connections::systemBus->async_method_call( 325ac6a4445SGunnar Mills [objPath, aResp{std::move(aResp)}]( 326ac6a4445SGunnar Mills const boost::system::error_code ec, 327ac6a4445SGunnar Mills const boost::container::flat_map< 328ac6a4445SGunnar Mills std::string, std::variant<std::string, uint32_t, uint16_t, 329ac6a4445SGunnar Mills bool>>& properties) { 330ac6a4445SGunnar Mills if (ec) 331ac6a4445SGunnar Mills { 332ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "DBUS response error"; 333ac6a4445SGunnar Mills messages::internalError(aResp->res); 334ac6a4445SGunnar Mills return; 335ac6a4445SGunnar Mills } 336ac6a4445SGunnar Mills 337ac6a4445SGunnar Mills for (const auto& property : properties) 338ac6a4445SGunnar Mills { 339ac6a4445SGunnar Mills if (property.first == "Version") 340ac6a4445SGunnar Mills { 341ac6a4445SGunnar Mills const std::string* ver = 342ac6a4445SGunnar Mills std::get_if<std::string>(&property.second); 343ac6a4445SGunnar Mills if (ver != nullptr) 344ac6a4445SGunnar Mills { 345ac6a4445SGunnar Mills aResp->res.jsonValue["Version"] = *ver; 346ac6a4445SGunnar Mills } 347ac6a4445SGunnar Mills break; 348ac6a4445SGunnar Mills } 349ac6a4445SGunnar Mills } 350ac6a4445SGunnar Mills }, 351ac6a4445SGunnar Mills service, objPath, "org.freedesktop.DBus.Properties", "GetAll", 352ac6a4445SGunnar Mills "xyz.openbmc_project.Inventory.Decorator.Revision"); 353ac6a4445SGunnar Mills } 354ac6a4445SGunnar Mills 3558d1b46d7Szhanghch05 inline void getAcceleratorDataByService( 3568d1b46d7Szhanghch05 std::shared_ptr<bmcweb::AsyncResp> aResp, const std::string& acclrtrId, 3578d1b46d7Szhanghch05 const std::string& service, const std::string& objPath) 358ac6a4445SGunnar Mills { 359ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG 360ac6a4445SGunnar Mills << "Get available system Accelerator resources by service."; 361ac6a4445SGunnar Mills crow::connections::systemBus->async_method_call( 362ac6a4445SGunnar Mills [acclrtrId, aResp{std::move(aResp)}]( 363ac6a4445SGunnar Mills const boost::system::error_code ec, 364ac6a4445SGunnar Mills const boost::container::flat_map< 365ac6a4445SGunnar Mills std::string, std::variant<std::string, uint32_t, uint16_t, 366ac6a4445SGunnar Mills bool>>& properties) { 367ac6a4445SGunnar Mills if (ec) 368ac6a4445SGunnar Mills { 369ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "DBUS response error"; 370ac6a4445SGunnar Mills messages::internalError(aResp->res); 371ac6a4445SGunnar Mills return; 372ac6a4445SGunnar Mills } 373ac6a4445SGunnar Mills aResp->res.jsonValue["Id"] = acclrtrId; 374ac6a4445SGunnar Mills aResp->res.jsonValue["Name"] = "Processor"; 375ac6a4445SGunnar Mills const bool* accPresent = nullptr; 376ac6a4445SGunnar Mills const bool* accFunctional = nullptr; 377ac6a4445SGunnar Mills 378ac6a4445SGunnar Mills for (const auto& property : properties) 379ac6a4445SGunnar Mills { 380ac6a4445SGunnar Mills if (property.first == "Functional") 381ac6a4445SGunnar Mills { 382ac6a4445SGunnar Mills accFunctional = std::get_if<bool>(&property.second); 383ac6a4445SGunnar Mills } 384ac6a4445SGunnar Mills else if (property.first == "Present") 385ac6a4445SGunnar Mills { 386ac6a4445SGunnar Mills accPresent = std::get_if<bool>(&property.second); 387ac6a4445SGunnar Mills } 388ac6a4445SGunnar Mills } 389ac6a4445SGunnar Mills 390ac6a4445SGunnar Mills std::string state = "Enabled"; 391ac6a4445SGunnar Mills std::string health = "OK"; 392ac6a4445SGunnar Mills 393ac6a4445SGunnar Mills if (accPresent != nullptr && *accPresent == false) 394ac6a4445SGunnar Mills { 395ac6a4445SGunnar Mills state = "Absent"; 396ac6a4445SGunnar Mills } 397ac6a4445SGunnar Mills 398ac6a4445SGunnar Mills if ((accFunctional != nullptr) && (*accFunctional == false)) 399ac6a4445SGunnar Mills { 400ac6a4445SGunnar Mills if (state == "Enabled") 401ac6a4445SGunnar Mills { 402ac6a4445SGunnar Mills health = "Critical"; 403ac6a4445SGunnar Mills } 404ac6a4445SGunnar Mills } 405ac6a4445SGunnar Mills 406ac6a4445SGunnar Mills aResp->res.jsonValue["Status"]["State"] = state; 407ac6a4445SGunnar Mills aResp->res.jsonValue["Status"]["Health"] = health; 408ac6a4445SGunnar Mills aResp->res.jsonValue["ProcessorType"] = "Accelerator"; 409ac6a4445SGunnar Mills }, 410ac6a4445SGunnar Mills service, objPath, "org.freedesktop.DBus.Properties", "GetAll", ""); 411ac6a4445SGunnar Mills } 412ac6a4445SGunnar Mills 413dba0c291SJonathan Doman // OperatingConfig D-Bus Types 414dba0c291SJonathan Doman using TurboProfileProperty = std::vector<std::tuple<uint32_t, size_t>>; 415dba0c291SJonathan Doman using BaseSpeedPrioritySettingsProperty = 416dba0c291SJonathan Doman std::vector<std::tuple<uint32_t, std::vector<uint32_t>>>; 417dba0c291SJonathan Doman // uint32_t and size_t may or may not be the same type, requiring a dedup'd 418dba0c291SJonathan Doman // variant 419dba0c291SJonathan Doman using OperatingConfigProperties = std::vector<std::pair< 420dba0c291SJonathan Doman std::string, 421dba0c291SJonathan Doman sdbusplus::utility::dedup_variant<uint32_t, size_t, TurboProfileProperty, 422dba0c291SJonathan Doman BaseSpeedPrioritySettingsProperty>>>; 423dba0c291SJonathan Doman 424dba0c291SJonathan Doman /** 425dba0c291SJonathan Doman * Fill out the HighSpeedCoreIDs in a Processor resource from the given 426dba0c291SJonathan Doman * OperatingConfig D-Bus property. 427dba0c291SJonathan Doman * 428dba0c291SJonathan Doman * @param[in,out] aResp Async HTTP response. 429dba0c291SJonathan Doman * @param[in] baseSpeedSettings Full list of base speed priority groups, 430dba0c291SJonathan Doman * to use to determine the list of high 431dba0c291SJonathan Doman * speed cores. 432dba0c291SJonathan Doman */ 433dba0c291SJonathan Doman inline void highSpeedCoreIdsHandler( 4348d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& aResp, 435dba0c291SJonathan Doman const BaseSpeedPrioritySettingsProperty& baseSpeedSettings) 436dba0c291SJonathan Doman { 437dba0c291SJonathan Doman // The D-Bus property does not indicate which bucket is the "high 438dba0c291SJonathan Doman // priority" group, so let's discern that by looking for the one with 439dba0c291SJonathan Doman // highest base frequency. 440dba0c291SJonathan Doman auto highPriorityGroup = baseSpeedSettings.cend(); 441dba0c291SJonathan Doman uint32_t highestBaseSpeed = 0; 442dba0c291SJonathan Doman for (auto it = baseSpeedSettings.cbegin(); it != baseSpeedSettings.cend(); 443dba0c291SJonathan Doman ++it) 444dba0c291SJonathan Doman { 445dba0c291SJonathan Doman const uint32_t baseFreq = std::get<uint32_t>(*it); 446dba0c291SJonathan Doman if (baseFreq > highestBaseSpeed) 447dba0c291SJonathan Doman { 448dba0c291SJonathan Doman highestBaseSpeed = baseFreq; 449dba0c291SJonathan Doman highPriorityGroup = it; 450dba0c291SJonathan Doman } 451dba0c291SJonathan Doman } 452dba0c291SJonathan Doman 453dba0c291SJonathan Doman nlohmann::json& jsonCoreIds = aResp->res.jsonValue["HighSpeedCoreIDs"]; 454dba0c291SJonathan Doman jsonCoreIds = nlohmann::json::array(); 455dba0c291SJonathan Doman 456dba0c291SJonathan Doman // There may not be any entries in the D-Bus property, so only populate 457dba0c291SJonathan Doman // if there was actually something there. 458dba0c291SJonathan Doman if (highPriorityGroup != baseSpeedSettings.cend()) 459dba0c291SJonathan Doman { 460dba0c291SJonathan Doman jsonCoreIds = std::get<std::vector<uint32_t>>(*highPriorityGroup); 461dba0c291SJonathan Doman } 462dba0c291SJonathan Doman } 463dba0c291SJonathan Doman 464dba0c291SJonathan Doman /** 465dba0c291SJonathan Doman * Fill out OperatingConfig related items in a Processor resource by requesting 466dba0c291SJonathan Doman * data from the given D-Bus object. 467dba0c291SJonathan Doman * 468dba0c291SJonathan Doman * @param[in,out] aResp Async HTTP response. 469dba0c291SJonathan Doman * @param[in] cpuId CPU D-Bus name. 470dba0c291SJonathan Doman * @param[in] service D-Bus service to query. 471dba0c291SJonathan Doman * @param[in] objPath D-Bus object to query. 472dba0c291SJonathan Doman */ 4738d1b46d7Szhanghch05 inline void getCpuConfigData(const std::shared_ptr<bmcweb::AsyncResp>& aResp, 474dba0c291SJonathan Doman const std::string& cpuId, 475dba0c291SJonathan Doman const std::string& service, 476dba0c291SJonathan Doman const std::string& objPath) 477dba0c291SJonathan Doman { 478dba0c291SJonathan Doman BMCWEB_LOG_INFO << "Getting CPU operating configs for " << cpuId; 479dba0c291SJonathan Doman 480dba0c291SJonathan Doman // First, GetAll CurrentOperatingConfig properties on the object 481dba0c291SJonathan Doman crow::connections::systemBus->async_method_call( 482dba0c291SJonathan Doman [aResp, cpuId, service]( 483dba0c291SJonathan Doman const boost::system::error_code ec, 484dba0c291SJonathan Doman const std::vector< 485dba0c291SJonathan Doman std::pair<std::string, 486dba0c291SJonathan Doman std::variant<sdbusplus::message::object_path, bool>>>& 487dba0c291SJonathan Doman properties) { 488dba0c291SJonathan Doman if (ec) 489dba0c291SJonathan Doman { 490dba0c291SJonathan Doman BMCWEB_LOG_WARNING << "D-Bus error: " << ec << ", " 491dba0c291SJonathan Doman << ec.message(); 492dba0c291SJonathan Doman messages::internalError(aResp->res); 493dba0c291SJonathan Doman return; 494dba0c291SJonathan Doman } 495dba0c291SJonathan Doman 496dba0c291SJonathan Doman nlohmann::json& json = aResp->res.jsonValue; 497dba0c291SJonathan Doman 498dba0c291SJonathan Doman for (const auto& [dbusPropName, variantVal] : properties) 499dba0c291SJonathan Doman { 500dba0c291SJonathan Doman if (dbusPropName == "AppliedConfig") 501dba0c291SJonathan Doman { 502dba0c291SJonathan Doman const sdbusplus::message::object_path* dbusPathWrapper = 503dba0c291SJonathan Doman std::get_if<sdbusplus::message::object_path>( 504dba0c291SJonathan Doman &variantVal); 505dba0c291SJonathan Doman if (dbusPathWrapper == nullptr) 506dba0c291SJonathan Doman { 507dba0c291SJonathan Doman continue; 508dba0c291SJonathan Doman } 509dba0c291SJonathan Doman 510dba0c291SJonathan Doman const std::string& dbusPath = dbusPathWrapper->str; 511dba0c291SJonathan Doman std::string uri = "/redfish/v1/Systems/system/Processors/" + 512dba0c291SJonathan Doman cpuId + "/OperatingConfigs"; 513dba0c291SJonathan Doman json["OperatingConfigs"] = {{"@odata.id", uri}}; 514dba0c291SJonathan Doman 515dba0c291SJonathan Doman // Reuse the D-Bus config object name for the Redfish 516dba0c291SJonathan Doman // URI 517dba0c291SJonathan Doman size_t baseNamePos = dbusPath.rfind('/'); 518dba0c291SJonathan Doman if (baseNamePos == std::string::npos || 519dba0c291SJonathan Doman baseNamePos == (dbusPath.size() - 1)) 520dba0c291SJonathan Doman { 521dba0c291SJonathan Doman // If the AppliedConfig was somehow not a valid path, 522dba0c291SJonathan Doman // skip adding any more properties, since everything 523dba0c291SJonathan Doman // else is tied to this applied config. 524dba0c291SJonathan Doman messages::internalError(aResp->res); 525dba0c291SJonathan Doman break; 526dba0c291SJonathan Doman } 527dba0c291SJonathan Doman uri += '/'; 528dba0c291SJonathan Doman uri += dbusPath.substr(baseNamePos + 1); 529dba0c291SJonathan Doman json["AppliedOperatingConfig"] = {{"@odata.id", uri}}; 530dba0c291SJonathan Doman 531dba0c291SJonathan Doman // Once we found the current applied config, queue another 532dba0c291SJonathan Doman // request to read the base freq core ids out of that 533dba0c291SJonathan Doman // config. 534dba0c291SJonathan Doman crow::connections::systemBus->async_method_call( 535dba0c291SJonathan Doman [aResp]( 536dba0c291SJonathan Doman const boost::system::error_code ec, 537dba0c291SJonathan Doman const std::variant< 538dba0c291SJonathan Doman BaseSpeedPrioritySettingsProperty>& property) { 539dba0c291SJonathan Doman if (ec) 540dba0c291SJonathan Doman { 541dba0c291SJonathan Doman BMCWEB_LOG_WARNING 542dba0c291SJonathan Doman << "D-Bus Property Get error: " << ec; 543dba0c291SJonathan Doman messages::internalError(aResp->res); 544dba0c291SJonathan Doman return; 545dba0c291SJonathan Doman } 546dba0c291SJonathan Doman auto baseSpeedList = 547dba0c291SJonathan Doman std::get_if<BaseSpeedPrioritySettingsProperty>( 548dba0c291SJonathan Doman &property); 549dba0c291SJonathan Doman if (baseSpeedList != nullptr) 550dba0c291SJonathan Doman { 551dba0c291SJonathan Doman highSpeedCoreIdsHandler(aResp, *baseSpeedList); 552dba0c291SJonathan Doman } 553dba0c291SJonathan Doman }, 554dba0c291SJonathan Doman service, dbusPath, "org.freedesktop.DBus.Properties", 555dba0c291SJonathan Doman "Get", 556dba0c291SJonathan Doman "xyz.openbmc_project.Inventory.Item.Cpu." 557dba0c291SJonathan Doman "OperatingConfig", 558dba0c291SJonathan Doman "BaseSpeedPrioritySettings"); 559dba0c291SJonathan Doman } 560dba0c291SJonathan Doman else if (dbusPropName == "BaseSpeedPriorityEnabled") 561dba0c291SJonathan Doman { 562dba0c291SJonathan Doman const bool* state = std::get_if<bool>(&variantVal); 563dba0c291SJonathan Doman if (state != nullptr) 564dba0c291SJonathan Doman { 565dba0c291SJonathan Doman json["BaseSpeedPriorityState"] = 566dba0c291SJonathan Doman *state ? "Enabled" : "Disabled"; 567dba0c291SJonathan Doman } 568dba0c291SJonathan Doman } 569dba0c291SJonathan Doman } 570dba0c291SJonathan Doman }, 571dba0c291SJonathan Doman service, objPath, "org.freedesktop.DBus.Properties", "GetAll", 572dba0c291SJonathan Doman "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig"); 573dba0c291SJonathan Doman } 574dba0c291SJonathan Doman 575cba4f448SSunnySrivastava1984 /** 576cba4f448SSunnySrivastava1984 * @brief Fill out location info of a processor by 577cba4f448SSunnySrivastava1984 * requesting data from the given D-Bus object. 578cba4f448SSunnySrivastava1984 * 579cba4f448SSunnySrivastava1984 * @param[in,out] aResp Async HTTP response. 580cba4f448SSunnySrivastava1984 * @param[in] service D-Bus service to query. 581cba4f448SSunnySrivastava1984 * @param[in] objPath D-Bus object to query. 582cba4f448SSunnySrivastava1984 */ 5838d1b46d7Szhanghch05 inline void getCpuLocationCode(std::shared_ptr<bmcweb::AsyncResp> aResp, 584cba4f448SSunnySrivastava1984 const std::string& service, 585cba4f448SSunnySrivastava1984 const std::string& objPath) 586cba4f448SSunnySrivastava1984 { 587cba4f448SSunnySrivastava1984 BMCWEB_LOG_DEBUG << "Get Cpu Location Data"; 588cba4f448SSunnySrivastava1984 crow::connections::systemBus->async_method_call( 589cba4f448SSunnySrivastava1984 [objPath, 590cba4f448SSunnySrivastava1984 aResp{std::move(aResp)}](const boost::system::error_code ec, 591cba4f448SSunnySrivastava1984 const std::variant<std::string>& property) { 592cba4f448SSunnySrivastava1984 if (ec) 593cba4f448SSunnySrivastava1984 { 594cba4f448SSunnySrivastava1984 BMCWEB_LOG_DEBUG << "DBUS response error"; 595cba4f448SSunnySrivastava1984 messages::internalError(aResp->res); 596cba4f448SSunnySrivastava1984 return; 597cba4f448SSunnySrivastava1984 } 598cba4f448SSunnySrivastava1984 599cba4f448SSunnySrivastava1984 const std::string* value = std::get_if<std::string>(&property); 600cba4f448SSunnySrivastava1984 601cba4f448SSunnySrivastava1984 if (value == nullptr) 602cba4f448SSunnySrivastava1984 { 603cba4f448SSunnySrivastava1984 // illegal value 604cba4f448SSunnySrivastava1984 BMCWEB_LOG_DEBUG << "Location code value error"; 605cba4f448SSunnySrivastava1984 messages::internalError(aResp->res); 606cba4f448SSunnySrivastava1984 return; 607cba4f448SSunnySrivastava1984 } 608cba4f448SSunnySrivastava1984 609cba4f448SSunnySrivastava1984 aResp->res.jsonValue["Location"]["PartLocation"]["ServiceLabel"] = 610cba4f448SSunnySrivastava1984 *value; 611cba4f448SSunnySrivastava1984 }, 612cba4f448SSunnySrivastava1984 service, objPath, "org.freedesktop.DBus.Properties", "Get", 613cba4f448SSunnySrivastava1984 "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode"); 614cba4f448SSunnySrivastava1984 } 615cba4f448SSunnySrivastava1984 616c951448aSJonathan Doman /** 617c951448aSJonathan Doman * Find the D-Bus object representing the requested Processor, and call the 618c951448aSJonathan Doman * handler with the results. If matching object is not found, add 404 error to 619c951448aSJonathan Doman * response and don't call the handler. 620c951448aSJonathan Doman * 621c951448aSJonathan Doman * @param[in,out] resp Async HTTP response. 622c951448aSJonathan Doman * @param[in] processorId Redfish Processor Id. 623c951448aSJonathan Doman * @param[in] handler Callback to continue processing request upon 624c951448aSJonathan Doman * successfully finding object. 625c951448aSJonathan Doman */ 626c951448aSJonathan Doman template <typename Handler> 6278d1b46d7Szhanghch05 inline void getProcessorObject(const std::shared_ptr<bmcweb::AsyncResp>& resp, 628c951448aSJonathan Doman const std::string& processorId, 629c951448aSJonathan Doman Handler&& handler) 630ac6a4445SGunnar Mills { 631ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "Get available system processor resources."; 632ac6a4445SGunnar Mills 633c951448aSJonathan Doman // GetSubTree on all interfaces which provide info about a Processor 634ac6a4445SGunnar Mills crow::connections::systemBus->async_method_call( 635c951448aSJonathan Doman [resp, processorId, handler = std::forward<Handler>(handler)]( 636c951448aSJonathan Doman boost::system::error_code ec, 637c951448aSJonathan Doman const MapperGetSubTreeResponse& subtree) mutable { 638ac6a4445SGunnar Mills if (ec) 639ac6a4445SGunnar Mills { 640c951448aSJonathan Doman BMCWEB_LOG_DEBUG << "DBUS response error: " << ec; 641c951448aSJonathan Doman messages::internalError(resp->res); 642ac6a4445SGunnar Mills return; 643ac6a4445SGunnar Mills } 6442bab9831SJonathan Doman for (const auto& [objectPath, serviceMap] : subtree) 645ac6a4445SGunnar Mills { 6462bab9831SJonathan Doman // Ignore any objects which don't end with our desired cpu name 6472bab9831SJonathan Doman if (!boost::ends_with(objectPath, processorId)) 648ac6a4445SGunnar Mills { 6492bab9831SJonathan Doman continue; 650ac6a4445SGunnar Mills } 6512bab9831SJonathan Doman 652c951448aSJonathan Doman bool found = false; 653c951448aSJonathan Doman // Filter out objects that don't have the CPU-specific 654c951448aSJonathan Doman // interfaces to make sure we can return 404 on non-CPUs 655c951448aSJonathan Doman // (e.g. /redfish/../Processors/dimm0) 6562bab9831SJonathan Doman for (const auto& [serviceName, interfaceList] : serviceMap) 657ac6a4445SGunnar Mills { 658c951448aSJonathan Doman if (std::find_first_of( 659c951448aSJonathan Doman interfaceList.begin(), interfaceList.end(), 660c951448aSJonathan Doman processorInterfaces.begin(), 661c951448aSJonathan Doman processorInterfaces.end()) != interfaceList.end()) 6622bab9831SJonathan Doman { 663c951448aSJonathan Doman found = true; 664c951448aSJonathan Doman break; 665c951448aSJonathan Doman } 666c951448aSJonathan Doman } 667c951448aSJonathan Doman 668c951448aSJonathan Doman if (!found) 6692bab9831SJonathan Doman { 670c951448aSJonathan Doman continue; 671ac6a4445SGunnar Mills } 672c951448aSJonathan Doman 673c951448aSJonathan Doman // Process the first object which does match our cpu name and 674c951448aSJonathan Doman // required interfaces, and potentially ignore any other 675c951448aSJonathan Doman // matching objects. Assume all interfaces we want to process 676c951448aSJonathan Doman // must be on the same object path. 677c951448aSJonathan Doman 678c951448aSJonathan Doman handler(resp, processorId, objectPath, serviceMap); 679ac6a4445SGunnar Mills return; 680ac6a4445SGunnar Mills } 681c951448aSJonathan Doman messages::resourceNotFound(resp->res, "Processor", processorId); 682ac6a4445SGunnar Mills }, 683ac6a4445SGunnar Mills "xyz.openbmc_project.ObjectMapper", 684ac6a4445SGunnar Mills "/xyz/openbmc_project/object_mapper", 685ac6a4445SGunnar Mills "xyz.openbmc_project.ObjectMapper", "GetSubTree", 6862bab9831SJonathan Doman "/xyz/openbmc_project/inventory", 0, 687cba4f448SSunnySrivastava1984 std::array<const char*, 6>{ 6882bab9831SJonathan Doman "xyz.openbmc_project.Inventory.Decorator.Asset", 6892bab9831SJonathan Doman "xyz.openbmc_project.Inventory.Decorator.Revision", 6902bab9831SJonathan Doman "xyz.openbmc_project.Inventory.Item.Cpu", 691cba4f448SSunnySrivastava1984 "xyz.openbmc_project.Inventory.Decorator.LocationCode", 692dba0c291SJonathan Doman "xyz.openbmc_project.Inventory.Item.Accelerator", 693dba0c291SJonathan Doman "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig"}); 694ac6a4445SGunnar Mills } 695ac6a4445SGunnar Mills 6968d1b46d7Szhanghch05 inline void getProcessorData(const std::shared_ptr<bmcweb::AsyncResp>& aResp, 697c951448aSJonathan Doman const std::string& processorId, 698c951448aSJonathan Doman const std::string& objectPath, 699c951448aSJonathan Doman const MapperServiceMap& serviceMap) 700c951448aSJonathan Doman { 701c951448aSJonathan Doman for (const auto& [serviceName, interfaceList] : serviceMap) 702c951448aSJonathan Doman { 703c951448aSJonathan Doman for (const auto& interface : interfaceList) 704c951448aSJonathan Doman { 705c951448aSJonathan Doman if (interface == "xyz.openbmc_project.Inventory.Decorator.Asset") 706c951448aSJonathan Doman { 707c951448aSJonathan Doman getCpuAssetData(aResp, serviceName, objectPath); 708c951448aSJonathan Doman } 709c951448aSJonathan Doman else if (interface == "xyz.openbmc_project.Inventory." 710c951448aSJonathan Doman "Decorator.Revision") 711c951448aSJonathan Doman { 712c951448aSJonathan Doman getCpuRevisionData(aResp, serviceName, objectPath); 713c951448aSJonathan Doman } 714c951448aSJonathan Doman else if (interface == "xyz.openbmc_project.Inventory.Item.Cpu") 715c951448aSJonathan Doman { 716c951448aSJonathan Doman getCpuDataByService(aResp, processorId, serviceName, 717c951448aSJonathan Doman objectPath); 718c951448aSJonathan Doman } 719c951448aSJonathan Doman else if (interface == "xyz.openbmc_project.Inventory." 720c951448aSJonathan Doman "Item.Accelerator") 721c951448aSJonathan Doman { 722c951448aSJonathan Doman getAcceleratorDataByService(aResp, processorId, serviceName, 723c951448aSJonathan Doman objectPath); 724c951448aSJonathan Doman } 725c951448aSJonathan Doman else if (interface == "xyz.openbmc_project.Control.Processor." 726c951448aSJonathan Doman "CurrentOperatingConfig") 727c951448aSJonathan Doman { 728c951448aSJonathan Doman getCpuConfigData(aResp, processorId, serviceName, objectPath); 729c951448aSJonathan Doman } 730c951448aSJonathan Doman else if (interface == "xyz.openbmc_project.Inventory." 731c951448aSJonathan Doman "Decorator.LocationCode") 732c951448aSJonathan Doman { 733c951448aSJonathan Doman getCpuLocationCode(aResp, serviceName, objectPath); 734c951448aSJonathan Doman } 735c951448aSJonathan Doman } 736c951448aSJonathan Doman } 737c951448aSJonathan Doman } 738c951448aSJonathan Doman 739dba0c291SJonathan Doman /** 740dba0c291SJonathan Doman * Request all the properties for the given D-Bus object and fill out the 741dba0c291SJonathan Doman * related entries in the Redfish OperatingConfig response. 742dba0c291SJonathan Doman * 743dba0c291SJonathan Doman * @param[in,out] aResp Async HTTP response. 744dba0c291SJonathan Doman * @param[in] service D-Bus service name to query. 745dba0c291SJonathan Doman * @param[in] objPath D-Bus object to query. 746dba0c291SJonathan Doman */ 7478d1b46d7Szhanghch05 inline void 7488d1b46d7Szhanghch05 getOperatingConfigData(const std::shared_ptr<bmcweb::AsyncResp>& aResp, 749dba0c291SJonathan Doman const std::string& service, 750dba0c291SJonathan Doman const std::string& objPath) 751dba0c291SJonathan Doman { 752dba0c291SJonathan Doman crow::connections::systemBus->async_method_call( 753dba0c291SJonathan Doman [aResp](boost::system::error_code ec, 754dba0c291SJonathan Doman const OperatingConfigProperties& properties) { 755dba0c291SJonathan Doman if (ec) 756dba0c291SJonathan Doman { 757dba0c291SJonathan Doman BMCWEB_LOG_WARNING << "D-Bus error: " << ec << ", " 758dba0c291SJonathan Doman << ec.message(); 759dba0c291SJonathan Doman messages::internalError(aResp->res); 760dba0c291SJonathan Doman return; 761dba0c291SJonathan Doman } 762dba0c291SJonathan Doman 763dba0c291SJonathan Doman nlohmann::json& json = aResp->res.jsonValue; 764dba0c291SJonathan Doman for (const auto& [key, variant] : properties) 765dba0c291SJonathan Doman { 766dba0c291SJonathan Doman if (key == "AvailableCoreCount") 767dba0c291SJonathan Doman { 768dba0c291SJonathan Doman const size_t* cores = std::get_if<size_t>(&variant); 769dba0c291SJonathan Doman if (cores != nullptr) 770dba0c291SJonathan Doman { 771dba0c291SJonathan Doman json["TotalAvailableCoreCount"] = *cores; 772dba0c291SJonathan Doman } 773dba0c291SJonathan Doman } 774dba0c291SJonathan Doman else if (key == "BaseSpeed") 775dba0c291SJonathan Doman { 776dba0c291SJonathan Doman const uint32_t* speed = std::get_if<uint32_t>(&variant); 777dba0c291SJonathan Doman if (speed != nullptr) 778dba0c291SJonathan Doman { 779dba0c291SJonathan Doman json["BaseSpeedMHz"] = *speed; 780dba0c291SJonathan Doman } 781dba0c291SJonathan Doman } 782dba0c291SJonathan Doman else if (key == "MaxJunctionTemperature") 783dba0c291SJonathan Doman { 784dba0c291SJonathan Doman const uint32_t* temp = std::get_if<uint32_t>(&variant); 785dba0c291SJonathan Doman if (temp != nullptr) 786dba0c291SJonathan Doman { 787dba0c291SJonathan Doman json["MaxJunctionTemperatureCelsius"] = *temp; 788dba0c291SJonathan Doman } 789dba0c291SJonathan Doman } 790dba0c291SJonathan Doman else if (key == "MaxSpeed") 791dba0c291SJonathan Doman { 792dba0c291SJonathan Doman const uint32_t* speed = std::get_if<uint32_t>(&variant); 793dba0c291SJonathan Doman if (speed != nullptr) 794dba0c291SJonathan Doman { 795dba0c291SJonathan Doman json["MaxSpeedMHz"] = *speed; 796dba0c291SJonathan Doman } 797dba0c291SJonathan Doman } 798dba0c291SJonathan Doman else if (key == "PowerLimit") 799dba0c291SJonathan Doman { 800dba0c291SJonathan Doman const uint32_t* tdp = std::get_if<uint32_t>(&variant); 801dba0c291SJonathan Doman if (tdp != nullptr) 802dba0c291SJonathan Doman { 803dba0c291SJonathan Doman json["TDPWatts"] = *tdp; 804dba0c291SJonathan Doman } 805dba0c291SJonathan Doman } 806dba0c291SJonathan Doman else if (key == "TurboProfile") 807dba0c291SJonathan Doman { 808dba0c291SJonathan Doman const auto* turboList = 809dba0c291SJonathan Doman std::get_if<TurboProfileProperty>(&variant); 810dba0c291SJonathan Doman if (turboList == nullptr) 811dba0c291SJonathan Doman { 812dba0c291SJonathan Doman continue; 813dba0c291SJonathan Doman } 814dba0c291SJonathan Doman 815dba0c291SJonathan Doman nlohmann::json& turboArray = json["TurboProfile"]; 816dba0c291SJonathan Doman turboArray = nlohmann::json::array(); 817dba0c291SJonathan Doman for (const auto& [turboSpeed, coreCount] : *turboList) 818dba0c291SJonathan Doman { 819dba0c291SJonathan Doman turboArray.push_back({{"ActiveCoreCount", coreCount}, 820dba0c291SJonathan Doman {"MaxSpeedMHz", turboSpeed}}); 821dba0c291SJonathan Doman } 822dba0c291SJonathan Doman } 823dba0c291SJonathan Doman else if (key == "BaseSpeedPrioritySettings") 824dba0c291SJonathan Doman { 825dba0c291SJonathan Doman const auto* baseSpeedList = 826dba0c291SJonathan Doman std::get_if<BaseSpeedPrioritySettingsProperty>( 827dba0c291SJonathan Doman &variant); 828dba0c291SJonathan Doman if (baseSpeedList == nullptr) 829dba0c291SJonathan Doman { 830dba0c291SJonathan Doman continue; 831dba0c291SJonathan Doman } 832dba0c291SJonathan Doman 833dba0c291SJonathan Doman nlohmann::json& baseSpeedArray = 834dba0c291SJonathan Doman json["BaseSpeedPrioritySettings"]; 835dba0c291SJonathan Doman baseSpeedArray = nlohmann::json::array(); 836dba0c291SJonathan Doman for (const auto& [baseSpeed, coreList] : *baseSpeedList) 837dba0c291SJonathan Doman { 838dba0c291SJonathan Doman baseSpeedArray.push_back( 839dba0c291SJonathan Doman {{"CoreCount", coreList.size()}, 840dba0c291SJonathan Doman {"CoreIDs", coreList}, 841dba0c291SJonathan Doman {"BaseSpeedMHz", baseSpeed}}); 842dba0c291SJonathan Doman } 843dba0c291SJonathan Doman } 844dba0c291SJonathan Doman } 845dba0c291SJonathan Doman }, 846dba0c291SJonathan Doman service, objPath, "org.freedesktop.DBus.Properties", "GetAll", 847dba0c291SJonathan Doman "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig"); 848dba0c291SJonathan Doman } 849dba0c291SJonathan Doman 8503cde86f1SJonathan Doman /** 8513cde86f1SJonathan Doman * Handle the D-Bus response from attempting to set the CPU's AppliedConfig 8523cde86f1SJonathan Doman * property. Main task is to translate error messages into Redfish errors. 8533cde86f1SJonathan Doman * 8543cde86f1SJonathan Doman * @param[in,out] resp HTTP response. 8553cde86f1SJonathan Doman * @param[in] setPropVal Value which we attempted to set. 8563cde86f1SJonathan Doman * @param[in] ec D-Bus response error code. 8573cde86f1SJonathan Doman * @param[in] msg D-Bus response message. 8583cde86f1SJonathan Doman */ 8593cde86f1SJonathan Doman inline void 8603cde86f1SJonathan Doman handleAppliedConfigResponse(const std::shared_ptr<bmcweb::AsyncResp>& resp, 8613cde86f1SJonathan Doman const std::string& setPropVal, 8623cde86f1SJonathan Doman boost::system::error_code ec, 8633cde86f1SJonathan Doman const sdbusplus::message::message& msg) 8643cde86f1SJonathan Doman { 8653cde86f1SJonathan Doman if (!ec) 8663cde86f1SJonathan Doman { 8673cde86f1SJonathan Doman BMCWEB_LOG_DEBUG << "Set Property succeeded"; 8683cde86f1SJonathan Doman return; 8693cde86f1SJonathan Doman } 8703cde86f1SJonathan Doman 8713cde86f1SJonathan Doman BMCWEB_LOG_DEBUG << "Set Property failed: " << ec; 8723cde86f1SJonathan Doman 8733cde86f1SJonathan Doman const sd_bus_error* dbusError = msg.get_error(); 8743cde86f1SJonathan Doman if (dbusError == nullptr) 8753cde86f1SJonathan Doman { 8763cde86f1SJonathan Doman messages::internalError(resp->res); 8773cde86f1SJonathan Doman return; 8783cde86f1SJonathan Doman } 8793cde86f1SJonathan Doman 8803cde86f1SJonathan Doman // The asio error code doesn't know about our custom errors, so we have to 8813cde86f1SJonathan Doman // parse the error string. Some of these D-Bus -> Redfish translations are a 8823cde86f1SJonathan Doman // stretch, but it's good to try to communicate something vaguely useful. 8833cde86f1SJonathan Doman if (strcmp(dbusError->name, 8843cde86f1SJonathan Doman "xyz.openbmc_project.Common.Error.InvalidArgument") == 0) 8853cde86f1SJonathan Doman { 8863cde86f1SJonathan Doman // Service did not like the object_path we tried to set. 8873cde86f1SJonathan Doman messages::propertyValueIncorrect( 8883cde86f1SJonathan Doman resp->res, "AppliedOperatingConfig/@odata.id", setPropVal); 8893cde86f1SJonathan Doman } 8903cde86f1SJonathan Doman else if (strcmp(dbusError->name, 8913cde86f1SJonathan Doman "xyz.openbmc_project.Common.Error.NotAllowed") == 0) 8923cde86f1SJonathan Doman { 8933cde86f1SJonathan Doman // Service indicates we can never change the config for this processor. 8943cde86f1SJonathan Doman messages::propertyNotWritable(resp->res, "AppliedOperatingConfig"); 8953cde86f1SJonathan Doman } 8963cde86f1SJonathan Doman else if (strcmp(dbusError->name, 8973cde86f1SJonathan Doman "xyz.openbmc_project.Common.Error.Unavailable") == 0) 8983cde86f1SJonathan Doman { 8993cde86f1SJonathan Doman // Service indicates the config cannot be changed right now, but maybe 9003cde86f1SJonathan Doman // in a different system state. 9013cde86f1SJonathan Doman messages::resourceInStandby(resp->res); 9023cde86f1SJonathan Doman } 9033cde86f1SJonathan Doman else if (strcmp(dbusError->name, 9043cde86f1SJonathan Doman "xyz.openbmc_project.Common.Device.Error.WriteFailure") == 9053cde86f1SJonathan Doman 0) 9063cde86f1SJonathan Doman { 9073cde86f1SJonathan Doman // Service tried to change the config, but it failed. 9083cde86f1SJonathan Doman messages::operationFailed(resp->res); 9093cde86f1SJonathan Doman } 9103cde86f1SJonathan Doman else 9113cde86f1SJonathan Doman { 9123cde86f1SJonathan Doman messages::internalError(resp->res); 9133cde86f1SJonathan Doman } 9143cde86f1SJonathan Doman } 9153cde86f1SJonathan Doman 9163cde86f1SJonathan Doman /** 9173cde86f1SJonathan Doman * Handle the PATCH operation of the AppliedOperatingConfig property. Do basic 9183cde86f1SJonathan Doman * validation of the input data, and then set the D-Bus property. 9193cde86f1SJonathan Doman * 9203cde86f1SJonathan Doman * @param[in,out] resp Async HTTP response. 9213cde86f1SJonathan Doman * @param[in] processorId Processor's Id. 9223cde86f1SJonathan Doman * @param[in] appliedConfigUri New property value to apply. 9233cde86f1SJonathan Doman * @param[in] cpuObjectPath Path of CPU object to modify. 9243cde86f1SJonathan Doman * @param[in] serviceMap Service map for CPU object. 9253cde86f1SJonathan Doman */ 9263cde86f1SJonathan Doman inline void patchAppliedOperatingConfig( 9273cde86f1SJonathan Doman const std::shared_ptr<bmcweb::AsyncResp>& resp, 9283cde86f1SJonathan Doman const std::string& processorId, const std::string& appliedConfigUri, 9293cde86f1SJonathan Doman const std::string& cpuObjectPath, const MapperServiceMap& serviceMap) 9303cde86f1SJonathan Doman { 9313cde86f1SJonathan Doman // Check that the property even exists by checking for the interface 9323cde86f1SJonathan Doman const std::string* controlService = nullptr; 9333cde86f1SJonathan Doman for (const auto& [serviceName, interfaceList] : serviceMap) 9343cde86f1SJonathan Doman { 9353cde86f1SJonathan Doman if (std::find(interfaceList.begin(), interfaceList.end(), 9363cde86f1SJonathan Doman "xyz.openbmc_project.Control.Processor." 9373cde86f1SJonathan Doman "CurrentOperatingConfig") != interfaceList.end()) 9383cde86f1SJonathan Doman { 9393cde86f1SJonathan Doman controlService = &serviceName; 9403cde86f1SJonathan Doman break; 9413cde86f1SJonathan Doman } 9423cde86f1SJonathan Doman } 9433cde86f1SJonathan Doman 9443cde86f1SJonathan Doman if (controlService == nullptr) 9453cde86f1SJonathan Doman { 9463cde86f1SJonathan Doman messages::internalError(resp->res); 9473cde86f1SJonathan Doman return; 9483cde86f1SJonathan Doman } 9493cde86f1SJonathan Doman 9503cde86f1SJonathan Doman // Check that the config URI is a child of the cpu URI being patched. 9513cde86f1SJonathan Doman std::string expectedPrefix("/redfish/v1/Systems/system/Processors/"); 9523cde86f1SJonathan Doman expectedPrefix += processorId; 9533cde86f1SJonathan Doman expectedPrefix += "/OperatingConfigs/"; 9543cde86f1SJonathan Doman if (!boost::starts_with(appliedConfigUri, expectedPrefix) || 9553cde86f1SJonathan Doman expectedPrefix.size() == appliedConfigUri.size()) 9563cde86f1SJonathan Doman { 9573cde86f1SJonathan Doman messages::propertyValueIncorrect( 9583cde86f1SJonathan Doman resp->res, "AppliedOperatingConfig/@odata.id", appliedConfigUri); 9593cde86f1SJonathan Doman return; 9603cde86f1SJonathan Doman } 9613cde86f1SJonathan Doman 9623cde86f1SJonathan Doman // Generate the D-Bus path of the OperatingConfig object, by assuming it's a 9633cde86f1SJonathan Doman // direct child of the CPU object. 9643cde86f1SJonathan Doman // Strip the expectedPrefix from the config URI to get the "filename", and 9653cde86f1SJonathan Doman // append to the CPU's path. 9663cde86f1SJonathan Doman std::string configBaseName = appliedConfigUri.substr(expectedPrefix.size()); 9673cde86f1SJonathan Doman sdbusplus::message::object_path configPath(cpuObjectPath); 9683cde86f1SJonathan Doman configPath /= configBaseName; 9693cde86f1SJonathan Doman 9703cde86f1SJonathan Doman BMCWEB_LOG_INFO << "Setting config to " << configPath.str; 9713cde86f1SJonathan Doman 9723cde86f1SJonathan Doman // Set the property, with handler to check error responses 9733cde86f1SJonathan Doman crow::connections::systemBus->async_method_call( 9743cde86f1SJonathan Doman [resp, appliedConfigUri](boost::system::error_code ec, 9753cde86f1SJonathan Doman sdbusplus::message::message& msg) { 9763cde86f1SJonathan Doman handleAppliedConfigResponse(resp, appliedConfigUri, ec, msg); 9773cde86f1SJonathan Doman }, 9783cde86f1SJonathan Doman *controlService, cpuObjectPath, "org.freedesktop.DBus.Properties", 9793cde86f1SJonathan Doman "Set", "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig", 9803cde86f1SJonathan Doman "AppliedConfig", 9813cde86f1SJonathan Doman std::variant<sdbusplus::message::object_path>(std::move(configPath))); 9823cde86f1SJonathan Doman } 9833cde86f1SJonathan Doman 984*7e860f15SJohn Edward Broadbent inline void requestRoutesOperatingConfigCollection(App& app) 985dba0c291SJonathan Doman { 986dba0c291SJonathan Doman 987*7e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 988*7e860f15SJohn Edward Broadbent app, "/redfish/v1/Systems/system/Processors/<str>/OperatingConfigs/") 989*7e860f15SJohn Edward Broadbent .privileges({"Login"}) 990*7e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 991*7e860f15SJohn Edward Broadbent [](const crow::Request& req, 992*7e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 993*7e860f15SJohn Edward Broadbent const std::string& cpuName) { 9948d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.type"] = 995dba0c291SJonathan Doman "#OperatingConfigCollection.OperatingConfigCollection"; 9968d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.id"] = req.url; 997*7e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Name"] = 998*7e860f15SJohn Edward Broadbent "Operating Config Collection"; 999dba0c291SJonathan Doman 1000*7e860f15SJohn Edward Broadbent // First find the matching CPU object so we know how to 1001*7e860f15SJohn Edward Broadbent // constrain our search for related Config objects. 1002dba0c291SJonathan Doman crow::connections::systemBus->async_method_call( 1003*7e860f15SJohn Edward Broadbent [asyncResp, 1004*7e860f15SJohn Edward Broadbent cpuName](const boost::system::error_code ec, 1005dba0c291SJonathan Doman const std::vector<std::string>& objects) { 1006dba0c291SJonathan Doman if (ec) 1007dba0c291SJonathan Doman { 1008dba0c291SJonathan Doman BMCWEB_LOG_WARNING << "D-Bus error: " << ec << ", " 1009dba0c291SJonathan Doman << ec.message(); 1010dba0c291SJonathan Doman messages::internalError(asyncResp->res); 1011dba0c291SJonathan Doman return; 1012dba0c291SJonathan Doman } 1013dba0c291SJonathan Doman 1014dba0c291SJonathan Doman for (const std::string& object : objects) 1015dba0c291SJonathan Doman { 1016dba0c291SJonathan Doman if (!boost::ends_with(object, cpuName)) 1017dba0c291SJonathan Doman { 1018dba0c291SJonathan Doman continue; 1019dba0c291SJonathan Doman } 1020dba0c291SJonathan Doman 1021*7e860f15SJohn Edward Broadbent // Not expected that there will be multiple matching 1022*7e860f15SJohn Edward Broadbent // CPU objects, but if there are just use the first 1023*7e860f15SJohn Edward Broadbent // one. 1024dba0c291SJonathan Doman 1025*7e860f15SJohn Edward Broadbent // Use the common search routine to construct the 1026*7e860f15SJohn Edward Broadbent // Collection of all Config objects under this CPU. 1027dba0c291SJonathan Doman collection_util::getCollectionMembers( 1028dba0c291SJonathan Doman asyncResp, 1029*7e860f15SJohn Edward Broadbent "/redfish/v1/Systems/system/Processors/" + 1030*7e860f15SJohn Edward Broadbent cpuName + "/OperatingConfigs", 1031dba0c291SJonathan Doman {"xyz.openbmc_project.Inventory.Item.Cpu." 1032dba0c291SJonathan Doman "OperatingConfig"}, 1033dba0c291SJonathan Doman object.c_str()); 1034dba0c291SJonathan Doman return; 1035dba0c291SJonathan Doman } 1036dba0c291SJonathan Doman }, 1037dba0c291SJonathan Doman "xyz.openbmc_project.ObjectMapper", 1038dba0c291SJonathan Doman "/xyz/openbmc_project/object_mapper", 1039dba0c291SJonathan Doman "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", 1040dba0c291SJonathan Doman "/xyz/openbmc_project/inventory", 0, 1041*7e860f15SJohn Edward Broadbent std::array<const char*, 1>{ 1042*7e860f15SJohn Edward Broadbent "xyz.openbmc_project.Control.Processor." 1043dba0c291SJonathan Doman "CurrentOperatingConfig"}); 1044*7e860f15SJohn Edward Broadbent }); 1045dba0c291SJonathan Doman } 1046dba0c291SJonathan Doman 1047*7e860f15SJohn Edward Broadbent inline void requestRoutesOperatingConfig(App& app) 1048dba0c291SJonathan Doman { 1049*7e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 1050*7e860f15SJohn Edward Broadbent app, 1051*7e860f15SJohn Edward Broadbent "/redfish/v1/Systems/system/Processors/<str>/OperatingConfigs/<str>/") 1052*7e860f15SJohn Edward Broadbent .privileges({"Login"}) 1053*7e860f15SJohn Edward Broadbent .methods( 1054*7e860f15SJohn Edward Broadbent boost::beast::http::verb::get)([](const crow::Request& req, 1055*7e860f15SJohn Edward Broadbent const std::shared_ptr< 1056*7e860f15SJohn Edward Broadbent bmcweb::AsyncResp>& asyncResp, 1057*7e860f15SJohn Edward Broadbent const std::string& cpuName, 1058*7e860f15SJohn Edward Broadbent const std::string& configName) { 1059*7e860f15SJohn Edward Broadbent // Ask for all objects implementing OperatingConfig so we can search 1060*7e860f15SJohn Edward Broadbent // for one with a matching name 1061dba0c291SJonathan Doman crow::connections::systemBus->async_method_call( 1062dba0c291SJonathan Doman [asyncResp, cpuName, configName, 1063dba0c291SJonathan Doman reqUrl{req.url}](boost::system::error_code ec, 1064dba0c291SJonathan Doman const MapperGetSubTreeResponse& subtree) { 1065dba0c291SJonathan Doman if (ec) 1066dba0c291SJonathan Doman { 1067dba0c291SJonathan Doman BMCWEB_LOG_WARNING << "D-Bus error: " << ec << ", " 1068dba0c291SJonathan Doman << ec.message(); 1069dba0c291SJonathan Doman messages::internalError(asyncResp->res); 1070dba0c291SJonathan Doman return; 1071dba0c291SJonathan Doman } 1072*7e860f15SJohn Edward Broadbent const std::string expectedEnding = 1073*7e860f15SJohn Edward Broadbent cpuName + '/' + configName; 1074dba0c291SJonathan Doman for (const auto& [objectPath, serviceMap] : subtree) 1075dba0c291SJonathan Doman { 1076dba0c291SJonathan Doman // Ignore any configs without matching cpuX/configY 1077dba0c291SJonathan Doman if (!boost::ends_with(objectPath, expectedEnding) || 1078dba0c291SJonathan Doman serviceMap.empty()) 1079dba0c291SJonathan Doman { 1080dba0c291SJonathan Doman continue; 1081dba0c291SJonathan Doman } 1082dba0c291SJonathan Doman 1083dba0c291SJonathan Doman nlohmann::json& json = asyncResp->res.jsonValue; 1084dba0c291SJonathan Doman json["@odata.type"] = 1085dba0c291SJonathan Doman "#OperatingConfig.v1_0_0.OperatingConfig"; 1086dba0c291SJonathan Doman json["@odata.id"] = reqUrl; 1087dba0c291SJonathan Doman json["Name"] = "Processor Profile"; 1088dba0c291SJonathan Doman json["Id"] = configName; 1089dba0c291SJonathan Doman 1090dba0c291SJonathan Doman // Just use the first implementation of the object - not 1091*7e860f15SJohn Edward Broadbent // expected that there would be multiple matching 1092*7e860f15SJohn Edward Broadbent // services 1093*7e860f15SJohn Edward Broadbent getOperatingConfigData( 1094*7e860f15SJohn Edward Broadbent asyncResp, serviceMap.begin()->first, objectPath); 1095dba0c291SJonathan Doman return; 1096dba0c291SJonathan Doman } 1097*7e860f15SJohn Edward Broadbent messages::resourceNotFound(asyncResp->res, 1098*7e860f15SJohn Edward Broadbent "OperatingConfig", configName); 1099dba0c291SJonathan Doman }, 1100dba0c291SJonathan Doman "xyz.openbmc_project.ObjectMapper", 1101dba0c291SJonathan Doman "/xyz/openbmc_project/object_mapper", 1102dba0c291SJonathan Doman "xyz.openbmc_project.ObjectMapper", "GetSubTree", 1103dba0c291SJonathan Doman "/xyz/openbmc_project/inventory", 0, 1104dba0c291SJonathan Doman std::array<const char*, 1>{ 1105dba0c291SJonathan Doman "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig"}); 1106*7e860f15SJohn Edward Broadbent }); 1107ac6a4445SGunnar Mills } 1108ac6a4445SGunnar Mills 1109*7e860f15SJohn Edward Broadbent inline void requestRoutesProcessorCollection(App& app) 1110*7e860f15SJohn Edward Broadbent { 1111ac6a4445SGunnar Mills /** 1112ac6a4445SGunnar Mills * Functions triggers appropriate requests on DBus 1113ac6a4445SGunnar Mills */ 1114*7e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Processors/") 1115*7e860f15SJohn Edward Broadbent .privileges({"Login"}) 1116*7e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 1117*7e860f15SJohn Edward Broadbent [](const crow::Request&, 1118*7e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 11198d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.type"] = 1120ac6a4445SGunnar Mills "#ProcessorCollection.ProcessorCollection"; 11218d1b46d7Szhanghch05 asyncResp->res.jsonValue["Name"] = "Processor Collection"; 1122ac6a4445SGunnar Mills 11238d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.id"] = 11248d1b46d7Szhanghch05 "/redfish/v1/Systems/system/Processors"; 1125ac6a4445SGunnar Mills 112605030b8eSGunnar Mills collection_util::getCollectionMembers( 112705030b8eSGunnar Mills asyncResp, "/redfish/v1/Systems/system/Processors", 1128c951448aSJonathan Doman std::vector<const char*>(processorInterfaces.begin(), 1129c951448aSJonathan Doman processorInterfaces.end())); 1130*7e860f15SJohn Edward Broadbent }); 1131ac6a4445SGunnar Mills } 1132ac6a4445SGunnar Mills 1133*7e860f15SJohn Edward Broadbent inline void requestRoutesProcessor(App& app) 1134*7e860f15SJohn Edward Broadbent { 1135ac6a4445SGunnar Mills /** 1136ac6a4445SGunnar Mills * Functions triggers appropriate requests on DBus 1137ac6a4445SGunnar Mills */ 1138*7e860f15SJohn Edward Broadbent 1139*7e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Processors/<str>/") 1140*7e860f15SJohn Edward Broadbent .privileges({"Login"}) 1141*7e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 1142*7e860f15SJohn Edward Broadbent [](const crow::Request&, 1143*7e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1144*7e860f15SJohn Edward Broadbent const std::string& processorId) { 11458d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.type"] = 11468d1b46d7Szhanghch05 "#Processor.v1_11_0.Processor"; 11478d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.id"] = 1148ac6a4445SGunnar Mills "/redfish/v1/Systems/system/Processors/" + processorId; 1149ac6a4445SGunnar Mills 1150c951448aSJonathan Doman getProcessorObject(asyncResp, processorId, getProcessorData); 1151*7e860f15SJohn Edward Broadbent }); 11523cde86f1SJonathan Doman 1153*7e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Processors/<str>/") 1154*7e860f15SJohn Edward Broadbent .privileges({"ConfigureComponents"}) 1155*7e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::patch)( 1156*7e860f15SJohn Edward Broadbent [](const crow::Request& req, 1157*7e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1158*7e860f15SJohn Edward Broadbent const std::string& processorId) { 11593cde86f1SJonathan Doman std::optional<nlohmann::json> appliedConfigJson; 1160*7e860f15SJohn Edward Broadbent if (!json_util::readJson(req, asyncResp->res, 1161*7e860f15SJohn Edward Broadbent "AppliedOperatingConfig", 11623cde86f1SJonathan Doman appliedConfigJson)) 11633cde86f1SJonathan Doman { 11643cde86f1SJonathan Doman return; 11653cde86f1SJonathan Doman } 11663cde86f1SJonathan Doman 11673cde86f1SJonathan Doman std::string appliedConfigUri; 11683cde86f1SJonathan Doman if (appliedConfigJson) 11693cde86f1SJonathan Doman { 11703cde86f1SJonathan Doman if (!json_util::readJson(*appliedConfigJson, asyncResp->res, 11713cde86f1SJonathan Doman "@odata.id", appliedConfigUri)) 11723cde86f1SJonathan Doman { 11733cde86f1SJonathan Doman return; 11743cde86f1SJonathan Doman } 1175*7e860f15SJohn Edward Broadbent // Check for 404 and find matching D-Bus object, then run 1176*7e860f15SJohn Edward Broadbent // property patch handlers if that all succeeds. 11773cde86f1SJonathan Doman getProcessorObject( 1178*7e860f15SJohn Edward Broadbent asyncResp, processorId, 11793cde86f1SJonathan Doman [appliedConfigUri = std::move(appliedConfigUri)]( 11803cde86f1SJonathan Doman const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 11813cde86f1SJonathan Doman const std::string& processorId, 11823cde86f1SJonathan Doman const std::string& objectPath, 11833cde86f1SJonathan Doman const MapperServiceMap& serviceMap) { 11843cde86f1SJonathan Doman patchAppliedOperatingConfig(asyncResp, processorId, 1185*7e860f15SJohn Edward Broadbent appliedConfigUri, 1186*7e860f15SJohn Edward Broadbent objectPath, serviceMap); 11873cde86f1SJonathan Doman }); 11883cde86f1SJonathan Doman } 1189*7e860f15SJohn Edward Broadbent }); 11903cde86f1SJonathan Doman } 1191ac6a4445SGunnar Mills 1192ac6a4445SGunnar Mills } // namespace redfish 1193