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 20ac6a4445SGunnar Mills #include <boost/container/flat_map.hpp> 21ac6a4445SGunnar Mills #include <node.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 48*8d1b46d7Szhanghch05 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 53ac6a4445SGunnar Mills // Added for future purpose. Once present and functional attributes added 54ac6a4445SGunnar Mills // in busctl call, need to add actual logic to fetch original values. 55ac6a4445SGunnar Mills bool present = false; 56ac6a4445SGunnar Mills const bool functional = true; 57ac6a4445SGunnar Mills auto health = std::make_shared<HealthPopulate>(aResp); 58ac6a4445SGunnar Mills health->populate(); 59ac6a4445SGunnar Mills 60ac6a4445SGunnar Mills for (const auto& interface : cpuInterfacesProperties) 61ac6a4445SGunnar Mills { 62ac6a4445SGunnar Mills for (const auto& property : interface.second) 63ac6a4445SGunnar Mills { 64ac6a4445SGunnar Mills if (property.first == "CoreCount") 65ac6a4445SGunnar Mills { 66ac6a4445SGunnar Mills const uint16_t* coresCount = 67ac6a4445SGunnar Mills std::get_if<uint16_t>(&property.second); 68ac6a4445SGunnar Mills if (coresCount == nullptr) 69ac6a4445SGunnar Mills { 70ac6a4445SGunnar Mills // Important property not in desired type 71ac6a4445SGunnar Mills messages::internalError(aResp->res); 72ac6a4445SGunnar Mills return; 73ac6a4445SGunnar Mills } 74ac6a4445SGunnar Mills if (*coresCount == 0) 75ac6a4445SGunnar Mills { 76ac6a4445SGunnar Mills // Slot is not populated, set status end return 77ac6a4445SGunnar Mills aResp->res.jsonValue["Status"]["State"] = "Absent"; 78ac6a4445SGunnar Mills // HTTP Code will be set up automatically, just return 79ac6a4445SGunnar Mills return; 80ac6a4445SGunnar Mills } 81ac6a4445SGunnar Mills aResp->res.jsonValue["Status"]["State"] = "Enabled"; 82ac6a4445SGunnar Mills present = true; 83ac6a4445SGunnar Mills aResp->res.jsonValue["TotalCores"] = *coresCount; 84ac6a4445SGunnar Mills } 85dc3fa667SJonathan Doman else if (property.first == "MaxSpeedInMhz") 86dc3fa667SJonathan Doman { 87dc3fa667SJonathan Doman const uint32_t* value = std::get_if<uint32_t>(&property.second); 88dc3fa667SJonathan Doman if (value != nullptr) 89dc3fa667SJonathan Doman { 90dc3fa667SJonathan Doman aResp->res.jsonValue["MaxSpeedMHz"] = *value; 91dc3fa667SJonathan Doman } 92dc3fa667SJonathan Doman } 93ac6a4445SGunnar Mills else if (property.first == "Socket") 94ac6a4445SGunnar Mills { 95ac6a4445SGunnar Mills const std::string* value = 96ac6a4445SGunnar Mills std::get_if<std::string>(&property.second); 97ac6a4445SGunnar Mills if (value != nullptr) 98ac6a4445SGunnar Mills { 99ac6a4445SGunnar Mills aResp->res.jsonValue["Socket"] = *value; 100ac6a4445SGunnar Mills } 101ac6a4445SGunnar Mills } 102ac6a4445SGunnar Mills else if (property.first == "ThreadCount") 103ac6a4445SGunnar Mills { 104dc3fa667SJonathan Doman const uint16_t* value = std::get_if<uint16_t>(&property.second); 105ac6a4445SGunnar Mills if (value != nullptr) 106ac6a4445SGunnar Mills { 107ac6a4445SGunnar Mills aResp->res.jsonValue["TotalThreads"] = *value; 108ac6a4445SGunnar Mills } 109ac6a4445SGunnar Mills } 110ac6a4445SGunnar Mills else if (property.first == "Family") 111ac6a4445SGunnar Mills { 112ac6a4445SGunnar Mills const std::string* value = 113ac6a4445SGunnar Mills std::get_if<std::string>(&property.second); 114ac6a4445SGunnar Mills if (value != nullptr) 115ac6a4445SGunnar Mills { 116ac6a4445SGunnar Mills aResp->res.jsonValue["ProcessorId"]["EffectiveFamily"] = 117ac6a4445SGunnar Mills *value; 118ac6a4445SGunnar Mills } 119ac6a4445SGunnar Mills } 120ac6a4445SGunnar Mills else if (property.first == "Id") 121ac6a4445SGunnar Mills { 122ac6a4445SGunnar Mills const uint64_t* value = std::get_if<uint64_t>(&property.second); 123ac6a4445SGunnar Mills if (value != nullptr && *value != 0) 124ac6a4445SGunnar Mills { 125ac6a4445SGunnar Mills present = true; 126ac6a4445SGunnar Mills aResp->res 127ac6a4445SGunnar Mills .jsonValue["ProcessorId"]["IdentificationRegisters"] = 128ac6a4445SGunnar Mills boost::lexical_cast<std::string>(*value); 129ac6a4445SGunnar Mills } 130ac6a4445SGunnar Mills } 131ac6a4445SGunnar Mills } 132ac6a4445SGunnar Mills } 133ac6a4445SGunnar Mills 134ac6a4445SGunnar Mills if (present == false) 135ac6a4445SGunnar Mills { 136ac6a4445SGunnar Mills aResp->res.jsonValue["Status"]["State"] = "Absent"; 137ac6a4445SGunnar Mills aResp->res.jsonValue["Status"]["Health"] = "OK"; 138ac6a4445SGunnar Mills } 139ac6a4445SGunnar Mills else 140ac6a4445SGunnar Mills { 141ac6a4445SGunnar Mills aResp->res.jsonValue["Status"]["State"] = "Enabled"; 142ac6a4445SGunnar Mills if (functional) 143ac6a4445SGunnar Mills { 144ac6a4445SGunnar Mills aResp->res.jsonValue["Status"]["Health"] = "OK"; 145ac6a4445SGunnar Mills } 146ac6a4445SGunnar Mills else 147ac6a4445SGunnar Mills { 148ac6a4445SGunnar Mills aResp->res.jsonValue["Status"]["Health"] = "Critical"; 149ac6a4445SGunnar Mills } 150ac6a4445SGunnar Mills } 151ac6a4445SGunnar Mills 152ac6a4445SGunnar Mills return; 153ac6a4445SGunnar Mills } 154ac6a4445SGunnar Mills 155*8d1b46d7Szhanghch05 inline void getCpuDataByService(std::shared_ptr<bmcweb::AsyncResp> aResp, 156ac6a4445SGunnar Mills const std::string& cpuId, 157ac6a4445SGunnar Mills const std::string& service, 158ac6a4445SGunnar Mills const std::string& objPath) 159ac6a4445SGunnar Mills { 160ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "Get available system cpu resources by service."; 161ac6a4445SGunnar Mills 162ac6a4445SGunnar Mills crow::connections::systemBus->async_method_call( 163ac6a4445SGunnar Mills [cpuId, service, objPath, aResp{std::move(aResp)}]( 164ac6a4445SGunnar Mills const boost::system::error_code ec, 165ac6a4445SGunnar Mills const dbus::utility::ManagedObjectType& dbusData) { 166ac6a4445SGunnar Mills if (ec) 167ac6a4445SGunnar Mills { 168ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "DBUS response error"; 169ac6a4445SGunnar Mills messages::internalError(aResp->res); 170ac6a4445SGunnar Mills return; 171ac6a4445SGunnar Mills } 172ac6a4445SGunnar Mills aResp->res.jsonValue["Id"] = cpuId; 173ac6a4445SGunnar Mills aResp->res.jsonValue["Name"] = "Processor"; 174ac6a4445SGunnar Mills aResp->res.jsonValue["ProcessorType"] = "CPU"; 175ac6a4445SGunnar Mills 176ac6a4445SGunnar Mills bool slotPresent = false; 177ac6a4445SGunnar Mills std::string corePath = objPath + "/core"; 178ac6a4445SGunnar Mills size_t totalCores = 0; 179ac6a4445SGunnar Mills for (const auto& object : dbusData) 180ac6a4445SGunnar Mills { 181ac6a4445SGunnar Mills if (object.first.str == objPath) 182ac6a4445SGunnar Mills { 183ac6a4445SGunnar Mills getCpuDataByInterface(aResp, object.second); 184ac6a4445SGunnar Mills } 185ac6a4445SGunnar Mills else if (boost::starts_with(object.first.str, corePath)) 186ac6a4445SGunnar Mills { 187ac6a4445SGunnar Mills for (const auto& interface : object.second) 188ac6a4445SGunnar Mills { 189ac6a4445SGunnar Mills if (interface.first == 190ac6a4445SGunnar Mills "xyz.openbmc_project.Inventory.Item") 191ac6a4445SGunnar Mills { 192ac6a4445SGunnar Mills for (const auto& property : interface.second) 193ac6a4445SGunnar Mills { 194ac6a4445SGunnar Mills if (property.first == "Present") 195ac6a4445SGunnar Mills { 196ac6a4445SGunnar Mills const bool* present = 197ac6a4445SGunnar Mills std::get_if<bool>(&property.second); 198ac6a4445SGunnar Mills if (present != nullptr) 199ac6a4445SGunnar Mills { 200ac6a4445SGunnar Mills if (*present == true) 201ac6a4445SGunnar Mills { 202ac6a4445SGunnar Mills slotPresent = true; 203ac6a4445SGunnar Mills totalCores++; 204ac6a4445SGunnar Mills } 205ac6a4445SGunnar Mills } 206ac6a4445SGunnar Mills } 207ac6a4445SGunnar Mills } 208ac6a4445SGunnar Mills } 209ac6a4445SGunnar Mills } 210ac6a4445SGunnar Mills } 211ac6a4445SGunnar Mills } 212ac6a4445SGunnar Mills // In getCpuDataByInterface(), state and health are set 213ac6a4445SGunnar Mills // based on the present and functional status. If core 214ac6a4445SGunnar Mills // count is zero, then it has a higher precedence. 215ac6a4445SGunnar Mills if (slotPresent) 216ac6a4445SGunnar Mills { 217ac6a4445SGunnar Mills if (totalCores == 0) 218ac6a4445SGunnar Mills { 219ac6a4445SGunnar Mills // Slot is not populated, set status end return 220ac6a4445SGunnar Mills aResp->res.jsonValue["Status"]["State"] = "Absent"; 221ac6a4445SGunnar Mills aResp->res.jsonValue["Status"]["Health"] = "OK"; 222ac6a4445SGunnar Mills } 223ac6a4445SGunnar Mills aResp->res.jsonValue["TotalCores"] = totalCores; 224ac6a4445SGunnar Mills } 225ac6a4445SGunnar Mills return; 226ac6a4445SGunnar Mills }, 227ac6a4445SGunnar Mills service, "/xyz/openbmc_project/inventory", 228ac6a4445SGunnar Mills "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 229ac6a4445SGunnar Mills } 230ac6a4445SGunnar Mills 231*8d1b46d7Szhanghch05 inline void getCpuAssetData(std::shared_ptr<bmcweb::AsyncResp> aResp, 232ac6a4445SGunnar Mills const std::string& service, 233ac6a4445SGunnar Mills const std::string& objPath) 234ac6a4445SGunnar Mills { 235ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "Get Cpu Asset Data"; 236ac6a4445SGunnar Mills crow::connections::systemBus->async_method_call( 237ac6a4445SGunnar Mills [objPath, aResp{std::move(aResp)}]( 238ac6a4445SGunnar Mills const boost::system::error_code ec, 239ac6a4445SGunnar Mills const boost::container::flat_map< 240ac6a4445SGunnar Mills std::string, std::variant<std::string, uint32_t, uint16_t, 241ac6a4445SGunnar Mills bool>>& properties) { 242ac6a4445SGunnar Mills if (ec) 243ac6a4445SGunnar Mills { 244ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "DBUS response error"; 245ac6a4445SGunnar Mills messages::internalError(aResp->res); 246ac6a4445SGunnar Mills return; 247ac6a4445SGunnar Mills } 248ac6a4445SGunnar Mills 249ac6a4445SGunnar Mills for (const auto& property : properties) 250ac6a4445SGunnar Mills { 251ac6a4445SGunnar Mills if (property.first == "SerialNumber") 252ac6a4445SGunnar Mills { 253ac6a4445SGunnar Mills const std::string* sn = 254ac6a4445SGunnar Mills std::get_if<std::string>(&property.second); 255ac6a4445SGunnar Mills if (sn != nullptr && !sn->empty()) 256ac6a4445SGunnar Mills { 257ac6a4445SGunnar Mills aResp->res.jsonValue["SerialNumber"] = *sn; 258ac6a4445SGunnar Mills } 259ac6a4445SGunnar Mills } 260ac6a4445SGunnar Mills else if (property.first == "Model") 261ac6a4445SGunnar Mills { 262ac6a4445SGunnar Mills const std::string* model = 263ac6a4445SGunnar Mills std::get_if<std::string>(&property.second); 264ac6a4445SGunnar Mills if (model != nullptr && !model->empty()) 265ac6a4445SGunnar Mills { 266ac6a4445SGunnar Mills aResp->res.jsonValue["Model"] = *model; 267ac6a4445SGunnar Mills } 268ac6a4445SGunnar Mills } 269ac6a4445SGunnar Mills else if (property.first == "Manufacturer") 270ac6a4445SGunnar Mills { 271ac6a4445SGunnar Mills 272ac6a4445SGunnar Mills const std::string* mfg = 273ac6a4445SGunnar Mills std::get_if<std::string>(&property.second); 274ac6a4445SGunnar Mills if (mfg != nullptr) 275ac6a4445SGunnar Mills { 276ac6a4445SGunnar Mills aResp->res.jsonValue["Manufacturer"] = *mfg; 277ac6a4445SGunnar Mills 278ac6a4445SGunnar Mills // Otherwise would be unexpected. 279ac6a4445SGunnar Mills if (mfg->find("Intel") != std::string::npos) 280ac6a4445SGunnar Mills { 281ac6a4445SGunnar Mills aResp->res.jsonValue["ProcessorArchitecture"] = 282ac6a4445SGunnar Mills "x86"; 283ac6a4445SGunnar Mills aResp->res.jsonValue["InstructionSet"] = "x86-64"; 284ac6a4445SGunnar Mills } 285ac6a4445SGunnar Mills else if (mfg->find("IBM") != std::string::npos) 286ac6a4445SGunnar Mills { 287ac6a4445SGunnar Mills aResp->res.jsonValue["ProcessorArchitecture"] = 288ac6a4445SGunnar Mills "Power"; 289ac6a4445SGunnar Mills aResp->res.jsonValue["InstructionSet"] = "PowerISA"; 290ac6a4445SGunnar Mills } 291ac6a4445SGunnar Mills } 292ac6a4445SGunnar Mills } 293cba4f448SSunnySrivastava1984 else if (property.first == "PartNumber") 294cba4f448SSunnySrivastava1984 { 295cba4f448SSunnySrivastava1984 const std::string* partNumber = 296cba4f448SSunnySrivastava1984 std::get_if<std::string>(&property.second); 297cba4f448SSunnySrivastava1984 298cba4f448SSunnySrivastava1984 if (partNumber == nullptr) 299cba4f448SSunnySrivastava1984 { 300cba4f448SSunnySrivastava1984 messages::internalError(aResp->res); 301cba4f448SSunnySrivastava1984 return; 302cba4f448SSunnySrivastava1984 } 303cba4f448SSunnySrivastava1984 aResp->res.jsonValue["PartNumber"] = *partNumber; 304cba4f448SSunnySrivastava1984 } 305cba4f448SSunnySrivastava1984 else if (property.first == "SparePartNumber") 306cba4f448SSunnySrivastava1984 { 307cba4f448SSunnySrivastava1984 const std::string* sparePartNumber = 308cba4f448SSunnySrivastava1984 std::get_if<std::string>(&property.second); 309cba4f448SSunnySrivastava1984 310cba4f448SSunnySrivastava1984 if (sparePartNumber == nullptr) 311cba4f448SSunnySrivastava1984 { 312cba4f448SSunnySrivastava1984 messages::internalError(aResp->res); 313cba4f448SSunnySrivastava1984 return; 314cba4f448SSunnySrivastava1984 } 315cba4f448SSunnySrivastava1984 aResp->res.jsonValue["SparePartNumber"] = *sparePartNumber; 316cba4f448SSunnySrivastava1984 } 317ac6a4445SGunnar Mills } 318ac6a4445SGunnar Mills }, 319ac6a4445SGunnar Mills service, objPath, "org.freedesktop.DBus.Properties", "GetAll", 320ac6a4445SGunnar Mills "xyz.openbmc_project.Inventory.Decorator.Asset"); 321ac6a4445SGunnar Mills } 322ac6a4445SGunnar Mills 323*8d1b46d7Szhanghch05 inline void getCpuRevisionData(std::shared_ptr<bmcweb::AsyncResp> aResp, 324ac6a4445SGunnar Mills const std::string& service, 325ac6a4445SGunnar Mills const std::string& objPath) 326ac6a4445SGunnar Mills { 327ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "Get Cpu Revision Data"; 328ac6a4445SGunnar Mills crow::connections::systemBus->async_method_call( 329ac6a4445SGunnar Mills [objPath, aResp{std::move(aResp)}]( 330ac6a4445SGunnar Mills const boost::system::error_code ec, 331ac6a4445SGunnar Mills const boost::container::flat_map< 332ac6a4445SGunnar Mills std::string, std::variant<std::string, uint32_t, uint16_t, 333ac6a4445SGunnar Mills bool>>& properties) { 334ac6a4445SGunnar Mills if (ec) 335ac6a4445SGunnar Mills { 336ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "DBUS response error"; 337ac6a4445SGunnar Mills messages::internalError(aResp->res); 338ac6a4445SGunnar Mills return; 339ac6a4445SGunnar Mills } 340ac6a4445SGunnar Mills 341ac6a4445SGunnar Mills for (const auto& property : properties) 342ac6a4445SGunnar Mills { 343ac6a4445SGunnar Mills if (property.first == "Version") 344ac6a4445SGunnar Mills { 345ac6a4445SGunnar Mills const std::string* ver = 346ac6a4445SGunnar Mills std::get_if<std::string>(&property.second); 347ac6a4445SGunnar Mills if (ver != nullptr) 348ac6a4445SGunnar Mills { 349ac6a4445SGunnar Mills aResp->res.jsonValue["Version"] = *ver; 350ac6a4445SGunnar Mills } 351ac6a4445SGunnar Mills break; 352ac6a4445SGunnar Mills } 353ac6a4445SGunnar Mills } 354ac6a4445SGunnar Mills }, 355ac6a4445SGunnar Mills service, objPath, "org.freedesktop.DBus.Properties", "GetAll", 356ac6a4445SGunnar Mills "xyz.openbmc_project.Inventory.Decorator.Revision"); 357ac6a4445SGunnar Mills } 358ac6a4445SGunnar Mills 359*8d1b46d7Szhanghch05 inline void getAcceleratorDataByService( 360*8d1b46d7Szhanghch05 std::shared_ptr<bmcweb::AsyncResp> aResp, const std::string& acclrtrId, 361*8d1b46d7Szhanghch05 const std::string& service, const std::string& objPath) 362ac6a4445SGunnar Mills { 363ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG 364ac6a4445SGunnar Mills << "Get available system Accelerator resources by service."; 365ac6a4445SGunnar Mills crow::connections::systemBus->async_method_call( 366ac6a4445SGunnar Mills [acclrtrId, aResp{std::move(aResp)}]( 367ac6a4445SGunnar Mills const boost::system::error_code ec, 368ac6a4445SGunnar Mills const boost::container::flat_map< 369ac6a4445SGunnar Mills std::string, std::variant<std::string, uint32_t, uint16_t, 370ac6a4445SGunnar Mills bool>>& properties) { 371ac6a4445SGunnar Mills if (ec) 372ac6a4445SGunnar Mills { 373ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "DBUS response error"; 374ac6a4445SGunnar Mills messages::internalError(aResp->res); 375ac6a4445SGunnar Mills return; 376ac6a4445SGunnar Mills } 377ac6a4445SGunnar Mills aResp->res.jsonValue["Id"] = acclrtrId; 378ac6a4445SGunnar Mills aResp->res.jsonValue["Name"] = "Processor"; 379ac6a4445SGunnar Mills const bool* accPresent = nullptr; 380ac6a4445SGunnar Mills const bool* accFunctional = nullptr; 381ac6a4445SGunnar Mills 382ac6a4445SGunnar Mills for (const auto& property : properties) 383ac6a4445SGunnar Mills { 384ac6a4445SGunnar Mills if (property.first == "Functional") 385ac6a4445SGunnar Mills { 386ac6a4445SGunnar Mills accFunctional = std::get_if<bool>(&property.second); 387ac6a4445SGunnar Mills } 388ac6a4445SGunnar Mills else if (property.first == "Present") 389ac6a4445SGunnar Mills { 390ac6a4445SGunnar Mills accPresent = std::get_if<bool>(&property.second); 391ac6a4445SGunnar Mills } 392ac6a4445SGunnar Mills } 393ac6a4445SGunnar Mills 394ac6a4445SGunnar Mills std::string state = "Enabled"; 395ac6a4445SGunnar Mills std::string health = "OK"; 396ac6a4445SGunnar Mills 397ac6a4445SGunnar Mills if (accPresent != nullptr && *accPresent == false) 398ac6a4445SGunnar Mills { 399ac6a4445SGunnar Mills state = "Absent"; 400ac6a4445SGunnar Mills } 401ac6a4445SGunnar Mills 402ac6a4445SGunnar Mills if ((accFunctional != nullptr) && (*accFunctional == false)) 403ac6a4445SGunnar Mills { 404ac6a4445SGunnar Mills if (state == "Enabled") 405ac6a4445SGunnar Mills { 406ac6a4445SGunnar Mills health = "Critical"; 407ac6a4445SGunnar Mills } 408ac6a4445SGunnar Mills } 409ac6a4445SGunnar Mills 410ac6a4445SGunnar Mills aResp->res.jsonValue["Status"]["State"] = state; 411ac6a4445SGunnar Mills aResp->res.jsonValue["Status"]["Health"] = health; 412ac6a4445SGunnar Mills aResp->res.jsonValue["ProcessorType"] = "Accelerator"; 413ac6a4445SGunnar Mills }, 414ac6a4445SGunnar Mills service, objPath, "org.freedesktop.DBus.Properties", "GetAll", ""); 415ac6a4445SGunnar Mills } 416ac6a4445SGunnar Mills 417dba0c291SJonathan Doman // OperatingConfig D-Bus Types 418dba0c291SJonathan Doman using TurboProfileProperty = std::vector<std::tuple<uint32_t, size_t>>; 419dba0c291SJonathan Doman using BaseSpeedPrioritySettingsProperty = 420dba0c291SJonathan Doman std::vector<std::tuple<uint32_t, std::vector<uint32_t>>>; 421dba0c291SJonathan Doman // uint32_t and size_t may or may not be the same type, requiring a dedup'd 422dba0c291SJonathan Doman // variant 423dba0c291SJonathan Doman using OperatingConfigProperties = std::vector<std::pair< 424dba0c291SJonathan Doman std::string, 425dba0c291SJonathan Doman sdbusplus::utility::dedup_variant<uint32_t, size_t, TurboProfileProperty, 426dba0c291SJonathan Doman BaseSpeedPrioritySettingsProperty>>>; 427dba0c291SJonathan Doman 428dba0c291SJonathan Doman /** 429dba0c291SJonathan Doman * Fill out the HighSpeedCoreIDs in a Processor resource from the given 430dba0c291SJonathan Doman * OperatingConfig D-Bus property. 431dba0c291SJonathan Doman * 432dba0c291SJonathan Doman * @param[in,out] aResp Async HTTP response. 433dba0c291SJonathan Doman * @param[in] baseSpeedSettings Full list of base speed priority groups, 434dba0c291SJonathan Doman * to use to determine the list of high 435dba0c291SJonathan Doman * speed cores. 436dba0c291SJonathan Doman */ 437dba0c291SJonathan Doman inline void highSpeedCoreIdsHandler( 438*8d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& aResp, 439dba0c291SJonathan Doman const BaseSpeedPrioritySettingsProperty& baseSpeedSettings) 440dba0c291SJonathan Doman { 441dba0c291SJonathan Doman // The D-Bus property does not indicate which bucket is the "high 442dba0c291SJonathan Doman // priority" group, so let's discern that by looking for the one with 443dba0c291SJonathan Doman // highest base frequency. 444dba0c291SJonathan Doman auto highPriorityGroup = baseSpeedSettings.cend(); 445dba0c291SJonathan Doman uint32_t highestBaseSpeed = 0; 446dba0c291SJonathan Doman for (auto it = baseSpeedSettings.cbegin(); it != baseSpeedSettings.cend(); 447dba0c291SJonathan Doman ++it) 448dba0c291SJonathan Doman { 449dba0c291SJonathan Doman const uint32_t baseFreq = std::get<uint32_t>(*it); 450dba0c291SJonathan Doman if (baseFreq > highestBaseSpeed) 451dba0c291SJonathan Doman { 452dba0c291SJonathan Doman highestBaseSpeed = baseFreq; 453dba0c291SJonathan Doman highPriorityGroup = it; 454dba0c291SJonathan Doman } 455dba0c291SJonathan Doman } 456dba0c291SJonathan Doman 457dba0c291SJonathan Doman nlohmann::json& jsonCoreIds = aResp->res.jsonValue["HighSpeedCoreIDs"]; 458dba0c291SJonathan Doman jsonCoreIds = nlohmann::json::array(); 459dba0c291SJonathan Doman 460dba0c291SJonathan Doman // There may not be any entries in the D-Bus property, so only populate 461dba0c291SJonathan Doman // if there was actually something there. 462dba0c291SJonathan Doman if (highPriorityGroup != baseSpeedSettings.cend()) 463dba0c291SJonathan Doman { 464dba0c291SJonathan Doman jsonCoreIds = std::get<std::vector<uint32_t>>(*highPriorityGroup); 465dba0c291SJonathan Doman } 466dba0c291SJonathan Doman } 467dba0c291SJonathan Doman 468dba0c291SJonathan Doman /** 469dba0c291SJonathan Doman * Fill out OperatingConfig related items in a Processor resource by requesting 470dba0c291SJonathan Doman * data from the given D-Bus object. 471dba0c291SJonathan Doman * 472dba0c291SJonathan Doman * @param[in,out] aResp Async HTTP response. 473dba0c291SJonathan Doman * @param[in] cpuId CPU D-Bus name. 474dba0c291SJonathan Doman * @param[in] service D-Bus service to query. 475dba0c291SJonathan Doman * @param[in] objPath D-Bus object to query. 476dba0c291SJonathan Doman */ 477*8d1b46d7Szhanghch05 inline void getCpuConfigData(const std::shared_ptr<bmcweb::AsyncResp>& aResp, 478dba0c291SJonathan Doman const std::string& cpuId, 479dba0c291SJonathan Doman const std::string& service, 480dba0c291SJonathan Doman const std::string& objPath) 481dba0c291SJonathan Doman { 482dba0c291SJonathan Doman BMCWEB_LOG_INFO << "Getting CPU operating configs for " << cpuId; 483dba0c291SJonathan Doman 484dba0c291SJonathan Doman // First, GetAll CurrentOperatingConfig properties on the object 485dba0c291SJonathan Doman crow::connections::systemBus->async_method_call( 486dba0c291SJonathan Doman [aResp, cpuId, service]( 487dba0c291SJonathan Doman const boost::system::error_code ec, 488dba0c291SJonathan Doman const std::vector< 489dba0c291SJonathan Doman std::pair<std::string, 490dba0c291SJonathan Doman std::variant<sdbusplus::message::object_path, bool>>>& 491dba0c291SJonathan Doman properties) { 492dba0c291SJonathan Doman if (ec) 493dba0c291SJonathan Doman { 494dba0c291SJonathan Doman BMCWEB_LOG_WARNING << "D-Bus error: " << ec << ", " 495dba0c291SJonathan Doman << ec.message(); 496dba0c291SJonathan Doman messages::internalError(aResp->res); 497dba0c291SJonathan Doman return; 498dba0c291SJonathan Doman } 499dba0c291SJonathan Doman 500dba0c291SJonathan Doman nlohmann::json& json = aResp->res.jsonValue; 501dba0c291SJonathan Doman 502dba0c291SJonathan Doman for (const auto& [dbusPropName, variantVal] : properties) 503dba0c291SJonathan Doman { 504dba0c291SJonathan Doman if (dbusPropName == "AppliedConfig") 505dba0c291SJonathan Doman { 506dba0c291SJonathan Doman const sdbusplus::message::object_path* dbusPathWrapper = 507dba0c291SJonathan Doman std::get_if<sdbusplus::message::object_path>( 508dba0c291SJonathan Doman &variantVal); 509dba0c291SJonathan Doman if (dbusPathWrapper == nullptr) 510dba0c291SJonathan Doman { 511dba0c291SJonathan Doman continue; 512dba0c291SJonathan Doman } 513dba0c291SJonathan Doman 514dba0c291SJonathan Doman const std::string& dbusPath = dbusPathWrapper->str; 515dba0c291SJonathan Doman std::string uri = "/redfish/v1/Systems/system/Processors/" + 516dba0c291SJonathan Doman cpuId + "/OperatingConfigs"; 517dba0c291SJonathan Doman json["OperatingConfigs"] = {{"@odata.id", uri}}; 518dba0c291SJonathan Doman 519dba0c291SJonathan Doman // Reuse the D-Bus config object name for the Redfish 520dba0c291SJonathan Doman // URI 521dba0c291SJonathan Doman size_t baseNamePos = dbusPath.rfind('/'); 522dba0c291SJonathan Doman if (baseNamePos == std::string::npos || 523dba0c291SJonathan Doman baseNamePos == (dbusPath.size() - 1)) 524dba0c291SJonathan Doman { 525dba0c291SJonathan Doman // If the AppliedConfig was somehow not a valid path, 526dba0c291SJonathan Doman // skip adding any more properties, since everything 527dba0c291SJonathan Doman // else is tied to this applied config. 528dba0c291SJonathan Doman messages::internalError(aResp->res); 529dba0c291SJonathan Doman break; 530dba0c291SJonathan Doman } 531dba0c291SJonathan Doman uri += '/'; 532dba0c291SJonathan Doman uri += dbusPath.substr(baseNamePos + 1); 533dba0c291SJonathan Doman json["AppliedOperatingConfig"] = {{"@odata.id", uri}}; 534dba0c291SJonathan Doman 535dba0c291SJonathan Doman // Once we found the current applied config, queue another 536dba0c291SJonathan Doman // request to read the base freq core ids out of that 537dba0c291SJonathan Doman // config. 538dba0c291SJonathan Doman crow::connections::systemBus->async_method_call( 539dba0c291SJonathan Doman [aResp]( 540dba0c291SJonathan Doman const boost::system::error_code ec, 541dba0c291SJonathan Doman const std::variant< 542dba0c291SJonathan Doman BaseSpeedPrioritySettingsProperty>& property) { 543dba0c291SJonathan Doman if (ec) 544dba0c291SJonathan Doman { 545dba0c291SJonathan Doman BMCWEB_LOG_WARNING 546dba0c291SJonathan Doman << "D-Bus Property Get error: " << ec; 547dba0c291SJonathan Doman messages::internalError(aResp->res); 548dba0c291SJonathan Doman return; 549dba0c291SJonathan Doman } 550dba0c291SJonathan Doman auto baseSpeedList = 551dba0c291SJonathan Doman std::get_if<BaseSpeedPrioritySettingsProperty>( 552dba0c291SJonathan Doman &property); 553dba0c291SJonathan Doman if (baseSpeedList != nullptr) 554dba0c291SJonathan Doman { 555dba0c291SJonathan Doman highSpeedCoreIdsHandler(aResp, *baseSpeedList); 556dba0c291SJonathan Doman } 557dba0c291SJonathan Doman }, 558dba0c291SJonathan Doman service, dbusPath, "org.freedesktop.DBus.Properties", 559dba0c291SJonathan Doman "Get", 560dba0c291SJonathan Doman "xyz.openbmc_project.Inventory.Item.Cpu." 561dba0c291SJonathan Doman "OperatingConfig", 562dba0c291SJonathan Doman "BaseSpeedPrioritySettings"); 563dba0c291SJonathan Doman } 564dba0c291SJonathan Doman else if (dbusPropName == "BaseSpeedPriorityEnabled") 565dba0c291SJonathan Doman { 566dba0c291SJonathan Doman const bool* state = std::get_if<bool>(&variantVal); 567dba0c291SJonathan Doman if (state != nullptr) 568dba0c291SJonathan Doman { 569dba0c291SJonathan Doman json["BaseSpeedPriorityState"] = 570dba0c291SJonathan Doman *state ? "Enabled" : "Disabled"; 571dba0c291SJonathan Doman } 572dba0c291SJonathan Doman } 573dba0c291SJonathan Doman } 574dba0c291SJonathan Doman }, 575dba0c291SJonathan Doman service, objPath, "org.freedesktop.DBus.Properties", "GetAll", 576dba0c291SJonathan Doman "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig"); 577dba0c291SJonathan Doman } 578dba0c291SJonathan Doman 579cba4f448SSunnySrivastava1984 /** 580cba4f448SSunnySrivastava1984 * @brief Fill out location info of a processor by 581cba4f448SSunnySrivastava1984 * requesting data from the given D-Bus object. 582cba4f448SSunnySrivastava1984 * 583cba4f448SSunnySrivastava1984 * @param[in,out] aResp Async HTTP response. 584cba4f448SSunnySrivastava1984 * @param[in] service D-Bus service to query. 585cba4f448SSunnySrivastava1984 * @param[in] objPath D-Bus object to query. 586cba4f448SSunnySrivastava1984 */ 587*8d1b46d7Szhanghch05 inline void getCpuLocationCode(std::shared_ptr<bmcweb::AsyncResp> aResp, 588cba4f448SSunnySrivastava1984 const std::string& service, 589cba4f448SSunnySrivastava1984 const std::string& objPath) 590cba4f448SSunnySrivastava1984 { 591cba4f448SSunnySrivastava1984 BMCWEB_LOG_DEBUG << "Get Cpu Location Data"; 592cba4f448SSunnySrivastava1984 crow::connections::systemBus->async_method_call( 593cba4f448SSunnySrivastava1984 [objPath, 594cba4f448SSunnySrivastava1984 aResp{std::move(aResp)}](const boost::system::error_code ec, 595cba4f448SSunnySrivastava1984 const std::variant<std::string>& property) { 596cba4f448SSunnySrivastava1984 if (ec) 597cba4f448SSunnySrivastava1984 { 598cba4f448SSunnySrivastava1984 BMCWEB_LOG_DEBUG << "DBUS response error"; 599cba4f448SSunnySrivastava1984 messages::internalError(aResp->res); 600cba4f448SSunnySrivastava1984 return; 601cba4f448SSunnySrivastava1984 } 602cba4f448SSunnySrivastava1984 603cba4f448SSunnySrivastava1984 const std::string* value = std::get_if<std::string>(&property); 604cba4f448SSunnySrivastava1984 605cba4f448SSunnySrivastava1984 if (value == nullptr) 606cba4f448SSunnySrivastava1984 { 607cba4f448SSunnySrivastava1984 // illegal value 608cba4f448SSunnySrivastava1984 BMCWEB_LOG_DEBUG << "Location code value error"; 609cba4f448SSunnySrivastava1984 messages::internalError(aResp->res); 610cba4f448SSunnySrivastava1984 return; 611cba4f448SSunnySrivastava1984 } 612cba4f448SSunnySrivastava1984 613cba4f448SSunnySrivastava1984 aResp->res.jsonValue["Location"]["PartLocation"]["ServiceLabel"] = 614cba4f448SSunnySrivastava1984 *value; 615cba4f448SSunnySrivastava1984 }, 616cba4f448SSunnySrivastava1984 service, objPath, "org.freedesktop.DBus.Properties", "Get", 617cba4f448SSunnySrivastava1984 "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode"); 618cba4f448SSunnySrivastava1984 } 619cba4f448SSunnySrivastava1984 620c951448aSJonathan Doman /** 621c951448aSJonathan Doman * Find the D-Bus object representing the requested Processor, and call the 622c951448aSJonathan Doman * handler with the results. If matching object is not found, add 404 error to 623c951448aSJonathan Doman * response and don't call the handler. 624c951448aSJonathan Doman * 625c951448aSJonathan Doman * @param[in,out] resp Async HTTP response. 626c951448aSJonathan Doman * @param[in] processorId Redfish Processor Id. 627c951448aSJonathan Doman * @param[in] handler Callback to continue processing request upon 628c951448aSJonathan Doman * successfully finding object. 629c951448aSJonathan Doman */ 630c951448aSJonathan Doman template <typename Handler> 631*8d1b46d7Szhanghch05 inline void getProcessorObject(const std::shared_ptr<bmcweb::AsyncResp>& resp, 632c951448aSJonathan Doman const std::string& processorId, 633c951448aSJonathan Doman Handler&& handler) 634ac6a4445SGunnar Mills { 635ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "Get available system processor resources."; 636ac6a4445SGunnar Mills 637c951448aSJonathan Doman // GetSubTree on all interfaces which provide info about a Processor 638ac6a4445SGunnar Mills crow::connections::systemBus->async_method_call( 639c951448aSJonathan Doman [resp, processorId, handler = std::forward<Handler>(handler)]( 640c951448aSJonathan Doman boost::system::error_code ec, 641c951448aSJonathan Doman const MapperGetSubTreeResponse& subtree) mutable { 642ac6a4445SGunnar Mills if (ec) 643ac6a4445SGunnar Mills { 644c951448aSJonathan Doman BMCWEB_LOG_DEBUG << "DBUS response error: " << ec; 645c951448aSJonathan Doman messages::internalError(resp->res); 646ac6a4445SGunnar Mills return; 647ac6a4445SGunnar Mills } 6482bab9831SJonathan Doman for (const auto& [objectPath, serviceMap] : subtree) 649ac6a4445SGunnar Mills { 6502bab9831SJonathan Doman // Ignore any objects which don't end with our desired cpu name 6512bab9831SJonathan Doman if (!boost::ends_with(objectPath, processorId)) 652ac6a4445SGunnar Mills { 6532bab9831SJonathan Doman continue; 654ac6a4445SGunnar Mills } 6552bab9831SJonathan Doman 656c951448aSJonathan Doman bool found = false; 657c951448aSJonathan Doman // Filter out objects that don't have the CPU-specific 658c951448aSJonathan Doman // interfaces to make sure we can return 404 on non-CPUs 659c951448aSJonathan Doman // (e.g. /redfish/../Processors/dimm0) 6602bab9831SJonathan Doman for (const auto& [serviceName, interfaceList] : serviceMap) 661ac6a4445SGunnar Mills { 662c951448aSJonathan Doman if (std::find_first_of( 663c951448aSJonathan Doman interfaceList.begin(), interfaceList.end(), 664c951448aSJonathan Doman processorInterfaces.begin(), 665c951448aSJonathan Doman processorInterfaces.end()) != interfaceList.end()) 6662bab9831SJonathan Doman { 667c951448aSJonathan Doman found = true; 668c951448aSJonathan Doman break; 669c951448aSJonathan Doman } 670c951448aSJonathan Doman } 671c951448aSJonathan Doman 672c951448aSJonathan Doman if (!found) 6732bab9831SJonathan Doman { 674c951448aSJonathan Doman continue; 675ac6a4445SGunnar Mills } 676c951448aSJonathan Doman 677c951448aSJonathan Doman // Process the first object which does match our cpu name and 678c951448aSJonathan Doman // required interfaces, and potentially ignore any other 679c951448aSJonathan Doman // matching objects. Assume all interfaces we want to process 680c951448aSJonathan Doman // must be on the same object path. 681c951448aSJonathan Doman 682c951448aSJonathan Doman handler(resp, processorId, objectPath, serviceMap); 683ac6a4445SGunnar Mills return; 684ac6a4445SGunnar Mills } 685c951448aSJonathan Doman messages::resourceNotFound(resp->res, "Processor", processorId); 686ac6a4445SGunnar Mills }, 687ac6a4445SGunnar Mills "xyz.openbmc_project.ObjectMapper", 688ac6a4445SGunnar Mills "/xyz/openbmc_project/object_mapper", 689ac6a4445SGunnar Mills "xyz.openbmc_project.ObjectMapper", "GetSubTree", 6902bab9831SJonathan Doman "/xyz/openbmc_project/inventory", 0, 691cba4f448SSunnySrivastava1984 std::array<const char*, 6>{ 6922bab9831SJonathan Doman "xyz.openbmc_project.Inventory.Decorator.Asset", 6932bab9831SJonathan Doman "xyz.openbmc_project.Inventory.Decorator.Revision", 6942bab9831SJonathan Doman "xyz.openbmc_project.Inventory.Item.Cpu", 695cba4f448SSunnySrivastava1984 "xyz.openbmc_project.Inventory.Decorator.LocationCode", 696dba0c291SJonathan Doman "xyz.openbmc_project.Inventory.Item.Accelerator", 697dba0c291SJonathan Doman "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig"}); 698ac6a4445SGunnar Mills } 699ac6a4445SGunnar Mills 700*8d1b46d7Szhanghch05 inline void getProcessorData(const std::shared_ptr<bmcweb::AsyncResp>& aResp, 701c951448aSJonathan Doman const std::string& processorId, 702c951448aSJonathan Doman const std::string& objectPath, 703c951448aSJonathan Doman const MapperServiceMap& serviceMap) 704c951448aSJonathan Doman { 705c951448aSJonathan Doman for (const auto& [serviceName, interfaceList] : serviceMap) 706c951448aSJonathan Doman { 707c951448aSJonathan Doman for (const auto& interface : interfaceList) 708c951448aSJonathan Doman { 709c951448aSJonathan Doman if (interface == "xyz.openbmc_project.Inventory.Decorator.Asset") 710c951448aSJonathan Doman { 711c951448aSJonathan Doman getCpuAssetData(aResp, serviceName, objectPath); 712c951448aSJonathan Doman } 713c951448aSJonathan Doman else if (interface == "xyz.openbmc_project.Inventory." 714c951448aSJonathan Doman "Decorator.Revision") 715c951448aSJonathan Doman { 716c951448aSJonathan Doman getCpuRevisionData(aResp, serviceName, objectPath); 717c951448aSJonathan Doman } 718c951448aSJonathan Doman else if (interface == "xyz.openbmc_project.Inventory.Item.Cpu") 719c951448aSJonathan Doman { 720c951448aSJonathan Doman getCpuDataByService(aResp, processorId, serviceName, 721c951448aSJonathan Doman objectPath); 722c951448aSJonathan Doman } 723c951448aSJonathan Doman else if (interface == "xyz.openbmc_project.Inventory." 724c951448aSJonathan Doman "Item.Accelerator") 725c951448aSJonathan Doman { 726c951448aSJonathan Doman getAcceleratorDataByService(aResp, processorId, serviceName, 727c951448aSJonathan Doman objectPath); 728c951448aSJonathan Doman } 729c951448aSJonathan Doman else if (interface == "xyz.openbmc_project.Control.Processor." 730c951448aSJonathan Doman "CurrentOperatingConfig") 731c951448aSJonathan Doman { 732c951448aSJonathan Doman getCpuConfigData(aResp, processorId, serviceName, objectPath); 733c951448aSJonathan Doman } 734c951448aSJonathan Doman else if (interface == "xyz.openbmc_project.Inventory." 735c951448aSJonathan Doman "Decorator.LocationCode") 736c951448aSJonathan Doman { 737c951448aSJonathan Doman getCpuLocationCode(aResp, serviceName, objectPath); 738c951448aSJonathan Doman } 739c951448aSJonathan Doman } 740c951448aSJonathan Doman } 741c951448aSJonathan Doman } 742c951448aSJonathan Doman 743dba0c291SJonathan Doman /** 744dba0c291SJonathan Doman * Request all the properties for the given D-Bus object and fill out the 745dba0c291SJonathan Doman * related entries in the Redfish OperatingConfig response. 746dba0c291SJonathan Doman * 747dba0c291SJonathan Doman * @param[in,out] aResp Async HTTP response. 748dba0c291SJonathan Doman * @param[in] service D-Bus service name to query. 749dba0c291SJonathan Doman * @param[in] objPath D-Bus object to query. 750dba0c291SJonathan Doman */ 751*8d1b46d7Szhanghch05 inline void 752*8d1b46d7Szhanghch05 getOperatingConfigData(const std::shared_ptr<bmcweb::AsyncResp>& aResp, 753dba0c291SJonathan Doman const std::string& service, 754dba0c291SJonathan Doman const std::string& objPath) 755dba0c291SJonathan Doman { 756dba0c291SJonathan Doman crow::connections::systemBus->async_method_call( 757dba0c291SJonathan Doman [aResp](boost::system::error_code ec, 758dba0c291SJonathan Doman const OperatingConfigProperties& properties) { 759dba0c291SJonathan Doman if (ec) 760dba0c291SJonathan Doman { 761dba0c291SJonathan Doman BMCWEB_LOG_WARNING << "D-Bus error: " << ec << ", " 762dba0c291SJonathan Doman << ec.message(); 763dba0c291SJonathan Doman messages::internalError(aResp->res); 764dba0c291SJonathan Doman return; 765dba0c291SJonathan Doman } 766dba0c291SJonathan Doman 767dba0c291SJonathan Doman nlohmann::json& json = aResp->res.jsonValue; 768dba0c291SJonathan Doman for (const auto& [key, variant] : properties) 769dba0c291SJonathan Doman { 770dba0c291SJonathan Doman if (key == "AvailableCoreCount") 771dba0c291SJonathan Doman { 772dba0c291SJonathan Doman const size_t* cores = std::get_if<size_t>(&variant); 773dba0c291SJonathan Doman if (cores != nullptr) 774dba0c291SJonathan Doman { 775dba0c291SJonathan Doman json["TotalAvailableCoreCount"] = *cores; 776dba0c291SJonathan Doman } 777dba0c291SJonathan Doman } 778dba0c291SJonathan Doman else if (key == "BaseSpeed") 779dba0c291SJonathan Doman { 780dba0c291SJonathan Doman const uint32_t* speed = std::get_if<uint32_t>(&variant); 781dba0c291SJonathan Doman if (speed != nullptr) 782dba0c291SJonathan Doman { 783dba0c291SJonathan Doman json["BaseSpeedMHz"] = *speed; 784dba0c291SJonathan Doman } 785dba0c291SJonathan Doman } 786dba0c291SJonathan Doman else if (key == "MaxJunctionTemperature") 787dba0c291SJonathan Doman { 788dba0c291SJonathan Doman const uint32_t* temp = std::get_if<uint32_t>(&variant); 789dba0c291SJonathan Doman if (temp != nullptr) 790dba0c291SJonathan Doman { 791dba0c291SJonathan Doman json["MaxJunctionTemperatureCelsius"] = *temp; 792dba0c291SJonathan Doman } 793dba0c291SJonathan Doman } 794dba0c291SJonathan Doman else if (key == "MaxSpeed") 795dba0c291SJonathan Doman { 796dba0c291SJonathan Doman const uint32_t* speed = std::get_if<uint32_t>(&variant); 797dba0c291SJonathan Doman if (speed != nullptr) 798dba0c291SJonathan Doman { 799dba0c291SJonathan Doman json["MaxSpeedMHz"] = *speed; 800dba0c291SJonathan Doman } 801dba0c291SJonathan Doman } 802dba0c291SJonathan Doman else if (key == "PowerLimit") 803dba0c291SJonathan Doman { 804dba0c291SJonathan Doman const uint32_t* tdp = std::get_if<uint32_t>(&variant); 805dba0c291SJonathan Doman if (tdp != nullptr) 806dba0c291SJonathan Doman { 807dba0c291SJonathan Doman json["TDPWatts"] = *tdp; 808dba0c291SJonathan Doman } 809dba0c291SJonathan Doman } 810dba0c291SJonathan Doman else if (key == "TurboProfile") 811dba0c291SJonathan Doman { 812dba0c291SJonathan Doman const auto* turboList = 813dba0c291SJonathan Doman std::get_if<TurboProfileProperty>(&variant); 814dba0c291SJonathan Doman if (turboList == nullptr) 815dba0c291SJonathan Doman { 816dba0c291SJonathan Doman continue; 817dba0c291SJonathan Doman } 818dba0c291SJonathan Doman 819dba0c291SJonathan Doman nlohmann::json& turboArray = json["TurboProfile"]; 820dba0c291SJonathan Doman turboArray = nlohmann::json::array(); 821dba0c291SJonathan Doman for (const auto& [turboSpeed, coreCount] : *turboList) 822dba0c291SJonathan Doman { 823dba0c291SJonathan Doman turboArray.push_back({{"ActiveCoreCount", coreCount}, 824dba0c291SJonathan Doman {"MaxSpeedMHz", turboSpeed}}); 825dba0c291SJonathan Doman } 826dba0c291SJonathan Doman } 827dba0c291SJonathan Doman else if (key == "BaseSpeedPrioritySettings") 828dba0c291SJonathan Doman { 829dba0c291SJonathan Doman const auto* baseSpeedList = 830dba0c291SJonathan Doman std::get_if<BaseSpeedPrioritySettingsProperty>( 831dba0c291SJonathan Doman &variant); 832dba0c291SJonathan Doman if (baseSpeedList == nullptr) 833dba0c291SJonathan Doman { 834dba0c291SJonathan Doman continue; 835dba0c291SJonathan Doman } 836dba0c291SJonathan Doman 837dba0c291SJonathan Doman nlohmann::json& baseSpeedArray = 838dba0c291SJonathan Doman json["BaseSpeedPrioritySettings"]; 839dba0c291SJonathan Doman baseSpeedArray = nlohmann::json::array(); 840dba0c291SJonathan Doman for (const auto& [baseSpeed, coreList] : *baseSpeedList) 841dba0c291SJonathan Doman { 842dba0c291SJonathan Doman baseSpeedArray.push_back( 843dba0c291SJonathan Doman {{"CoreCount", coreList.size()}, 844dba0c291SJonathan Doman {"CoreIDs", coreList}, 845dba0c291SJonathan Doman {"BaseSpeedMHz", baseSpeed}}); 846dba0c291SJonathan Doman } 847dba0c291SJonathan Doman } 848dba0c291SJonathan Doman } 849dba0c291SJonathan Doman }, 850dba0c291SJonathan Doman service, objPath, "org.freedesktop.DBus.Properties", "GetAll", 851dba0c291SJonathan Doman "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig"); 852dba0c291SJonathan Doman } 853dba0c291SJonathan Doman 854dba0c291SJonathan Doman class OperatingConfigCollection : public Node 855dba0c291SJonathan Doman { 856dba0c291SJonathan Doman public: 857dba0c291SJonathan Doman OperatingConfigCollection(App& app) : 858dba0c291SJonathan Doman Node(app, 859dba0c291SJonathan Doman "/redfish/v1/Systems/system/Processors/<str>/OperatingConfigs/", 860dba0c291SJonathan Doman std::string()) 861dba0c291SJonathan Doman { 862dba0c291SJonathan Doman // Defined by Redfish spec privilege registry 863dba0c291SJonathan Doman entityPrivileges = { 864dba0c291SJonathan Doman {boost::beast::http::verb::get, {{"Login"}}}, 865dba0c291SJonathan Doman {boost::beast::http::verb::head, {{"Login"}}}, 866dba0c291SJonathan Doman {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 867dba0c291SJonathan Doman {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 868dba0c291SJonathan Doman {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 869dba0c291SJonathan Doman {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 870dba0c291SJonathan Doman } 871dba0c291SJonathan Doman 872dba0c291SJonathan Doman private: 873*8d1b46d7Szhanghch05 void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 874*8d1b46d7Szhanghch05 const crow::Request& req, 875dba0c291SJonathan Doman const std::vector<std::string>& params) override 876dba0c291SJonathan Doman { 877dba0c291SJonathan Doman if (params.size() != 1) 878dba0c291SJonathan Doman { 879*8d1b46d7Szhanghch05 messages::internalError(asyncResp->res); 880dba0c291SJonathan Doman return; 881dba0c291SJonathan Doman } 882dba0c291SJonathan Doman 883dba0c291SJonathan Doman const std::string& cpuName = params[0]; 884*8d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.type"] = 885dba0c291SJonathan Doman "#OperatingConfigCollection.OperatingConfigCollection"; 886*8d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.id"] = req.url; 887*8d1b46d7Szhanghch05 asyncResp->res.jsonValue["Name"] = "Operating Config Collection"; 888dba0c291SJonathan Doman 889dba0c291SJonathan Doman // First find the matching CPU object so we know how to constrain our 890dba0c291SJonathan Doman // search for related Config objects. 891dba0c291SJonathan Doman crow::connections::systemBus->async_method_call( 892dba0c291SJonathan Doman [asyncResp, cpuName](const boost::system::error_code ec, 893dba0c291SJonathan Doman const std::vector<std::string>& objects) { 894dba0c291SJonathan Doman if (ec) 895dba0c291SJonathan Doman { 896dba0c291SJonathan Doman BMCWEB_LOG_WARNING << "D-Bus error: " << ec << ", " 897dba0c291SJonathan Doman << ec.message(); 898dba0c291SJonathan Doman messages::internalError(asyncResp->res); 899dba0c291SJonathan Doman return; 900dba0c291SJonathan Doman } 901dba0c291SJonathan Doman 902dba0c291SJonathan Doman for (const std::string& object : objects) 903dba0c291SJonathan Doman { 904dba0c291SJonathan Doman if (!boost::ends_with(object, cpuName)) 905dba0c291SJonathan Doman { 906dba0c291SJonathan Doman continue; 907dba0c291SJonathan Doman } 908dba0c291SJonathan Doman 909dba0c291SJonathan Doman // Not expected that there will be multiple matching CPU 910dba0c291SJonathan Doman // objects, but if there are just use the first one. 911dba0c291SJonathan Doman 912dba0c291SJonathan Doman // Use the common search routine to construct the Collection 913dba0c291SJonathan Doman // of all Config objects under this CPU. 914dba0c291SJonathan Doman collection_util::getCollectionMembers( 915dba0c291SJonathan Doman asyncResp, 916dba0c291SJonathan Doman "/redfish/v1/Systems/system/Processors/" + cpuName + 917dba0c291SJonathan Doman "/OperatingConfigs", 918dba0c291SJonathan Doman {"xyz.openbmc_project.Inventory.Item.Cpu." 919dba0c291SJonathan Doman "OperatingConfig"}, 920dba0c291SJonathan Doman object.c_str()); 921dba0c291SJonathan Doman return; 922dba0c291SJonathan Doman } 923dba0c291SJonathan Doman }, 924dba0c291SJonathan Doman "xyz.openbmc_project.ObjectMapper", 925dba0c291SJonathan Doman "/xyz/openbmc_project/object_mapper", 926dba0c291SJonathan Doman "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", 927dba0c291SJonathan Doman "/xyz/openbmc_project/inventory", 0, 928dba0c291SJonathan Doman std::array<const char*, 1>{"xyz.openbmc_project.Control.Processor." 929dba0c291SJonathan Doman "CurrentOperatingConfig"}); 930dba0c291SJonathan Doman } 931dba0c291SJonathan Doman }; 932dba0c291SJonathan Doman 933dba0c291SJonathan Doman class OperatingConfig : public Node 934dba0c291SJonathan Doman { 935dba0c291SJonathan Doman public: 936dba0c291SJonathan Doman OperatingConfig(App& app) : 937dba0c291SJonathan Doman Node(app, 938dba0c291SJonathan Doman "/redfish/v1/Systems/system/Processors/<str>/OperatingConfigs/" 939dba0c291SJonathan Doman "<str>/", 940dba0c291SJonathan Doman std::string(), std::string()) 941dba0c291SJonathan Doman { 942dba0c291SJonathan Doman // Defined by Redfish spec privilege registry 943dba0c291SJonathan Doman entityPrivileges = { 944dba0c291SJonathan Doman {boost::beast::http::verb::get, {{"Login"}}}, 945dba0c291SJonathan Doman {boost::beast::http::verb::head, {{"Login"}}}, 946dba0c291SJonathan Doman {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 947dba0c291SJonathan Doman {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 948dba0c291SJonathan Doman {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 949dba0c291SJonathan Doman {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 950dba0c291SJonathan Doman } 951dba0c291SJonathan Doman 952dba0c291SJonathan Doman private: 953*8d1b46d7Szhanghch05 void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 954*8d1b46d7Szhanghch05 const crow::Request& req, 955dba0c291SJonathan Doman const std::vector<std::string>& params) override 956dba0c291SJonathan Doman { 957dba0c291SJonathan Doman if (params.size() != 2) 958dba0c291SJonathan Doman { 959*8d1b46d7Szhanghch05 messages::internalError(asyncResp->res); 960dba0c291SJonathan Doman return; 961dba0c291SJonathan Doman } 962dba0c291SJonathan Doman 963dba0c291SJonathan Doman const std::string& cpuName = params[0]; 964dba0c291SJonathan Doman const std::string& configName = params[1]; 965dba0c291SJonathan Doman 966dba0c291SJonathan Doman // Ask for all objects implementing OperatingConfig so we can search for 967dba0c291SJonathan Doman // one with a matching name 968dba0c291SJonathan Doman crow::connections::systemBus->async_method_call( 969dba0c291SJonathan Doman [asyncResp, cpuName, configName, 970dba0c291SJonathan Doman reqUrl{req.url}](boost::system::error_code ec, 971dba0c291SJonathan Doman const MapperGetSubTreeResponse& subtree) { 972dba0c291SJonathan Doman if (ec) 973dba0c291SJonathan Doman { 974dba0c291SJonathan Doman BMCWEB_LOG_WARNING << "D-Bus error: " << ec << ", " 975dba0c291SJonathan Doman << ec.message(); 976dba0c291SJonathan Doman messages::internalError(asyncResp->res); 977dba0c291SJonathan Doman return; 978dba0c291SJonathan Doman } 979dba0c291SJonathan Doman const std::string expectedEnding = cpuName + '/' + configName; 980dba0c291SJonathan Doman for (const auto& [objectPath, serviceMap] : subtree) 981dba0c291SJonathan Doman { 982dba0c291SJonathan Doman // Ignore any configs without matching cpuX/configY 983dba0c291SJonathan Doman if (!boost::ends_with(objectPath, expectedEnding) || 984dba0c291SJonathan Doman serviceMap.empty()) 985dba0c291SJonathan Doman { 986dba0c291SJonathan Doman continue; 987dba0c291SJonathan Doman } 988dba0c291SJonathan Doman 989dba0c291SJonathan Doman nlohmann::json& json = asyncResp->res.jsonValue; 990dba0c291SJonathan Doman json["@odata.type"] = 991dba0c291SJonathan Doman "#OperatingConfig.v1_0_0.OperatingConfig"; 992dba0c291SJonathan Doman json["@odata.id"] = reqUrl; 993dba0c291SJonathan Doman json["Name"] = "Processor Profile"; 994dba0c291SJonathan Doman json["Id"] = configName; 995dba0c291SJonathan Doman 996dba0c291SJonathan Doman // Just use the first implementation of the object - not 997dba0c291SJonathan Doman // expected that there would be multiple matching services 998dba0c291SJonathan Doman getOperatingConfigData(asyncResp, serviceMap.begin()->first, 999dba0c291SJonathan Doman objectPath); 1000dba0c291SJonathan Doman return; 1001dba0c291SJonathan Doman } 1002dba0c291SJonathan Doman messages::resourceNotFound(asyncResp->res, "OperatingConfig", 1003dba0c291SJonathan Doman configName); 1004dba0c291SJonathan Doman }, 1005dba0c291SJonathan Doman "xyz.openbmc_project.ObjectMapper", 1006dba0c291SJonathan Doman "/xyz/openbmc_project/object_mapper", 1007dba0c291SJonathan Doman "xyz.openbmc_project.ObjectMapper", "GetSubTree", 1008dba0c291SJonathan Doman "/xyz/openbmc_project/inventory", 0, 1009dba0c291SJonathan Doman std::array<const char*, 1>{ 1010dba0c291SJonathan Doman "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig"}); 1011dba0c291SJonathan Doman } 1012dba0c291SJonathan Doman }; 1013dba0c291SJonathan Doman 1014ac6a4445SGunnar Mills class ProcessorCollection : public Node 1015ac6a4445SGunnar Mills { 1016ac6a4445SGunnar Mills public: 1017ac6a4445SGunnar Mills /* 1018ac6a4445SGunnar Mills * Default Constructor 1019ac6a4445SGunnar Mills */ 1020ac6a4445SGunnar Mills ProcessorCollection(App& app) : 1021ac6a4445SGunnar Mills Node(app, "/redfish/v1/Systems/system/Processors/") 1022ac6a4445SGunnar Mills { 1023ac6a4445SGunnar Mills entityPrivileges = { 1024ac6a4445SGunnar Mills {boost::beast::http::verb::get, {{"Login"}}}, 1025ac6a4445SGunnar Mills {boost::beast::http::verb::head, {{"Login"}}}, 1026ac6a4445SGunnar Mills {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 1027ac6a4445SGunnar Mills {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 1028ac6a4445SGunnar Mills {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 1029ac6a4445SGunnar Mills {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 1030ac6a4445SGunnar Mills } 1031ac6a4445SGunnar Mills 1032ac6a4445SGunnar Mills private: 1033ac6a4445SGunnar Mills /** 1034ac6a4445SGunnar Mills * Functions triggers appropriate requests on DBus 1035ac6a4445SGunnar Mills */ 1036*8d1b46d7Szhanghch05 void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1037*8d1b46d7Szhanghch05 const crow::Request&, const std::vector<std::string>&) override 1038ac6a4445SGunnar Mills { 1039*8d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.type"] = 1040ac6a4445SGunnar Mills "#ProcessorCollection.ProcessorCollection"; 1041*8d1b46d7Szhanghch05 asyncResp->res.jsonValue["Name"] = "Processor Collection"; 1042ac6a4445SGunnar Mills 1043*8d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.id"] = 1044*8d1b46d7Szhanghch05 "/redfish/v1/Systems/system/Processors"; 1045ac6a4445SGunnar Mills 104605030b8eSGunnar Mills collection_util::getCollectionMembers( 104705030b8eSGunnar Mills asyncResp, "/redfish/v1/Systems/system/Processors", 1048c951448aSJonathan Doman std::vector<const char*>(processorInterfaces.begin(), 1049c951448aSJonathan Doman processorInterfaces.end())); 1050ac6a4445SGunnar Mills } 1051ac6a4445SGunnar Mills }; 1052ac6a4445SGunnar Mills 1053ac6a4445SGunnar Mills class Processor : public Node 1054ac6a4445SGunnar Mills { 1055ac6a4445SGunnar Mills public: 1056ac6a4445SGunnar Mills /* 1057ac6a4445SGunnar Mills * Default Constructor 1058ac6a4445SGunnar Mills */ 1059ac6a4445SGunnar Mills Processor(App& app) : 1060ac6a4445SGunnar Mills Node(app, "/redfish/v1/Systems/system/Processors/<str>/", std::string()) 1061ac6a4445SGunnar Mills { 1062ac6a4445SGunnar Mills entityPrivileges = { 1063ac6a4445SGunnar Mills {boost::beast::http::verb::get, {{"Login"}}}, 1064ac6a4445SGunnar Mills {boost::beast::http::verb::head, {{"Login"}}}, 1065ac6a4445SGunnar Mills {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 1066ac6a4445SGunnar Mills {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 1067ac6a4445SGunnar Mills {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 1068ac6a4445SGunnar Mills {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 1069ac6a4445SGunnar Mills } 1070ac6a4445SGunnar Mills 1071ac6a4445SGunnar Mills private: 1072ac6a4445SGunnar Mills /** 1073ac6a4445SGunnar Mills * Functions triggers appropriate requests on DBus 1074ac6a4445SGunnar Mills */ 1075*8d1b46d7Szhanghch05 void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1076*8d1b46d7Szhanghch05 const crow::Request&, 1077ac6a4445SGunnar Mills const std::vector<std::string>& params) override 1078ac6a4445SGunnar Mills { 1079ac6a4445SGunnar Mills // Check if there is required param, truly entering this shall be 1080ac6a4445SGunnar Mills // impossible 1081ac6a4445SGunnar Mills if (params.size() != 1) 1082ac6a4445SGunnar Mills { 1083*8d1b46d7Szhanghch05 messages::internalError(asyncResp->res); 1084ac6a4445SGunnar Mills return; 1085ac6a4445SGunnar Mills } 1086ac6a4445SGunnar Mills const std::string& processorId = params[0]; 1087*8d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.type"] = 1088*8d1b46d7Szhanghch05 "#Processor.v1_11_0.Processor"; 1089*8d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.id"] = 1090ac6a4445SGunnar Mills "/redfish/v1/Systems/system/Processors/" + processorId; 1091ac6a4445SGunnar Mills 1092c951448aSJonathan Doman getProcessorObject(asyncResp, processorId, getProcessorData); 1093ac6a4445SGunnar Mills } 1094ac6a4445SGunnar Mills }; 1095ac6a4445SGunnar Mills 1096ac6a4445SGunnar Mills } // namespace redfish 1097