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 183ccb3adbSEd Tanous #include "app.hpp" 191e1e598dSJonathan Doman #include "dbus_singleton.hpp" 207a1dbc48SGeorge Liu #include "dbus_utility.hpp" 211e1e598dSJonathan Doman #include "error_messages.hpp" 22ac6a4445SGunnar Mills #include "health.hpp" 233ccb3adbSEd Tanous #include "query.hpp" 243ccb3adbSEd Tanous #include "registries/privilege_registry.hpp" 253ccb3adbSEd Tanous #include "utils/collection.hpp" 263ccb3adbSEd Tanous #include "utils/dbus_utils.hpp" 273ccb3adbSEd Tanous #include "utils/json_utils.hpp" 28ac6a4445SGunnar Mills 29ac6a4445SGunnar Mills #include <boost/container/flat_map.hpp> 30e99073f5SGeorge Liu #include <boost/system/error_code.hpp> 31*ef4c65b7SEd Tanous #include <boost/url/format.hpp> 321e1e598dSJonathan Doman #include <sdbusplus/asio/property.hpp> 33dba0c291SJonathan Doman #include <sdbusplus/message/native_types.hpp> 34351053f2SKrzysztof Grobelny #include <sdbusplus/unpack_properties.hpp> 35dba0c291SJonathan Doman #include <sdbusplus/utility/dedup_variant.hpp> 36ac6a4445SGunnar Mills 377a1dbc48SGeorge Liu #include <array> 38b9d679d1SMichael Shen #include <limits> 397a1dbc48SGeorge Liu #include <string_view> 407a1dbc48SGeorge Liu 41ac6a4445SGunnar Mills namespace redfish 42ac6a4445SGunnar Mills { 43ac6a4445SGunnar Mills 44c951448aSJonathan Doman // Interfaces which imply a D-Bus object represents a Processor 457a1dbc48SGeorge Liu constexpr std::array<std::string_view, 2> processorInterfaces = { 46c951448aSJonathan Doman "xyz.openbmc_project.Inventory.Item.Cpu", 47c951448aSJonathan Doman "xyz.openbmc_project.Inventory.Item.Accelerator"}; 482bab9831SJonathan Doman 4971b82f26SSharad Yadav /** 5071b82f26SSharad Yadav * @brief Fill out uuid info of a processor by 5171b82f26SSharad Yadav * requesting data from the given D-Bus object. 5271b82f26SSharad Yadav * 5371b82f26SSharad Yadav * @param[in,out] aResp Async HTTP response. 5471b82f26SSharad Yadav * @param[in] service D-Bus service to query. 5571b82f26SSharad Yadav * @param[in] objPath D-Bus object to query. 5671b82f26SSharad Yadav */ 5771b82f26SSharad Yadav inline void getProcessorUUID(std::shared_ptr<bmcweb::AsyncResp> aResp, 5871b82f26SSharad Yadav const std::string& service, 5971b82f26SSharad Yadav const std::string& objPath) 6071b82f26SSharad Yadav { 6171b82f26SSharad Yadav BMCWEB_LOG_DEBUG << "Get Processor UUID"; 621e1e598dSJonathan Doman sdbusplus::asio::getProperty<std::string>( 631e1e598dSJonathan Doman *crow::connections::systemBus, service, objPath, 641e1e598dSJonathan Doman "xyz.openbmc_project.Common.UUID", "UUID", 655e7e2dc5SEd Tanous [objPath, aResp{std::move(aResp)}](const boost::system::error_code& ec, 661e1e598dSJonathan Doman const std::string& property) { 6771b82f26SSharad Yadav if (ec) 6871b82f26SSharad Yadav { 6971b82f26SSharad Yadav BMCWEB_LOG_DEBUG << "DBUS response error"; 7071b82f26SSharad Yadav messages::internalError(aResp->res); 7171b82f26SSharad Yadav return; 7271b82f26SSharad Yadav } 731e1e598dSJonathan Doman aResp->res.jsonValue["UUID"] = property; 741e1e598dSJonathan Doman }); 7571b82f26SSharad Yadav } 7671b82f26SSharad Yadav 77711ac7a9SEd Tanous inline void getCpuDataByInterface( 78711ac7a9SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& aResp, 79711ac7a9SEd Tanous const dbus::utility::DBusInteracesMap& cpuInterfacesProperties) 80ac6a4445SGunnar Mills { 81ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "Get CPU resources by interface."; 82ac6a4445SGunnar Mills 83a1649ec6SChicago Duan // Set the default value of state 84a1649ec6SChicago Duan aResp->res.jsonValue["Status"]["State"] = "Enabled"; 85a1649ec6SChicago Duan aResp->res.jsonValue["Status"]["Health"] = "OK"; 86ac6a4445SGunnar Mills 87ac6a4445SGunnar Mills for (const auto& interface : cpuInterfacesProperties) 88ac6a4445SGunnar Mills { 89ac6a4445SGunnar Mills for (const auto& property : interface.second) 90ac6a4445SGunnar Mills { 91a1649ec6SChicago Duan if (property.first == "Present") 92ac6a4445SGunnar Mills { 93a1649ec6SChicago Duan const bool* cpuPresent = std::get_if<bool>(&property.second); 94a1649ec6SChicago Duan if (cpuPresent == nullptr) 95ac6a4445SGunnar Mills { 96ac6a4445SGunnar Mills // Important property not in desired type 97ac6a4445SGunnar Mills messages::internalError(aResp->res); 98ac6a4445SGunnar Mills return; 99ac6a4445SGunnar Mills } 100e05aec50SEd Tanous if (!*cpuPresent) 101ac6a4445SGunnar Mills { 102a1649ec6SChicago Duan // Slot is not populated 103ac6a4445SGunnar Mills aResp->res.jsonValue["Status"]["State"] = "Absent"; 104a1649ec6SChicago Duan } 105a1649ec6SChicago Duan } 106a1649ec6SChicago Duan else if (property.first == "Functional") 107a1649ec6SChicago Duan { 108a1649ec6SChicago Duan const bool* cpuFunctional = std::get_if<bool>(&property.second); 109a1649ec6SChicago Duan if (cpuFunctional == nullptr) 110a1649ec6SChicago Duan { 111a1649ec6SChicago Duan messages::internalError(aResp->res); 112ac6a4445SGunnar Mills return; 113ac6a4445SGunnar Mills } 114e05aec50SEd Tanous if (!*cpuFunctional) 115a1649ec6SChicago Duan { 116a1649ec6SChicago Duan aResp->res.jsonValue["Status"]["Health"] = "Critical"; 117a1649ec6SChicago Duan } 118a1649ec6SChicago Duan } 119a1649ec6SChicago Duan else if (property.first == "CoreCount") 120a1649ec6SChicago Duan { 121a1649ec6SChicago Duan const uint16_t* coresCount = 122a1649ec6SChicago Duan std::get_if<uint16_t>(&property.second); 123a1649ec6SChicago Duan if (coresCount == nullptr) 124a1649ec6SChicago Duan { 125a1649ec6SChicago Duan messages::internalError(aResp->res); 126a1649ec6SChicago Duan return; 127a1649ec6SChicago Duan } 128ac6a4445SGunnar Mills aResp->res.jsonValue["TotalCores"] = *coresCount; 129ac6a4445SGunnar Mills } 130dc3fa667SJonathan Doman else if (property.first == "MaxSpeedInMhz") 131dc3fa667SJonathan Doman { 132dc3fa667SJonathan Doman const uint32_t* value = std::get_if<uint32_t>(&property.second); 133dc3fa667SJonathan Doman if (value != nullptr) 134dc3fa667SJonathan Doman { 135dc3fa667SJonathan Doman aResp->res.jsonValue["MaxSpeedMHz"] = *value; 136dc3fa667SJonathan Doman } 137dc3fa667SJonathan Doman } 138ac6a4445SGunnar Mills else if (property.first == "Socket") 139ac6a4445SGunnar Mills { 140ac6a4445SGunnar Mills const std::string* value = 141ac6a4445SGunnar Mills std::get_if<std::string>(&property.second); 142ac6a4445SGunnar Mills if (value != nullptr) 143ac6a4445SGunnar Mills { 144ac6a4445SGunnar Mills aResp->res.jsonValue["Socket"] = *value; 145ac6a4445SGunnar Mills } 146ac6a4445SGunnar Mills } 147ac6a4445SGunnar Mills else if (property.first == "ThreadCount") 148ac6a4445SGunnar Mills { 149dc3fa667SJonathan Doman const uint16_t* value = std::get_if<uint16_t>(&property.second); 150ac6a4445SGunnar Mills if (value != nullptr) 151ac6a4445SGunnar Mills { 152ac6a4445SGunnar Mills aResp->res.jsonValue["TotalThreads"] = *value; 153ac6a4445SGunnar Mills } 154ac6a4445SGunnar Mills } 1551930fbd4SBrandon Kim else if (property.first == "EffectiveFamily") 156ac6a4445SGunnar Mills { 1571930fbd4SBrandon Kim const uint16_t* value = std::get_if<uint16_t>(&property.second); 1586169de2cSBrad Bishop if (value != nullptr && *value != 2) 159ac6a4445SGunnar Mills { 160ac6a4445SGunnar Mills aResp->res.jsonValue["ProcessorId"]["EffectiveFamily"] = 161866e4862SEd Tanous "0x" + intToHexString(*value, 4); 162ac6a4445SGunnar Mills } 163ac6a4445SGunnar Mills } 1641930fbd4SBrandon Kim else if (property.first == "EffectiveModel") 1651930fbd4SBrandon Kim { 1661930fbd4SBrandon Kim const uint16_t* value = std::get_if<uint16_t>(&property.second); 1671930fbd4SBrandon Kim if (value == nullptr) 1681930fbd4SBrandon Kim { 1691930fbd4SBrandon Kim messages::internalError(aResp->res); 1701930fbd4SBrandon Kim return; 1711930fbd4SBrandon Kim } 1726169de2cSBrad Bishop if (*value != 0) 1736169de2cSBrad Bishop { 1741930fbd4SBrandon Kim aResp->res.jsonValue["ProcessorId"]["EffectiveModel"] = 175866e4862SEd Tanous "0x" + intToHexString(*value, 4); 1761930fbd4SBrandon Kim } 1776169de2cSBrad Bishop } 178ac6a4445SGunnar Mills else if (property.first == "Id") 179ac6a4445SGunnar Mills { 180ac6a4445SGunnar Mills const uint64_t* value = std::get_if<uint64_t>(&property.second); 181ac6a4445SGunnar Mills if (value != nullptr && *value != 0) 182ac6a4445SGunnar Mills { 183ac6a4445SGunnar Mills aResp->res 184ac6a4445SGunnar Mills .jsonValue["ProcessorId"]["IdentificationRegisters"] = 185866e4862SEd Tanous "0x" + intToHexString(*value, 16); 186ac6a4445SGunnar Mills } 187ac6a4445SGunnar Mills } 1881930fbd4SBrandon Kim else if (property.first == "Microcode") 1891930fbd4SBrandon Kim { 1901930fbd4SBrandon Kim const uint32_t* value = std::get_if<uint32_t>(&property.second); 1911930fbd4SBrandon Kim if (value == nullptr) 1921930fbd4SBrandon Kim { 1931930fbd4SBrandon Kim messages::internalError(aResp->res); 1941930fbd4SBrandon Kim return; 1951930fbd4SBrandon Kim } 1966169de2cSBrad Bishop if (*value != 0) 1976169de2cSBrad Bishop { 1981930fbd4SBrandon Kim aResp->res.jsonValue["ProcessorId"]["MicrocodeInfo"] = 199866e4862SEd Tanous "0x" + intToHexString(*value, 8); 2001930fbd4SBrandon Kim } 2016169de2cSBrad Bishop } 2021930fbd4SBrandon Kim else if (property.first == "Step") 2031930fbd4SBrandon Kim { 2041930fbd4SBrandon Kim const uint16_t* value = std::get_if<uint16_t>(&property.second); 2051930fbd4SBrandon Kim if (value == nullptr) 2061930fbd4SBrandon Kim { 2071930fbd4SBrandon Kim messages::internalError(aResp->res); 2081930fbd4SBrandon Kim return; 2091930fbd4SBrandon Kim } 210b9d679d1SMichael Shen if (*value != std::numeric_limits<uint16_t>::max()) 2116169de2cSBrad Bishop { 2121930fbd4SBrandon Kim aResp->res.jsonValue["ProcessorId"]["Step"] = 213866e4862SEd Tanous "0x" + intToHexString(*value, 4); 2141930fbd4SBrandon Kim } 215ac6a4445SGunnar Mills } 216ac6a4445SGunnar Mills } 217ac6a4445SGunnar Mills } 2186169de2cSBrad Bishop } 219ac6a4445SGunnar Mills 2208d1b46d7Szhanghch05 inline void getCpuDataByService(std::shared_ptr<bmcweb::AsyncResp> aResp, 221ac6a4445SGunnar Mills const std::string& cpuId, 222ac6a4445SGunnar Mills const std::string& service, 223ac6a4445SGunnar Mills const std::string& objPath) 224ac6a4445SGunnar Mills { 225ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "Get available system cpu resources by service."; 226ac6a4445SGunnar Mills 227ac6a4445SGunnar Mills crow::connections::systemBus->async_method_call( 228ac6a4445SGunnar Mills [cpuId, service, objPath, aResp{std::move(aResp)}]( 2295e7e2dc5SEd Tanous const boost::system::error_code& ec, 230ac6a4445SGunnar Mills const dbus::utility::ManagedObjectType& dbusData) { 231ac6a4445SGunnar Mills if (ec) 232ac6a4445SGunnar Mills { 233ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "DBUS response error"; 234ac6a4445SGunnar Mills messages::internalError(aResp->res); 235ac6a4445SGunnar Mills return; 236ac6a4445SGunnar Mills } 237ac6a4445SGunnar Mills aResp->res.jsonValue["Id"] = cpuId; 238ac6a4445SGunnar Mills aResp->res.jsonValue["Name"] = "Processor"; 239ac6a4445SGunnar Mills aResp->res.jsonValue["ProcessorType"] = "CPU"; 240ac6a4445SGunnar Mills 241ac6a4445SGunnar Mills bool slotPresent = false; 242ac6a4445SGunnar Mills std::string corePath = objPath + "/core"; 243ac6a4445SGunnar Mills size_t totalCores = 0; 244ac6a4445SGunnar Mills for (const auto& object : dbusData) 245ac6a4445SGunnar Mills { 246ac6a4445SGunnar Mills if (object.first.str == objPath) 247ac6a4445SGunnar Mills { 248ac6a4445SGunnar Mills getCpuDataByInterface(aResp, object.second); 249ac6a4445SGunnar Mills } 25011ba3979SEd Tanous else if (object.first.str.starts_with(corePath)) 251ac6a4445SGunnar Mills { 252ac6a4445SGunnar Mills for (const auto& interface : object.second) 253ac6a4445SGunnar Mills { 254002d39b4SEd Tanous if (interface.first == "xyz.openbmc_project.Inventory.Item") 255ac6a4445SGunnar Mills { 256ac6a4445SGunnar Mills for (const auto& property : interface.second) 257ac6a4445SGunnar Mills { 258ac6a4445SGunnar Mills if (property.first == "Present") 259ac6a4445SGunnar Mills { 260ac6a4445SGunnar Mills const bool* present = 261ac6a4445SGunnar Mills std::get_if<bool>(&property.second); 262ac6a4445SGunnar Mills if (present != nullptr) 263ac6a4445SGunnar Mills { 264e05aec50SEd Tanous if (*present) 265ac6a4445SGunnar Mills { 266ac6a4445SGunnar Mills slotPresent = true; 267ac6a4445SGunnar Mills totalCores++; 268ac6a4445SGunnar Mills } 269ac6a4445SGunnar Mills } 270ac6a4445SGunnar Mills } 271ac6a4445SGunnar Mills } 272ac6a4445SGunnar Mills } 273ac6a4445SGunnar Mills } 274ac6a4445SGunnar Mills } 275ac6a4445SGunnar Mills } 276ac6a4445SGunnar Mills // In getCpuDataByInterface(), state and health are set 277ac6a4445SGunnar Mills // based on the present and functional status. If core 278ac6a4445SGunnar Mills // count is zero, then it has a higher precedence. 279ac6a4445SGunnar Mills if (slotPresent) 280ac6a4445SGunnar Mills { 281ac6a4445SGunnar Mills if (totalCores == 0) 282ac6a4445SGunnar Mills { 283ac6a4445SGunnar Mills // Slot is not populated, set status end return 284ac6a4445SGunnar Mills aResp->res.jsonValue["Status"]["State"] = "Absent"; 285ac6a4445SGunnar Mills aResp->res.jsonValue["Status"]["Health"] = "OK"; 286ac6a4445SGunnar Mills } 287ac6a4445SGunnar Mills aResp->res.jsonValue["TotalCores"] = totalCores; 288ac6a4445SGunnar Mills } 289ac6a4445SGunnar Mills return; 290ac6a4445SGunnar Mills }, 291ac6a4445SGunnar Mills service, "/xyz/openbmc_project/inventory", 292ac6a4445SGunnar Mills "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 293ac6a4445SGunnar Mills } 294ac6a4445SGunnar Mills 2958d1b46d7Szhanghch05 inline void getCpuAssetData(std::shared_ptr<bmcweb::AsyncResp> aResp, 296ac6a4445SGunnar Mills const std::string& service, 297ac6a4445SGunnar Mills const std::string& objPath) 298ac6a4445SGunnar Mills { 299ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "Get Cpu Asset Data"; 300351053f2SKrzysztof Grobelny sdbusplus::asio::getAllProperties( 301351053f2SKrzysztof Grobelny *crow::connections::systemBus, service, objPath, 302351053f2SKrzysztof Grobelny "xyz.openbmc_project.Inventory.Decorator.Asset", 303ac6a4445SGunnar Mills [objPath, aResp{std::move(aResp)}]( 3045e7e2dc5SEd Tanous const boost::system::error_code& ec, 305351053f2SKrzysztof Grobelny const dbus::utility::DBusPropertiesMap& properties) { 306ac6a4445SGunnar Mills if (ec) 307ac6a4445SGunnar Mills { 308ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "DBUS response error"; 309ac6a4445SGunnar Mills messages::internalError(aResp->res); 310ac6a4445SGunnar Mills return; 311ac6a4445SGunnar Mills } 312ac6a4445SGunnar Mills 313351053f2SKrzysztof Grobelny const std::string* serialNumber = nullptr; 314351053f2SKrzysztof Grobelny const std::string* model = nullptr; 315351053f2SKrzysztof Grobelny const std::string* manufacturer = nullptr; 316351053f2SKrzysztof Grobelny const std::string* partNumber = nullptr; 317351053f2SKrzysztof Grobelny const std::string* sparePartNumber = nullptr; 318351053f2SKrzysztof Grobelny 319351053f2SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 320351053f2SKrzysztof Grobelny dbus_utils::UnpackErrorPrinter(), properties, "SerialNumber", 321351053f2SKrzysztof Grobelny serialNumber, "Model", model, "Manufacturer", manufacturer, 322351053f2SKrzysztof Grobelny "PartNumber", partNumber, "SparePartNumber", sparePartNumber); 323351053f2SKrzysztof Grobelny 324351053f2SKrzysztof Grobelny if (!success) 325ac6a4445SGunnar Mills { 326351053f2SKrzysztof Grobelny messages::internalError(aResp->res); 327351053f2SKrzysztof Grobelny return; 328ac6a4445SGunnar Mills } 329351053f2SKrzysztof Grobelny 330351053f2SKrzysztof Grobelny if (serialNumber != nullptr && !serialNumber->empty()) 331ac6a4445SGunnar Mills { 332351053f2SKrzysztof Grobelny aResp->res.jsonValue["SerialNumber"] = *serialNumber; 333351053f2SKrzysztof Grobelny } 334351053f2SKrzysztof Grobelny 335351053f2SKrzysztof Grobelny if ((model != nullptr) && !model->empty()) 336ac6a4445SGunnar Mills { 337ac6a4445SGunnar Mills aResp->res.jsonValue["Model"] = *model; 338ac6a4445SGunnar Mills } 339ac6a4445SGunnar Mills 340351053f2SKrzysztof Grobelny if (manufacturer != nullptr) 341ac6a4445SGunnar Mills { 342351053f2SKrzysztof Grobelny aResp->res.jsonValue["Manufacturer"] = *manufacturer; 343ac6a4445SGunnar Mills 344ac6a4445SGunnar Mills // Otherwise would be unexpected. 345351053f2SKrzysztof Grobelny if (manufacturer->find("Intel") != std::string::npos) 346ac6a4445SGunnar Mills { 347002d39b4SEd Tanous aResp->res.jsonValue["ProcessorArchitecture"] = "x86"; 348ac6a4445SGunnar Mills aResp->res.jsonValue["InstructionSet"] = "x86-64"; 349ac6a4445SGunnar Mills } 350351053f2SKrzysztof Grobelny else if (manufacturer->find("IBM") != std::string::npos) 351ac6a4445SGunnar Mills { 352002d39b4SEd Tanous aResp->res.jsonValue["ProcessorArchitecture"] = "Power"; 353ac6a4445SGunnar Mills aResp->res.jsonValue["InstructionSet"] = "PowerISA"; 354ac6a4445SGunnar Mills } 355ac6a4445SGunnar Mills } 356cba4f448SSunnySrivastava1984 357351053f2SKrzysztof Grobelny if (partNumber != nullptr) 358cba4f448SSunnySrivastava1984 { 359cba4f448SSunnySrivastava1984 aResp->res.jsonValue["PartNumber"] = *partNumber; 360cba4f448SSunnySrivastava1984 } 361cba4f448SSunnySrivastava1984 3626169de2cSBrad Bishop if (sparePartNumber != nullptr && !sparePartNumber->empty()) 363cba4f448SSunnySrivastava1984 { 364cba4f448SSunnySrivastava1984 aResp->res.jsonValue["SparePartNumber"] = *sparePartNumber; 365cba4f448SSunnySrivastava1984 } 366351053f2SKrzysztof Grobelny }); 367ac6a4445SGunnar Mills } 368ac6a4445SGunnar Mills 3698d1b46d7Szhanghch05 inline void getCpuRevisionData(std::shared_ptr<bmcweb::AsyncResp> aResp, 370ac6a4445SGunnar Mills const std::string& service, 371ac6a4445SGunnar Mills const std::string& objPath) 372ac6a4445SGunnar Mills { 373ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "Get Cpu Revision Data"; 374351053f2SKrzysztof Grobelny sdbusplus::asio::getAllProperties( 375351053f2SKrzysztof Grobelny *crow::connections::systemBus, service, objPath, 376351053f2SKrzysztof Grobelny "xyz.openbmc_project.Inventory.Decorator.Revision", 377ac6a4445SGunnar Mills [objPath, aResp{std::move(aResp)}]( 3785e7e2dc5SEd Tanous const boost::system::error_code& ec, 379351053f2SKrzysztof Grobelny const dbus::utility::DBusPropertiesMap& properties) { 380ac6a4445SGunnar Mills if (ec) 381ac6a4445SGunnar Mills { 382ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "DBUS response error"; 383ac6a4445SGunnar Mills messages::internalError(aResp->res); 384ac6a4445SGunnar Mills return; 385ac6a4445SGunnar Mills } 386ac6a4445SGunnar Mills 387351053f2SKrzysztof Grobelny const std::string* version = nullptr; 388351053f2SKrzysztof Grobelny 389351053f2SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 390351053f2SKrzysztof Grobelny dbus_utils::UnpackErrorPrinter(), properties, "Version", version); 391351053f2SKrzysztof Grobelny 392351053f2SKrzysztof Grobelny if (!success) 393ac6a4445SGunnar Mills { 394351053f2SKrzysztof Grobelny messages::internalError(aResp->res); 395351053f2SKrzysztof Grobelny return; 396351053f2SKrzysztof Grobelny } 397351053f2SKrzysztof Grobelny 398351053f2SKrzysztof Grobelny if (version != nullptr) 399ac6a4445SGunnar Mills { 400351053f2SKrzysztof Grobelny aResp->res.jsonValue["Version"] = *version; 401ac6a4445SGunnar Mills } 402351053f2SKrzysztof Grobelny }); 403ac6a4445SGunnar Mills } 404ac6a4445SGunnar Mills 4058d1b46d7Szhanghch05 inline void getAcceleratorDataByService( 4068d1b46d7Szhanghch05 std::shared_ptr<bmcweb::AsyncResp> aResp, const std::string& acclrtrId, 4078d1b46d7Szhanghch05 const std::string& service, const std::string& objPath) 408ac6a4445SGunnar Mills { 409ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG 410ac6a4445SGunnar Mills << "Get available system Accelerator resources by service."; 411351053f2SKrzysztof Grobelny sdbusplus::asio::getAllProperties( 412351053f2SKrzysztof Grobelny *crow::connections::systemBus, service, objPath, "", 413ac6a4445SGunnar Mills [acclrtrId, aResp{std::move(aResp)}]( 4145e7e2dc5SEd Tanous const boost::system::error_code& ec, 415351053f2SKrzysztof Grobelny const dbus::utility::DBusPropertiesMap& properties) { 416ac6a4445SGunnar Mills if (ec) 417ac6a4445SGunnar Mills { 418ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "DBUS response error"; 419ac6a4445SGunnar Mills messages::internalError(aResp->res); 420ac6a4445SGunnar Mills return; 421ac6a4445SGunnar Mills } 422ac6a4445SGunnar Mills 423351053f2SKrzysztof Grobelny const bool* functional = nullptr; 424351053f2SKrzysztof Grobelny const bool* present = nullptr; 425351053f2SKrzysztof Grobelny 426351053f2SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 427351053f2SKrzysztof Grobelny dbus_utils::UnpackErrorPrinter(), properties, "Functional", 428351053f2SKrzysztof Grobelny functional, "Present", present); 429351053f2SKrzysztof Grobelny 430351053f2SKrzysztof Grobelny if (!success) 431ac6a4445SGunnar Mills { 432351053f2SKrzysztof Grobelny messages::internalError(aResp->res); 433351053f2SKrzysztof Grobelny return; 434ac6a4445SGunnar Mills } 435ac6a4445SGunnar Mills 436ac6a4445SGunnar Mills std::string state = "Enabled"; 437ac6a4445SGunnar Mills std::string health = "OK"; 438ac6a4445SGunnar Mills 439351053f2SKrzysztof Grobelny if (present != nullptr && !*present) 440ac6a4445SGunnar Mills { 441ac6a4445SGunnar Mills state = "Absent"; 442ac6a4445SGunnar Mills } 443ac6a4445SGunnar Mills 444351053f2SKrzysztof Grobelny if (functional != nullptr && !*functional) 445ac6a4445SGunnar Mills { 446ac6a4445SGunnar Mills if (state == "Enabled") 447ac6a4445SGunnar Mills { 448ac6a4445SGunnar Mills health = "Critical"; 449ac6a4445SGunnar Mills } 450ac6a4445SGunnar Mills } 451ac6a4445SGunnar Mills 452351053f2SKrzysztof Grobelny aResp->res.jsonValue["Id"] = acclrtrId; 453351053f2SKrzysztof Grobelny aResp->res.jsonValue["Name"] = "Processor"; 454ac6a4445SGunnar Mills aResp->res.jsonValue["Status"]["State"] = state; 455ac6a4445SGunnar Mills aResp->res.jsonValue["Status"]["Health"] = health; 456ac6a4445SGunnar Mills aResp->res.jsonValue["ProcessorType"] = "Accelerator"; 457351053f2SKrzysztof Grobelny }); 458ac6a4445SGunnar Mills } 459ac6a4445SGunnar Mills 460dba0c291SJonathan Doman // OperatingConfig D-Bus Types 461dba0c291SJonathan Doman using TurboProfileProperty = std::vector<std::tuple<uint32_t, size_t>>; 462dba0c291SJonathan Doman using BaseSpeedPrioritySettingsProperty = 463dba0c291SJonathan Doman std::vector<std::tuple<uint32_t, std::vector<uint32_t>>>; 464dba0c291SJonathan Doman // uint32_t and size_t may or may not be the same type, requiring a dedup'd 465dba0c291SJonathan Doman // variant 466dba0c291SJonathan Doman 467dba0c291SJonathan Doman /** 468dba0c291SJonathan Doman * Fill out the HighSpeedCoreIDs in a Processor resource from the given 469dba0c291SJonathan Doman * OperatingConfig D-Bus property. 470dba0c291SJonathan Doman * 471dba0c291SJonathan Doman * @param[in,out] aResp Async HTTP response. 472dba0c291SJonathan Doman * @param[in] baseSpeedSettings Full list of base speed priority groups, 473dba0c291SJonathan Doman * to use to determine the list of high 474dba0c291SJonathan Doman * speed cores. 475dba0c291SJonathan Doman */ 476dba0c291SJonathan Doman inline void highSpeedCoreIdsHandler( 4778d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& aResp, 478dba0c291SJonathan Doman const BaseSpeedPrioritySettingsProperty& baseSpeedSettings) 479dba0c291SJonathan Doman { 480dba0c291SJonathan Doman // The D-Bus property does not indicate which bucket is the "high 481dba0c291SJonathan Doman // priority" group, so let's discern that by looking for the one with 482dba0c291SJonathan Doman // highest base frequency. 483dba0c291SJonathan Doman auto highPriorityGroup = baseSpeedSettings.cend(); 484dba0c291SJonathan Doman uint32_t highestBaseSpeed = 0; 485dba0c291SJonathan Doman for (auto it = baseSpeedSettings.cbegin(); it != baseSpeedSettings.cend(); 486dba0c291SJonathan Doman ++it) 487dba0c291SJonathan Doman { 488dba0c291SJonathan Doman const uint32_t baseFreq = std::get<uint32_t>(*it); 489dba0c291SJonathan Doman if (baseFreq > highestBaseSpeed) 490dba0c291SJonathan Doman { 491dba0c291SJonathan Doman highestBaseSpeed = baseFreq; 492dba0c291SJonathan Doman highPriorityGroup = it; 493dba0c291SJonathan Doman } 494dba0c291SJonathan Doman } 495dba0c291SJonathan Doman 496dba0c291SJonathan Doman nlohmann::json& jsonCoreIds = aResp->res.jsonValue["HighSpeedCoreIDs"]; 497dba0c291SJonathan Doman jsonCoreIds = nlohmann::json::array(); 498dba0c291SJonathan Doman 499dba0c291SJonathan Doman // There may not be any entries in the D-Bus property, so only populate 500dba0c291SJonathan Doman // if there was actually something there. 501dba0c291SJonathan Doman if (highPriorityGroup != baseSpeedSettings.cend()) 502dba0c291SJonathan Doman { 503dba0c291SJonathan Doman jsonCoreIds = std::get<std::vector<uint32_t>>(*highPriorityGroup); 504dba0c291SJonathan Doman } 505dba0c291SJonathan Doman } 506dba0c291SJonathan Doman 507dba0c291SJonathan Doman /** 508dba0c291SJonathan Doman * Fill out OperatingConfig related items in a Processor resource by requesting 509dba0c291SJonathan Doman * data from the given D-Bus object. 510dba0c291SJonathan Doman * 511dba0c291SJonathan Doman * @param[in,out] aResp Async HTTP response. 512dba0c291SJonathan Doman * @param[in] cpuId CPU D-Bus name. 513dba0c291SJonathan Doman * @param[in] service D-Bus service to query. 514dba0c291SJonathan Doman * @param[in] objPath D-Bus object to query. 515dba0c291SJonathan Doman */ 5168d1b46d7Szhanghch05 inline void getCpuConfigData(const std::shared_ptr<bmcweb::AsyncResp>& aResp, 517dba0c291SJonathan Doman const std::string& cpuId, 518dba0c291SJonathan Doman const std::string& service, 519dba0c291SJonathan Doman const std::string& objPath) 520dba0c291SJonathan Doman { 521dba0c291SJonathan Doman BMCWEB_LOG_INFO << "Getting CPU operating configs for " << cpuId; 522dba0c291SJonathan Doman 523dba0c291SJonathan Doman // First, GetAll CurrentOperatingConfig properties on the object 524351053f2SKrzysztof Grobelny sdbusplus::asio::getAllProperties( 525351053f2SKrzysztof Grobelny *crow::connections::systemBus, service, objPath, 526351053f2SKrzysztof Grobelny "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig", 527351053f2SKrzysztof Grobelny [aResp, cpuId, 5285e7e2dc5SEd Tanous service](const boost::system::error_code& ec, 529351053f2SKrzysztof Grobelny const dbus::utility::DBusPropertiesMap& properties) { 530dba0c291SJonathan Doman if (ec) 531dba0c291SJonathan Doman { 532002d39b4SEd Tanous BMCWEB_LOG_WARNING << "D-Bus error: " << ec << ", " << ec.message(); 533dba0c291SJonathan Doman messages::internalError(aResp->res); 534dba0c291SJonathan Doman return; 535dba0c291SJonathan Doman } 536dba0c291SJonathan Doman 537dba0c291SJonathan Doman nlohmann::json& json = aResp->res.jsonValue; 538dba0c291SJonathan Doman 539351053f2SKrzysztof Grobelny const sdbusplus::message::object_path* appliedConfig = nullptr; 540351053f2SKrzysztof Grobelny const bool* baseSpeedPriorityEnabled = nullptr; 541351053f2SKrzysztof Grobelny 542351053f2SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 543351053f2SKrzysztof Grobelny dbus_utils::UnpackErrorPrinter(), properties, "AppliedConfig", 544351053f2SKrzysztof Grobelny appliedConfig, "BaseSpeedPriorityEnabled", 545351053f2SKrzysztof Grobelny baseSpeedPriorityEnabled); 546351053f2SKrzysztof Grobelny 547351053f2SKrzysztof Grobelny if (!success) 548dba0c291SJonathan Doman { 549351053f2SKrzysztof Grobelny messages::internalError(aResp->res); 550351053f2SKrzysztof Grobelny return; 551dba0c291SJonathan Doman } 552dba0c291SJonathan Doman 553351053f2SKrzysztof Grobelny if (appliedConfig != nullptr) 554351053f2SKrzysztof Grobelny { 555351053f2SKrzysztof Grobelny const std::string& dbusPath = appliedConfig->str; 5561476687dSEd Tanous nlohmann::json::object_t operatingConfig; 557*ef4c65b7SEd Tanous operatingConfig["@odata.id"] = boost::urls::format( 558*ef4c65b7SEd Tanous "/redfish/v1/Systems/system/Processors/{}/OperatingConfigs", 559*ef4c65b7SEd Tanous cpuId); 5601476687dSEd Tanous json["OperatingConfigs"] = std::move(operatingConfig); 561dba0c291SJonathan Doman 562dba0c291SJonathan Doman // Reuse the D-Bus config object name for the Redfish 563dba0c291SJonathan Doman // URI 564dba0c291SJonathan Doman size_t baseNamePos = dbusPath.rfind('/'); 565dba0c291SJonathan Doman if (baseNamePos == std::string::npos || 566dba0c291SJonathan Doman baseNamePos == (dbusPath.size() - 1)) 567dba0c291SJonathan Doman { 568dba0c291SJonathan Doman // If the AppliedConfig was somehow not a valid path, 569dba0c291SJonathan Doman // skip adding any more properties, since everything 570dba0c291SJonathan Doman // else is tied to this applied config. 571dba0c291SJonathan Doman messages::internalError(aResp->res); 572351053f2SKrzysztof Grobelny return; 573dba0c291SJonathan Doman } 5741476687dSEd Tanous nlohmann::json::object_t appliedOperatingConfig; 575*ef4c65b7SEd Tanous appliedOperatingConfig["@odata.id"] = boost::urls::format( 576*ef4c65b7SEd Tanous "/redfish/v1/Systems/system/Processors/{}/OperatingConfigs/{}", 577*ef4c65b7SEd Tanous cpuId, dbusPath.substr(baseNamePos + 1)); 578351053f2SKrzysztof Grobelny json["AppliedOperatingConfig"] = std::move(appliedOperatingConfig); 579dba0c291SJonathan Doman 580dba0c291SJonathan Doman // Once we found the current applied config, queue another 581dba0c291SJonathan Doman // request to read the base freq core ids out of that 582dba0c291SJonathan Doman // config. 583002d39b4SEd Tanous sdbusplus::asio::getProperty<BaseSpeedPrioritySettingsProperty>( 5841e1e598dSJonathan Doman *crow::connections::systemBus, service, dbusPath, 5851e1e598dSJonathan Doman "xyz.openbmc_project.Inventory.Item.Cpu." 5861e1e598dSJonathan Doman "OperatingConfig", 5871e1e598dSJonathan Doman "BaseSpeedPrioritySettings", 588351053f2SKrzysztof Grobelny [aResp]( 5895e7e2dc5SEd Tanous const boost::system::error_code& ec2, 590351053f2SKrzysztof Grobelny const BaseSpeedPrioritySettingsProperty& baseSpeedList) { 5918a592810SEd Tanous if (ec2) 592dba0c291SJonathan Doman { 593351053f2SKrzysztof Grobelny BMCWEB_LOG_WARNING << "D-Bus Property Get error: " << ec2; 594dba0c291SJonathan Doman messages::internalError(aResp->res); 595dba0c291SJonathan Doman return; 596dba0c291SJonathan Doman } 5971e1e598dSJonathan Doman 5981e1e598dSJonathan Doman highSpeedCoreIdsHandler(aResp, baseSpeedList); 5991e1e598dSJonathan Doman }); 600dba0c291SJonathan Doman } 601351053f2SKrzysztof Grobelny 602351053f2SKrzysztof Grobelny if (baseSpeedPriorityEnabled != nullptr) 603dba0c291SJonathan Doman { 604dba0c291SJonathan Doman json["BaseSpeedPriorityState"] = 605351053f2SKrzysztof Grobelny *baseSpeedPriorityEnabled ? "Enabled" : "Disabled"; 606dba0c291SJonathan Doman } 607351053f2SKrzysztof Grobelny }); 608dba0c291SJonathan Doman } 609dba0c291SJonathan Doman 610cba4f448SSunnySrivastava1984 /** 611cba4f448SSunnySrivastava1984 * @brief Fill out location info of a processor by 612cba4f448SSunnySrivastava1984 * requesting data from the given D-Bus object. 613cba4f448SSunnySrivastava1984 * 614cba4f448SSunnySrivastava1984 * @param[in,out] aResp Async HTTP response. 615cba4f448SSunnySrivastava1984 * @param[in] service D-Bus service to query. 616cba4f448SSunnySrivastava1984 * @param[in] objPath D-Bus object to query. 617cba4f448SSunnySrivastava1984 */ 6188d1b46d7Szhanghch05 inline void getCpuLocationCode(std::shared_ptr<bmcweb::AsyncResp> aResp, 619cba4f448SSunnySrivastava1984 const std::string& service, 620cba4f448SSunnySrivastava1984 const std::string& objPath) 621cba4f448SSunnySrivastava1984 { 622cba4f448SSunnySrivastava1984 BMCWEB_LOG_DEBUG << "Get Cpu Location Data"; 6231e1e598dSJonathan Doman sdbusplus::asio::getProperty<std::string>( 6241e1e598dSJonathan Doman *crow::connections::systemBus, service, objPath, 6251e1e598dSJonathan Doman "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode", 6265e7e2dc5SEd Tanous [objPath, aResp{std::move(aResp)}](const boost::system::error_code& ec, 6271e1e598dSJonathan Doman const std::string& property) { 628cba4f448SSunnySrivastava1984 if (ec) 629cba4f448SSunnySrivastava1984 { 630cba4f448SSunnySrivastava1984 BMCWEB_LOG_DEBUG << "DBUS response error"; 631cba4f448SSunnySrivastava1984 messages::internalError(aResp->res); 632cba4f448SSunnySrivastava1984 return; 633cba4f448SSunnySrivastava1984 } 634cba4f448SSunnySrivastava1984 635cba4f448SSunnySrivastava1984 aResp->res.jsonValue["Location"]["PartLocation"]["ServiceLabel"] = 6361e1e598dSJonathan Doman property; 6371e1e598dSJonathan Doman }); 638cba4f448SSunnySrivastava1984 } 639cba4f448SSunnySrivastava1984 640c951448aSJonathan Doman /** 64149e429caSJonathan Doman * Populate the unique identifier in a Processor resource by requesting data 64249e429caSJonathan Doman * from the given D-Bus object. 64349e429caSJonathan Doman * 64449e429caSJonathan Doman * @param[in,out] aResp Async HTTP response. 64549e429caSJonathan Doman * @param[in] service D-Bus service to query. 64649e429caSJonathan Doman * @param[in] objPath D-Bus object to query. 64749e429caSJonathan Doman */ 64849e429caSJonathan Doman inline void getCpuUniqueId(const std::shared_ptr<bmcweb::AsyncResp>& aResp, 64949e429caSJonathan Doman const std::string& service, 65049e429caSJonathan Doman const std::string& objectPath) 65149e429caSJonathan Doman { 65249e429caSJonathan Doman BMCWEB_LOG_DEBUG << "Get CPU UniqueIdentifier"; 6531e1e598dSJonathan Doman sdbusplus::asio::getProperty<std::string>( 6541e1e598dSJonathan Doman *crow::connections::systemBus, service, objectPath, 6551e1e598dSJonathan Doman "xyz.openbmc_project.Inventory.Decorator.UniqueIdentifier", 6561e1e598dSJonathan Doman "UniqueIdentifier", 6575e7e2dc5SEd Tanous [aResp](const boost::system::error_code& ec, const std::string& id) { 6581e1e598dSJonathan Doman if (ec) 65949e429caSJonathan Doman { 66049e429caSJonathan Doman BMCWEB_LOG_ERROR << "Failed to read cpu unique id: " << ec; 66149e429caSJonathan Doman messages::internalError(aResp->res); 66249e429caSJonathan Doman return; 66349e429caSJonathan Doman } 664002d39b4SEd Tanous aResp->res.jsonValue["ProcessorId"]["ProtectedIdentificationNumber"] = 665002d39b4SEd Tanous id; 6661e1e598dSJonathan Doman }); 66749e429caSJonathan Doman } 66849e429caSJonathan Doman 66949e429caSJonathan Doman /** 670c951448aSJonathan Doman * Find the D-Bus object representing the requested Processor, and call the 671c951448aSJonathan Doman * handler with the results. If matching object is not found, add 404 error to 672c951448aSJonathan Doman * response and don't call the handler. 673c951448aSJonathan Doman * 674c951448aSJonathan Doman * @param[in,out] resp Async HTTP response. 675c951448aSJonathan Doman * @param[in] processorId Redfish Processor Id. 676c951448aSJonathan Doman * @param[in] handler Callback to continue processing request upon 677c951448aSJonathan Doman * successfully finding object. 678c951448aSJonathan Doman */ 679c951448aSJonathan Doman template <typename Handler> 6808d1b46d7Szhanghch05 inline void getProcessorObject(const std::shared_ptr<bmcweb::AsyncResp>& resp, 681c951448aSJonathan Doman const std::string& processorId, 682c951448aSJonathan Doman Handler&& handler) 683ac6a4445SGunnar Mills { 684ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "Get available system processor resources."; 685ac6a4445SGunnar Mills 686c951448aSJonathan Doman // GetSubTree on all interfaces which provide info about a Processor 687e99073f5SGeorge Liu constexpr std::array<std::string_view, 8> interfaces = { 688e99073f5SGeorge Liu "xyz.openbmc_project.Common.UUID", 689e99073f5SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.Asset", 690e99073f5SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.Revision", 691e99073f5SGeorge Liu "xyz.openbmc_project.Inventory.Item.Cpu", 692e99073f5SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.LocationCode", 693e99073f5SGeorge Liu "xyz.openbmc_project.Inventory.Item.Accelerator", 694e99073f5SGeorge Liu "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig", 695e99073f5SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.UniqueIdentifier"}; 696e99073f5SGeorge Liu dbus::utility::getSubTree( 697e99073f5SGeorge Liu "/xyz/openbmc_project/inventory", 0, interfaces, 698c951448aSJonathan Doman [resp, processorId, handler = std::forward<Handler>(handler)]( 699e99073f5SGeorge Liu const boost::system::error_code& ec, 700e99073f5SGeorge Liu const dbus::utility::MapperGetSubTreeResponse& subtree) { 701ac6a4445SGunnar Mills if (ec) 702ac6a4445SGunnar Mills { 703c951448aSJonathan Doman BMCWEB_LOG_DEBUG << "DBUS response error: " << ec; 704c951448aSJonathan Doman messages::internalError(resp->res); 705ac6a4445SGunnar Mills return; 706ac6a4445SGunnar Mills } 7072bab9831SJonathan Doman for (const auto& [objectPath, serviceMap] : subtree) 708ac6a4445SGunnar Mills { 7092bab9831SJonathan Doman // Ignore any objects which don't end with our desired cpu name 71011ba3979SEd Tanous if (!objectPath.ends_with(processorId)) 711ac6a4445SGunnar Mills { 7122bab9831SJonathan Doman continue; 713ac6a4445SGunnar Mills } 7142bab9831SJonathan Doman 715c951448aSJonathan Doman bool found = false; 716c951448aSJonathan Doman // Filter out objects that don't have the CPU-specific 717c951448aSJonathan Doman // interfaces to make sure we can return 404 on non-CPUs 718c951448aSJonathan Doman // (e.g. /redfish/../Processors/dimm0) 7192bab9831SJonathan Doman for (const auto& [serviceName, interfaceList] : serviceMap) 720ac6a4445SGunnar Mills { 721c951448aSJonathan Doman if (std::find_first_of( 722c951448aSJonathan Doman interfaceList.begin(), interfaceList.end(), 723c951448aSJonathan Doman processorInterfaces.begin(), 724c951448aSJonathan Doman processorInterfaces.end()) != interfaceList.end()) 7252bab9831SJonathan Doman { 726c951448aSJonathan Doman found = true; 727c951448aSJonathan Doman break; 728c951448aSJonathan Doman } 729c951448aSJonathan Doman } 730c951448aSJonathan Doman 731c951448aSJonathan Doman if (!found) 7322bab9831SJonathan Doman { 733c951448aSJonathan Doman continue; 734ac6a4445SGunnar Mills } 735c951448aSJonathan Doman 736c951448aSJonathan Doman // Process the first object which does match our cpu name and 737c951448aSJonathan Doman // required interfaces, and potentially ignore any other 738c951448aSJonathan Doman // matching objects. Assume all interfaces we want to process 739c951448aSJonathan Doman // must be on the same object path. 740c951448aSJonathan Doman 7418a592810SEd Tanous handler(objectPath, serviceMap); 742ac6a4445SGunnar Mills return; 743ac6a4445SGunnar Mills } 744c951448aSJonathan Doman messages::resourceNotFound(resp->res, "Processor", processorId); 745e99073f5SGeorge Liu }); 746ac6a4445SGunnar Mills } 747ac6a4445SGunnar Mills 7488d1b46d7Szhanghch05 inline void getProcessorData(const std::shared_ptr<bmcweb::AsyncResp>& aResp, 749c951448aSJonathan Doman const std::string& processorId, 750c951448aSJonathan Doman const std::string& objectPath, 7515df6eda2SShantappa Teekappanavar const dbus::utility::MapperServiceMap& serviceMap) 752c951448aSJonathan Doman { 753c951448aSJonathan Doman for (const auto& [serviceName, interfaceList] : serviceMap) 754c951448aSJonathan Doman { 755c951448aSJonathan Doman for (const auto& interface : interfaceList) 756c951448aSJonathan Doman { 757c951448aSJonathan Doman if (interface == "xyz.openbmc_project.Inventory.Decorator.Asset") 758c951448aSJonathan Doman { 759c951448aSJonathan Doman getCpuAssetData(aResp, serviceName, objectPath); 760c951448aSJonathan Doman } 7610fda0f12SGeorge Liu else if (interface == 7620fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.Revision") 763c951448aSJonathan Doman { 764c951448aSJonathan Doman getCpuRevisionData(aResp, serviceName, objectPath); 765c951448aSJonathan Doman } 766c951448aSJonathan Doman else if (interface == "xyz.openbmc_project.Inventory.Item.Cpu") 767c951448aSJonathan Doman { 768c951448aSJonathan Doman getCpuDataByService(aResp, processorId, serviceName, 769c951448aSJonathan Doman objectPath); 770c951448aSJonathan Doman } 7710fda0f12SGeorge Liu else if (interface == 7720fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Item.Accelerator") 773c951448aSJonathan Doman { 774c951448aSJonathan Doman getAcceleratorDataByService(aResp, processorId, serviceName, 775c951448aSJonathan Doman objectPath); 776c951448aSJonathan Doman } 7770fda0f12SGeorge Liu else if ( 7780fda0f12SGeorge Liu interface == 7790fda0f12SGeorge Liu "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig") 780c951448aSJonathan Doman { 781c951448aSJonathan Doman getCpuConfigData(aResp, processorId, serviceName, objectPath); 782c951448aSJonathan Doman } 7830fda0f12SGeorge Liu else if (interface == 7840fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.LocationCode") 785c951448aSJonathan Doman { 786c951448aSJonathan Doman getCpuLocationCode(aResp, serviceName, objectPath); 787c951448aSJonathan Doman } 78871b82f26SSharad Yadav else if (interface == "xyz.openbmc_project.Common.UUID") 78971b82f26SSharad Yadav { 79071b82f26SSharad Yadav getProcessorUUID(aResp, serviceName, objectPath); 79171b82f26SSharad Yadav } 7920fda0f12SGeorge Liu else if (interface == 7930fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.UniqueIdentifier") 79449e429caSJonathan Doman { 79549e429caSJonathan Doman getCpuUniqueId(aResp, serviceName, objectPath); 79649e429caSJonathan Doman } 797c951448aSJonathan Doman } 798c951448aSJonathan Doman } 799c951448aSJonathan Doman } 800c951448aSJonathan Doman 801dba0c291SJonathan Doman /** 802dba0c291SJonathan Doman * Request all the properties for the given D-Bus object and fill out the 803dba0c291SJonathan Doman * related entries in the Redfish OperatingConfig response. 804dba0c291SJonathan Doman * 805dba0c291SJonathan Doman * @param[in,out] aResp Async HTTP response. 806dba0c291SJonathan Doman * @param[in] service D-Bus service name to query. 807dba0c291SJonathan Doman * @param[in] objPath D-Bus object to query. 808dba0c291SJonathan Doman */ 8098d1b46d7Szhanghch05 inline void 8108d1b46d7Szhanghch05 getOperatingConfigData(const std::shared_ptr<bmcweb::AsyncResp>& aResp, 811dba0c291SJonathan Doman const std::string& service, 812dba0c291SJonathan Doman const std::string& objPath) 813dba0c291SJonathan Doman { 814351053f2SKrzysztof Grobelny sdbusplus::asio::getAllProperties( 815351053f2SKrzysztof Grobelny *crow::connections::systemBus, service, objPath, 816351053f2SKrzysztof Grobelny "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig", 8175e7e2dc5SEd Tanous [aResp](const boost::system::error_code& ec, 818351053f2SKrzysztof Grobelny const dbus::utility::DBusPropertiesMap& properties) { 819dba0c291SJonathan Doman if (ec) 820dba0c291SJonathan Doman { 821002d39b4SEd Tanous BMCWEB_LOG_WARNING << "D-Bus error: " << ec << ", " << ec.message(); 822dba0c291SJonathan Doman messages::internalError(aResp->res); 823dba0c291SJonathan Doman return; 824dba0c291SJonathan Doman } 825dba0c291SJonathan Doman 826351053f2SKrzysztof Grobelny const size_t* availableCoreCount = nullptr; 827351053f2SKrzysztof Grobelny const uint32_t* baseSpeed = nullptr; 828351053f2SKrzysztof Grobelny const uint32_t* maxJunctionTemperature = nullptr; 829351053f2SKrzysztof Grobelny const uint32_t* maxSpeed = nullptr; 830351053f2SKrzysztof Grobelny const uint32_t* powerLimit = nullptr; 831351053f2SKrzysztof Grobelny const TurboProfileProperty* turboProfile = nullptr; 832351053f2SKrzysztof Grobelny const BaseSpeedPrioritySettingsProperty* baseSpeedPrioritySettings = 833351053f2SKrzysztof Grobelny nullptr; 834351053f2SKrzysztof Grobelny 835351053f2SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 836351053f2SKrzysztof Grobelny dbus_utils::UnpackErrorPrinter(), properties, "AvailableCoreCount", 837351053f2SKrzysztof Grobelny availableCoreCount, "BaseSpeed", baseSpeed, 838351053f2SKrzysztof Grobelny "MaxJunctionTemperature", maxJunctionTemperature, "MaxSpeed", 839351053f2SKrzysztof Grobelny maxSpeed, "PowerLimit", powerLimit, "TurboProfile", turboProfile, 840351053f2SKrzysztof Grobelny "BaseSpeedPrioritySettings", baseSpeedPrioritySettings); 841351053f2SKrzysztof Grobelny 842351053f2SKrzysztof Grobelny if (!success) 843dba0c291SJonathan Doman { 844351053f2SKrzysztof Grobelny messages::internalError(aResp->res); 845351053f2SKrzysztof Grobelny return; 846dba0c291SJonathan Doman } 847dba0c291SJonathan Doman 848351053f2SKrzysztof Grobelny nlohmann::json& json = aResp->res.jsonValue; 849351053f2SKrzysztof Grobelny 850351053f2SKrzysztof Grobelny if (availableCoreCount != nullptr) 851351053f2SKrzysztof Grobelny { 852351053f2SKrzysztof Grobelny json["TotalAvailableCoreCount"] = *availableCoreCount; 853351053f2SKrzysztof Grobelny } 854351053f2SKrzysztof Grobelny 855351053f2SKrzysztof Grobelny if (baseSpeed != nullptr) 856351053f2SKrzysztof Grobelny { 857351053f2SKrzysztof Grobelny json["BaseSpeedMHz"] = *baseSpeed; 858351053f2SKrzysztof Grobelny } 859351053f2SKrzysztof Grobelny 860351053f2SKrzysztof Grobelny if (maxJunctionTemperature != nullptr) 861351053f2SKrzysztof Grobelny { 862351053f2SKrzysztof Grobelny json["MaxJunctionTemperatureCelsius"] = *maxJunctionTemperature; 863351053f2SKrzysztof Grobelny } 864351053f2SKrzysztof Grobelny 865351053f2SKrzysztof Grobelny if (maxSpeed != nullptr) 866351053f2SKrzysztof Grobelny { 867351053f2SKrzysztof Grobelny json["MaxSpeedMHz"] = *maxSpeed; 868351053f2SKrzysztof Grobelny } 869351053f2SKrzysztof Grobelny 870351053f2SKrzysztof Grobelny if (powerLimit != nullptr) 871351053f2SKrzysztof Grobelny { 872351053f2SKrzysztof Grobelny json["TDPWatts"] = *powerLimit; 873351053f2SKrzysztof Grobelny } 874351053f2SKrzysztof Grobelny 875351053f2SKrzysztof Grobelny if (turboProfile != nullptr) 876351053f2SKrzysztof Grobelny { 877dba0c291SJonathan Doman nlohmann::json& turboArray = json["TurboProfile"]; 878dba0c291SJonathan Doman turboArray = nlohmann::json::array(); 879351053f2SKrzysztof Grobelny for (const auto& [turboSpeed, coreCount] : *turboProfile) 880dba0c291SJonathan Doman { 8811476687dSEd Tanous nlohmann::json::object_t turbo; 8821476687dSEd Tanous turbo["ActiveCoreCount"] = coreCount; 8831476687dSEd Tanous turbo["MaxSpeedMHz"] = turboSpeed; 884b2ba3072SPatrick Williams turboArray.emplace_back(std::move(turbo)); 885dba0c291SJonathan Doman } 886dba0c291SJonathan Doman } 887dba0c291SJonathan Doman 888351053f2SKrzysztof Grobelny if (baseSpeedPrioritySettings != nullptr) 889351053f2SKrzysztof Grobelny { 890351053f2SKrzysztof Grobelny nlohmann::json& baseSpeedArray = json["BaseSpeedPrioritySettings"]; 891dba0c291SJonathan Doman baseSpeedArray = nlohmann::json::array(); 892351053f2SKrzysztof Grobelny for (const auto& [baseSpeedMhz, coreList] : 893351053f2SKrzysztof Grobelny *baseSpeedPrioritySettings) 894dba0c291SJonathan Doman { 8951476687dSEd Tanous nlohmann::json::object_t speed; 8961476687dSEd Tanous speed["CoreCount"] = coreList.size(); 8971476687dSEd Tanous speed["CoreIDs"] = coreList; 898351053f2SKrzysztof Grobelny speed["BaseSpeedMHz"] = baseSpeedMhz; 899b2ba3072SPatrick Williams baseSpeedArray.emplace_back(std::move(speed)); 900dba0c291SJonathan Doman } 901dba0c291SJonathan Doman } 902351053f2SKrzysztof Grobelny }); 903dba0c291SJonathan Doman } 904dba0c291SJonathan Doman 9053cde86f1SJonathan Doman /** 9063cde86f1SJonathan Doman * Handle the D-Bus response from attempting to set the CPU's AppliedConfig 9073cde86f1SJonathan Doman * property. Main task is to translate error messages into Redfish errors. 9083cde86f1SJonathan Doman * 9093cde86f1SJonathan Doman * @param[in,out] resp HTTP response. 9103cde86f1SJonathan Doman * @param[in] setPropVal Value which we attempted to set. 9113cde86f1SJonathan Doman * @param[in] ec D-Bus response error code. 9123cde86f1SJonathan Doman * @param[in] msg D-Bus response message. 9133cde86f1SJonathan Doman */ 9143cde86f1SJonathan Doman inline void 9153cde86f1SJonathan Doman handleAppliedConfigResponse(const std::shared_ptr<bmcweb::AsyncResp>& resp, 9163cde86f1SJonathan Doman const std::string& setPropVal, 9175e7e2dc5SEd Tanous const boost::system::error_code& ec, 91859d494eeSPatrick Williams const sdbusplus::message_t& msg) 9193cde86f1SJonathan Doman { 9203cde86f1SJonathan Doman if (!ec) 9213cde86f1SJonathan Doman { 9223cde86f1SJonathan Doman BMCWEB_LOG_DEBUG << "Set Property succeeded"; 9233cde86f1SJonathan Doman return; 9243cde86f1SJonathan Doman } 9253cde86f1SJonathan Doman 9263cde86f1SJonathan Doman BMCWEB_LOG_DEBUG << "Set Property failed: " << ec; 9273cde86f1SJonathan Doman 9283cde86f1SJonathan Doman const sd_bus_error* dbusError = msg.get_error(); 9293cde86f1SJonathan Doman if (dbusError == nullptr) 9303cde86f1SJonathan Doman { 9313cde86f1SJonathan Doman messages::internalError(resp->res); 9323cde86f1SJonathan Doman return; 9333cde86f1SJonathan Doman } 9343cde86f1SJonathan Doman 9353cde86f1SJonathan Doman // The asio error code doesn't know about our custom errors, so we have to 9363cde86f1SJonathan Doman // parse the error string. Some of these D-Bus -> Redfish translations are a 9373cde86f1SJonathan Doman // stretch, but it's good to try to communicate something vaguely useful. 9383cde86f1SJonathan Doman if (strcmp(dbusError->name, 9393cde86f1SJonathan Doman "xyz.openbmc_project.Common.Error.InvalidArgument") == 0) 9403cde86f1SJonathan Doman { 9413cde86f1SJonathan Doman // Service did not like the object_path we tried to set. 9423cde86f1SJonathan Doman messages::propertyValueIncorrect( 9433cde86f1SJonathan Doman resp->res, "AppliedOperatingConfig/@odata.id", setPropVal); 9443cde86f1SJonathan Doman } 9453cde86f1SJonathan Doman else if (strcmp(dbusError->name, 9463cde86f1SJonathan Doman "xyz.openbmc_project.Common.Error.NotAllowed") == 0) 9473cde86f1SJonathan Doman { 9483cde86f1SJonathan Doman // Service indicates we can never change the config for this processor. 9493cde86f1SJonathan Doman messages::propertyNotWritable(resp->res, "AppliedOperatingConfig"); 9503cde86f1SJonathan Doman } 9513cde86f1SJonathan Doman else if (strcmp(dbusError->name, 9523cde86f1SJonathan Doman "xyz.openbmc_project.Common.Error.Unavailable") == 0) 9533cde86f1SJonathan Doman { 9543cde86f1SJonathan Doman // Service indicates the config cannot be changed right now, but maybe 9553cde86f1SJonathan Doman // in a different system state. 9563cde86f1SJonathan Doman messages::resourceInStandby(resp->res); 9573cde86f1SJonathan Doman } 9583cde86f1SJonathan Doman else 9593cde86f1SJonathan Doman { 9603cde86f1SJonathan Doman messages::internalError(resp->res); 9613cde86f1SJonathan Doman } 9623cde86f1SJonathan Doman } 9633cde86f1SJonathan Doman 9643cde86f1SJonathan Doman /** 9653cde86f1SJonathan Doman * Handle the PATCH operation of the AppliedOperatingConfig property. Do basic 9663cde86f1SJonathan Doman * validation of the input data, and then set the D-Bus property. 9673cde86f1SJonathan Doman * 9683cde86f1SJonathan Doman * @param[in,out] resp Async HTTP response. 9693cde86f1SJonathan Doman * @param[in] processorId Processor's Id. 9703cde86f1SJonathan Doman * @param[in] appliedConfigUri New property value to apply. 9713cde86f1SJonathan Doman * @param[in] cpuObjectPath Path of CPU object to modify. 9723cde86f1SJonathan Doman * @param[in] serviceMap Service map for CPU object. 9733cde86f1SJonathan Doman */ 9743cde86f1SJonathan Doman inline void patchAppliedOperatingConfig( 9753cde86f1SJonathan Doman const std::shared_ptr<bmcweb::AsyncResp>& resp, 9763cde86f1SJonathan Doman const std::string& processorId, const std::string& appliedConfigUri, 9775df6eda2SShantappa Teekappanavar const std::string& cpuObjectPath, 9785df6eda2SShantappa Teekappanavar const dbus::utility::MapperServiceMap& serviceMap) 9793cde86f1SJonathan Doman { 9803cde86f1SJonathan Doman // Check that the property even exists by checking for the interface 9813cde86f1SJonathan Doman const std::string* controlService = nullptr; 9823cde86f1SJonathan Doman for (const auto& [serviceName, interfaceList] : serviceMap) 9833cde86f1SJonathan Doman { 9843cde86f1SJonathan Doman if (std::find(interfaceList.begin(), interfaceList.end(), 9853cde86f1SJonathan Doman "xyz.openbmc_project.Control.Processor." 9863cde86f1SJonathan Doman "CurrentOperatingConfig") != interfaceList.end()) 9873cde86f1SJonathan Doman { 9883cde86f1SJonathan Doman controlService = &serviceName; 9893cde86f1SJonathan Doman break; 9903cde86f1SJonathan Doman } 9913cde86f1SJonathan Doman } 9923cde86f1SJonathan Doman 9933cde86f1SJonathan Doman if (controlService == nullptr) 9943cde86f1SJonathan Doman { 9953cde86f1SJonathan Doman messages::internalError(resp->res); 9963cde86f1SJonathan Doman return; 9973cde86f1SJonathan Doman } 9983cde86f1SJonathan Doman 9993cde86f1SJonathan Doman // Check that the config URI is a child of the cpu URI being patched. 10003cde86f1SJonathan Doman std::string expectedPrefix("/redfish/v1/Systems/system/Processors/"); 10013cde86f1SJonathan Doman expectedPrefix += processorId; 10023cde86f1SJonathan Doman expectedPrefix += "/OperatingConfigs/"; 100311ba3979SEd Tanous if (!appliedConfigUri.starts_with(expectedPrefix) || 10043cde86f1SJonathan Doman expectedPrefix.size() == appliedConfigUri.size()) 10053cde86f1SJonathan Doman { 10063cde86f1SJonathan Doman messages::propertyValueIncorrect( 10073cde86f1SJonathan Doman resp->res, "AppliedOperatingConfig/@odata.id", appliedConfigUri); 10083cde86f1SJonathan Doman return; 10093cde86f1SJonathan Doman } 10103cde86f1SJonathan Doman 10113cde86f1SJonathan Doman // Generate the D-Bus path of the OperatingConfig object, by assuming it's a 10123cde86f1SJonathan Doman // direct child of the CPU object. 10133cde86f1SJonathan Doman // Strip the expectedPrefix from the config URI to get the "filename", and 10143cde86f1SJonathan Doman // append to the CPU's path. 10153cde86f1SJonathan Doman std::string configBaseName = appliedConfigUri.substr(expectedPrefix.size()); 10163cde86f1SJonathan Doman sdbusplus::message::object_path configPath(cpuObjectPath); 10173cde86f1SJonathan Doman configPath /= configBaseName; 10183cde86f1SJonathan Doman 10193cde86f1SJonathan Doman BMCWEB_LOG_INFO << "Setting config to " << configPath.str; 10203cde86f1SJonathan Doman 10213cde86f1SJonathan Doman // Set the property, with handler to check error responses 10223cde86f1SJonathan Doman crow::connections::systemBus->async_method_call( 10235e7e2dc5SEd Tanous [resp, appliedConfigUri](const boost::system::error_code& ec, 102459d494eeSPatrick Williams const sdbusplus::message_t& msg) { 10253cde86f1SJonathan Doman handleAppliedConfigResponse(resp, appliedConfigUri, ec, msg); 10263cde86f1SJonathan Doman }, 10273cde86f1SJonathan Doman *controlService, cpuObjectPath, "org.freedesktop.DBus.Properties", 10283cde86f1SJonathan Doman "Set", "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig", 1029168e20c1SEd Tanous "AppliedConfig", dbus::utility::DbusVariantType(std::move(configPath))); 10303cde86f1SJonathan Doman } 10313cde86f1SJonathan Doman 103271a24ca4SNikhil Namjoshi inline void handleProcessorHead(crow::App& app, const crow::Request& req, 103371a24ca4SNikhil Namjoshi const std::shared_ptr<bmcweb::AsyncResp>& aResp, 103471a24ca4SNikhil Namjoshi const std::string& /* systemName */, 103571a24ca4SNikhil Namjoshi const std::string& /* processorId */) 103671a24ca4SNikhil Namjoshi { 103771a24ca4SNikhil Namjoshi if (!redfish::setUpRedfishRoute(app, req, aResp)) 103871a24ca4SNikhil Namjoshi { 103971a24ca4SNikhil Namjoshi return; 104071a24ca4SNikhil Namjoshi } 104171a24ca4SNikhil Namjoshi aResp->res.addHeader( 104271a24ca4SNikhil Namjoshi boost::beast::http::field::link, 104371a24ca4SNikhil Namjoshi "</redfish/v1/JsonSchemas/Processor/Processor.json>; rel=describedby"); 104471a24ca4SNikhil Namjoshi } 104571a24ca4SNikhil Namjoshi 104671a24ca4SNikhil Namjoshi inline void handleProcessorCollectionHead( 104771a24ca4SNikhil Namjoshi crow::App& app, const crow::Request& req, 104871a24ca4SNikhil Namjoshi const std::shared_ptr<bmcweb::AsyncResp>& aResp, 104971a24ca4SNikhil Namjoshi const std::string& /* systemName */) 105071a24ca4SNikhil Namjoshi { 105171a24ca4SNikhil Namjoshi if (!redfish::setUpRedfishRoute(app, req, aResp)) 105271a24ca4SNikhil Namjoshi { 105371a24ca4SNikhil Namjoshi return; 105471a24ca4SNikhil Namjoshi } 105571a24ca4SNikhil Namjoshi aResp->res.addHeader( 105671a24ca4SNikhil Namjoshi boost::beast::http::field::link, 105771a24ca4SNikhil Namjoshi "</redfish/v1/JsonSchemas/ProcessorCollection/ProcessorCollection.json>; rel=describedby"); 105871a24ca4SNikhil Namjoshi } 105971a24ca4SNikhil Namjoshi 10607e860f15SJohn Edward Broadbent inline void requestRoutesOperatingConfigCollection(App& app) 1061dba0c291SJonathan Doman { 10627e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 10637e860f15SJohn Edward Broadbent app, "/redfish/v1/Systems/system/Processors/<str>/OperatingConfigs/") 1064ed398213SEd Tanous .privileges(redfish::privileges::getOperatingConfigCollection) 1065002d39b4SEd Tanous .methods(boost::beast::http::verb::get)( 1066002d39b4SEd Tanous [&app](const crow::Request& req, 106745ca1b86SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 10687e860f15SJohn Edward Broadbent const std::string& cpuName) { 10693ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 107045ca1b86SEd Tanous { 107145ca1b86SEd Tanous return; 107245ca1b86SEd Tanous } 10738d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.type"] = 1074dba0c291SJonathan Doman "#OperatingConfigCollection.OperatingConfigCollection"; 1075*ef4c65b7SEd Tanous asyncResp->res.jsonValue["@odata.id"] = boost::urls::format( 1076*ef4c65b7SEd Tanous "/redfish/v1/Systems/system/Processors/{}/OperatingConfigs", 1077*ef4c65b7SEd Tanous cpuName); 10780fda0f12SGeorge Liu asyncResp->res.jsonValue["Name"] = "Operating Config Collection"; 1079dba0c291SJonathan Doman 10807e860f15SJohn Edward Broadbent // First find the matching CPU object so we know how to 10817e860f15SJohn Edward Broadbent // constrain our search for related Config objects. 10827a1dbc48SGeorge Liu const std::array<std::string_view, 1> interfaces = { 10837a1dbc48SGeorge Liu "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig"}; 10847a1dbc48SGeorge Liu dbus::utility::getSubTreePaths( 10857a1dbc48SGeorge Liu "/xyz/openbmc_project/inventory", 0, interfaces, 1086002d39b4SEd Tanous [asyncResp, cpuName]( 10877a1dbc48SGeorge Liu const boost::system::error_code& ec, 1088002d39b4SEd Tanous const dbus::utility::MapperGetSubTreePathsResponse& objects) { 1089dba0c291SJonathan Doman if (ec) 1090dba0c291SJonathan Doman { 1091dba0c291SJonathan Doman BMCWEB_LOG_WARNING << "D-Bus error: " << ec << ", " 1092dba0c291SJonathan Doman << ec.message(); 1093dba0c291SJonathan Doman messages::internalError(asyncResp->res); 1094dba0c291SJonathan Doman return; 1095dba0c291SJonathan Doman } 1096dba0c291SJonathan Doman 1097dba0c291SJonathan Doman for (const std::string& object : objects) 1098dba0c291SJonathan Doman { 109911ba3979SEd Tanous if (!object.ends_with(cpuName)) 1100dba0c291SJonathan Doman { 1101dba0c291SJonathan Doman continue; 1102dba0c291SJonathan Doman } 1103dba0c291SJonathan Doman 11047e860f15SJohn Edward Broadbent // Not expected that there will be multiple matching 11057e860f15SJohn Edward Broadbent // CPU objects, but if there are just use the first 11067e860f15SJohn Edward Broadbent // one. 1107dba0c291SJonathan Doman 11087e860f15SJohn Edward Broadbent // Use the common search routine to construct the 11097e860f15SJohn Edward Broadbent // Collection of all Config objects under this CPU. 11107a1dbc48SGeorge Liu constexpr std::array<std::string_view, 1> interface { 11117a1dbc48SGeorge Liu "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig" 11127a1dbc48SGeorge Liu }; 1113dba0c291SJonathan Doman collection_util::getCollectionMembers( 1114dba0c291SJonathan Doman asyncResp, 1115*ef4c65b7SEd Tanous boost::urls::format( 1116*ef4c65b7SEd Tanous "/redfish/v1/Systems/system/Processors/{}/OperatingConfigs", 1117*ef4c65b7SEd Tanous cpuName), 11187a1dbc48SGeorge Liu interface, object.c_str()); 1119dba0c291SJonathan Doman return; 1120dba0c291SJonathan Doman } 11217a1dbc48SGeorge Liu }); 11227e860f15SJohn Edward Broadbent }); 1123dba0c291SJonathan Doman } 1124dba0c291SJonathan Doman 11257e860f15SJohn Edward Broadbent inline void requestRoutesOperatingConfig(App& app) 1126dba0c291SJonathan Doman { 11277e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 11287e860f15SJohn Edward Broadbent app, 11297e860f15SJohn Edward Broadbent "/redfish/v1/Systems/system/Processors/<str>/OperatingConfigs/<str>/") 1130ed398213SEd Tanous .privileges(redfish::privileges::getOperatingConfig) 1131002d39b4SEd Tanous .methods(boost::beast::http::verb::get)( 1132002d39b4SEd Tanous [&app](const crow::Request& req, 113345ca1b86SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1134002d39b4SEd Tanous const std::string& cpuName, const std::string& configName) { 11353ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 113645ca1b86SEd Tanous { 113745ca1b86SEd Tanous return; 113845ca1b86SEd Tanous } 11397e860f15SJohn Edward Broadbent // Ask for all objects implementing OperatingConfig so we can search 11407e860f15SJohn Edward Broadbent // for one with a matching name 1141e99073f5SGeorge Liu constexpr std::array<std::string_view, 1> interfaces = { 1142e99073f5SGeorge Liu "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig"}; 1143e99073f5SGeorge Liu dbus::utility::getSubTree( 1144e99073f5SGeorge Liu "/xyz/openbmc_project/inventory", 0, interfaces, 114539662a3bSEd Tanous [asyncResp, cpuName, configName]( 1146e99073f5SGeorge Liu const boost::system::error_code& ec, 11475df6eda2SShantappa Teekappanavar const dbus::utility::MapperGetSubTreeResponse& subtree) { 1148dba0c291SJonathan Doman if (ec) 1149dba0c291SJonathan Doman { 1150dba0c291SJonathan Doman BMCWEB_LOG_WARNING << "D-Bus error: " << ec << ", " 1151dba0c291SJonathan Doman << ec.message(); 1152dba0c291SJonathan Doman messages::internalError(asyncResp->res); 1153dba0c291SJonathan Doman return; 1154dba0c291SJonathan Doman } 1155002d39b4SEd Tanous const std::string expectedEnding = cpuName + '/' + configName; 1156dba0c291SJonathan Doman for (const auto& [objectPath, serviceMap] : subtree) 1157dba0c291SJonathan Doman { 1158dba0c291SJonathan Doman // Ignore any configs without matching cpuX/configY 115911ba3979SEd Tanous if (!objectPath.ends_with(expectedEnding) || serviceMap.empty()) 1160dba0c291SJonathan Doman { 1161dba0c291SJonathan Doman continue; 1162dba0c291SJonathan Doman } 1163dba0c291SJonathan Doman 1164dba0c291SJonathan Doman nlohmann::json& json = asyncResp->res.jsonValue; 1165002d39b4SEd Tanous json["@odata.type"] = "#OperatingConfig.v1_0_0.OperatingConfig"; 1166*ef4c65b7SEd Tanous json["@odata.id"] = boost::urls::format( 1167*ef4c65b7SEd Tanous "/redfish/v1/Systems/system/Processors/{}/OperatingConfigs/{}", 1168*ef4c65b7SEd Tanous cpuName, configName); 1169dba0c291SJonathan Doman json["Name"] = "Processor Profile"; 1170dba0c291SJonathan Doman json["Id"] = configName; 1171dba0c291SJonathan Doman 1172dba0c291SJonathan Doman // Just use the first implementation of the object - not 11737e860f15SJohn Edward Broadbent // expected that there would be multiple matching 11747e860f15SJohn Edward Broadbent // services 1175002d39b4SEd Tanous getOperatingConfigData(asyncResp, serviceMap.begin()->first, 1176002d39b4SEd Tanous objectPath); 1177dba0c291SJonathan Doman return; 1178dba0c291SJonathan Doman } 1179002d39b4SEd Tanous messages::resourceNotFound(asyncResp->res, "OperatingConfig", 1180002d39b4SEd Tanous configName); 1181e99073f5SGeorge Liu }); 11827e860f15SJohn Edward Broadbent }); 1183ac6a4445SGunnar Mills } 1184ac6a4445SGunnar Mills 11857e860f15SJohn Edward Broadbent inline void requestRoutesProcessorCollection(App& app) 11867e860f15SJohn Edward Broadbent { 1187ac6a4445SGunnar Mills /** 1188ac6a4445SGunnar Mills * Functions triggers appropriate requests on DBus 1189ac6a4445SGunnar Mills */ 119022d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/") 119171a24ca4SNikhil Namjoshi .privileges(redfish::privileges::headProcessorCollection) 119271a24ca4SNikhil Namjoshi .methods(boost::beast::http::verb::head)( 119371a24ca4SNikhil Namjoshi std::bind_front(handleProcessorCollectionHead, std::ref(app))); 119471a24ca4SNikhil Namjoshi 119571a24ca4SNikhil Namjoshi BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/") 1196ed398213SEd Tanous .privileges(redfish::privileges::getProcessorCollection) 11977e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 119845ca1b86SEd Tanous [&app](const crow::Request& req, 119922d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 120022d268cbSEd Tanous const std::string& systemName) { 12013ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 120245ca1b86SEd Tanous { 120345ca1b86SEd Tanous return; 120445ca1b86SEd Tanous } 120522d268cbSEd Tanous if (systemName != "system") 120622d268cbSEd Tanous { 120722d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 120822d268cbSEd Tanous systemName); 120922d268cbSEd Tanous return; 121022d268cbSEd Tanous } 121122d268cbSEd Tanous 121271a24ca4SNikhil Namjoshi asyncResp->res.addHeader( 121371a24ca4SNikhil Namjoshi boost::beast::http::field::link, 121471a24ca4SNikhil Namjoshi "</redfish/v1/JsonSchemas/ProcessorCollection/ProcessorCollection.json>; rel=describedby"); 121571a24ca4SNikhil Namjoshi 12168d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.type"] = 1217ac6a4445SGunnar Mills "#ProcessorCollection.ProcessorCollection"; 12188d1b46d7Szhanghch05 asyncResp->res.jsonValue["Name"] = "Processor Collection"; 1219ac6a4445SGunnar Mills 12208d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.id"] = 12218d1b46d7Szhanghch05 "/redfish/v1/Systems/system/Processors"; 1222ac6a4445SGunnar Mills 122305030b8eSGunnar Mills collection_util::getCollectionMembers( 1224ae9031f0SWilly Tu asyncResp, 1225ae9031f0SWilly Tu boost::urls::url("/redfish/v1/Systems/system/Processors"), 12267a1dbc48SGeorge Liu processorInterfaces); 12277e860f15SJohn Edward Broadbent }); 1228ac6a4445SGunnar Mills } 1229ac6a4445SGunnar Mills 12307e860f15SJohn Edward Broadbent inline void requestRoutesProcessor(App& app) 12317e860f15SJohn Edward Broadbent { 1232ac6a4445SGunnar Mills /** 1233ac6a4445SGunnar Mills * Functions triggers appropriate requests on DBus 1234ac6a4445SGunnar Mills */ 12357e860f15SJohn Edward Broadbent 123622d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/<str>/") 123771a24ca4SNikhil Namjoshi .privileges(redfish::privileges::headProcessor) 123871a24ca4SNikhil Namjoshi .methods(boost::beast::http::verb::head)( 123971a24ca4SNikhil Namjoshi std::bind_front(handleProcessorHead, std::ref(app))); 124071a24ca4SNikhil Namjoshi 124171a24ca4SNikhil Namjoshi BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/<str>/") 1242ed398213SEd Tanous .privileges(redfish::privileges::getProcessor) 12437e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 124445ca1b86SEd Tanous [&app](const crow::Request& req, 12457e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 124622d268cbSEd Tanous const std::string& systemName, 12477e860f15SJohn Edward Broadbent const std::string& processorId) { 12483ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 124945ca1b86SEd Tanous { 125045ca1b86SEd Tanous return; 125145ca1b86SEd Tanous } 125222d268cbSEd Tanous if (systemName != "system") 125322d268cbSEd Tanous { 125422d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 125522d268cbSEd Tanous systemName); 125622d268cbSEd Tanous return; 125722d268cbSEd Tanous } 125822d268cbSEd Tanous 125971a24ca4SNikhil Namjoshi asyncResp->res.addHeader( 126071a24ca4SNikhil Namjoshi boost::beast::http::field::link, 126171a24ca4SNikhil Namjoshi "</redfish/v1/JsonSchemas/Processor/Processor.json>; rel=describedby"); 12628d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.type"] = 12638d1b46d7Szhanghch05 "#Processor.v1_11_0.Processor"; 1264*ef4c65b7SEd Tanous asyncResp->res.jsonValue["@odata.id"] = boost::urls::format( 1265*ef4c65b7SEd Tanous "/redfish/v1/Systems/system/Processors/{}", processorId); 1266ac6a4445SGunnar Mills 12678a592810SEd Tanous getProcessorObject( 12688a592810SEd Tanous asyncResp, processorId, 12698a592810SEd Tanous std::bind_front(getProcessorData, asyncResp, processorId)); 12707e860f15SJohn Edward Broadbent }); 12713cde86f1SJonathan Doman 127222d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/<str>/") 1273ed398213SEd Tanous .privileges(redfish::privileges::patchProcessor) 12747e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::patch)( 127545ca1b86SEd Tanous [&app](const crow::Request& req, 12767e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 127722d268cbSEd Tanous const std::string& systemName, 12787e860f15SJohn Edward Broadbent const std::string& processorId) { 12793ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 128045ca1b86SEd Tanous { 128145ca1b86SEd Tanous return; 128245ca1b86SEd Tanous } 128322d268cbSEd Tanous if (systemName != "system") 128422d268cbSEd Tanous { 128522d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 128622d268cbSEd Tanous systemName); 128722d268cbSEd Tanous return; 128822d268cbSEd Tanous } 128922d268cbSEd Tanous 12903cde86f1SJonathan Doman std::optional<nlohmann::json> appliedConfigJson; 129115ed6780SWilly Tu if (!json_util::readJsonPatch(req, asyncResp->res, 12927e860f15SJohn Edward Broadbent "AppliedOperatingConfig", 12933cde86f1SJonathan Doman appliedConfigJson)) 12943cde86f1SJonathan Doman { 12953cde86f1SJonathan Doman return; 12963cde86f1SJonathan Doman } 12973cde86f1SJonathan Doman 12983cde86f1SJonathan Doman if (appliedConfigJson) 12993cde86f1SJonathan Doman { 1300f8fe53e7SEd Tanous std::string appliedConfigUri; 13013cde86f1SJonathan Doman if (!json_util::readJson(*appliedConfigJson, asyncResp->res, 13023cde86f1SJonathan Doman "@odata.id", appliedConfigUri)) 13033cde86f1SJonathan Doman { 13043cde86f1SJonathan Doman return; 13053cde86f1SJonathan Doman } 13067e860f15SJohn Edward Broadbent // Check for 404 and find matching D-Bus object, then run 13077e860f15SJohn Edward Broadbent // property patch handlers if that all succeeds. 13088a592810SEd Tanous getProcessorObject(asyncResp, processorId, 13098a592810SEd Tanous std::bind_front(patchAppliedOperatingConfig, 13107e860f15SJohn Edward Broadbent asyncResp, processorId, 13118a592810SEd Tanous appliedConfigUri)); 13123cde86f1SJonathan Doman } 13137e860f15SJohn Edward Broadbent }); 13143cde86f1SJonathan Doman } 1315ac6a4445SGunnar Mills 1316ac6a4445SGunnar Mills } // namespace redfish 1317