xref: /openbmc/bmcweb/features/redfish/lib/processor.hpp (revision deae6a789444debc4724fb6902fc5def299afbee)
1ac6a4445SGunnar Mills /*
26be832e2SEd Tanous Copyright (c) 2018 Intel Corporation
36be832e2SEd Tanous 
46be832e2SEd Tanous Licensed under the Apache License, Version 2.0 (the "License");
56be832e2SEd Tanous you may not use this file except in compliance with the License.
66be832e2SEd Tanous You may obtain a copy of the License at
76be832e2SEd Tanous 
86be832e2SEd Tanous       http://www.apache.org/licenses/LICENSE-2.0
96be832e2SEd Tanous 
106be832e2SEd Tanous Unless required by applicable law or agreed to in writing, software
116be832e2SEd Tanous distributed under the License is distributed on an "AS IS" BASIS,
126be832e2SEd Tanous WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136be832e2SEd Tanous See the License for the specific language governing permissions and
146be832e2SEd Tanous 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"
22dfbf7de5SChris Cain #include "generated/enums/processor.hpp"
23539d8c6bSEd Tanous #include "generated/enums/resource.hpp"
243ccb3adbSEd Tanous #include "query.hpp"
253ccb3adbSEd Tanous #include "registries/privilege_registry.hpp"
263ccb3adbSEd Tanous #include "utils/collection.hpp"
273ccb3adbSEd Tanous #include "utils/dbus_utils.hpp"
283ccb3adbSEd Tanous #include "utils/json_utils.hpp"
29ac6a4445SGunnar Mills 
30ac6a4445SGunnar Mills #include <boost/container/flat_map.hpp>
31e99073f5SGeorge Liu #include <boost/system/error_code.hpp>
32ef4c65b7SEd Tanous #include <boost/url/format.hpp>
331e1e598dSJonathan Doman #include <sdbusplus/asio/property.hpp>
34dba0c291SJonathan Doman #include <sdbusplus/message/native_types.hpp>
35351053f2SKrzysztof Grobelny #include <sdbusplus/unpack_properties.hpp>
36dba0c291SJonathan Doman #include <sdbusplus/utility/dedup_variant.hpp>
37ac6a4445SGunnar Mills 
387a1dbc48SGeorge Liu #include <array>
39b9d679d1SMichael Shen #include <limits>
403544d2a7SEd Tanous #include <ranges>
413c569218SEd Tanous #include <string>
427a1dbc48SGeorge Liu #include <string_view>
437a1dbc48SGeorge Liu 
44ac6a4445SGunnar Mills namespace redfish
45ac6a4445SGunnar Mills {
46ac6a4445SGunnar Mills 
47c951448aSJonathan Doman // Interfaces which imply a D-Bus object represents a Processor
487a1dbc48SGeorge Liu constexpr std::array<std::string_view, 2> processorInterfaces = {
49c951448aSJonathan Doman     "xyz.openbmc_project.Inventory.Item.Cpu",
50c951448aSJonathan Doman     "xyz.openbmc_project.Inventory.Item.Accelerator"};
512bab9831SJonathan Doman 
5271b82f26SSharad Yadav /**
5371b82f26SSharad Yadav  * @brief Fill out uuid info of a processor by
5471b82f26SSharad Yadav  * requesting data from the given D-Bus object.
5571b82f26SSharad Yadav  *
56ac106bf6SEd Tanous  * @param[in,out]   asyncResp       Async HTTP response.
5771b82f26SSharad Yadav  * @param[in]       service     D-Bus service to query.
5871b82f26SSharad Yadav  * @param[in]       objPath     D-Bus object to query.
5971b82f26SSharad Yadav  */
60ac106bf6SEd Tanous inline void getProcessorUUID(std::shared_ptr<bmcweb::AsyncResp> asyncResp,
6171b82f26SSharad Yadav                              const std::string& service,
6271b82f26SSharad Yadav                              const std::string& objPath)
6371b82f26SSharad Yadav {
6462598e31SEd Tanous     BMCWEB_LOG_DEBUG("Get Processor UUID");
65*deae6a78SEd Tanous     dbus::utility::getProperty<std::string>(
66*deae6a78SEd Tanous         service, objPath, "xyz.openbmc_project.Common.UUID", "UUID",
67ac106bf6SEd Tanous         [objPath, asyncResp{std::move(asyncResp)}](
68ac106bf6SEd Tanous             const boost::system::error_code& ec, const std::string& property) {
6971b82f26SSharad Yadav             if (ec)
7071b82f26SSharad Yadav             {
7162598e31SEd Tanous                 BMCWEB_LOG_DEBUG("DBUS response error");
72ac106bf6SEd Tanous                 messages::internalError(asyncResp->res);
7371b82f26SSharad Yadav                 return;
7471b82f26SSharad Yadav             }
75ac106bf6SEd Tanous             asyncResp->res.jsonValue["UUID"] = property;
761e1e598dSJonathan Doman         });
7771b82f26SSharad Yadav }
7871b82f26SSharad Yadav 
79711ac7a9SEd Tanous inline void getCpuDataByInterface(
80ac106bf6SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
8180f79a40SMichael Shen     const dbus::utility::DBusInterfacesMap& cpuInterfacesProperties)
82ac6a4445SGunnar Mills {
8362598e31SEd Tanous     BMCWEB_LOG_DEBUG("Get CPU resources by interface.");
84ac6a4445SGunnar Mills 
85a1649ec6SChicago Duan     // Set the default value of state
86539d8c6bSEd Tanous     asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled;
87539d8c6bSEd Tanous     asyncResp->res.jsonValue["Status"]["Health"] = resource::Health::OK;
88ac6a4445SGunnar Mills 
89ac6a4445SGunnar Mills     for (const auto& interface : cpuInterfacesProperties)
90ac6a4445SGunnar Mills     {
91ac6a4445SGunnar Mills         for (const auto& property : interface.second)
92ac6a4445SGunnar Mills         {
93a1649ec6SChicago Duan             if (property.first == "Present")
94ac6a4445SGunnar Mills             {
95a1649ec6SChicago Duan                 const bool* cpuPresent = std::get_if<bool>(&property.second);
96a1649ec6SChicago Duan                 if (cpuPresent == nullptr)
97ac6a4445SGunnar Mills                 {
98ac6a4445SGunnar Mills                     // Important property not in desired type
99ac106bf6SEd Tanous                     messages::internalError(asyncResp->res);
100ac6a4445SGunnar Mills                     return;
101ac6a4445SGunnar Mills                 }
102e05aec50SEd Tanous                 if (!*cpuPresent)
103ac6a4445SGunnar Mills                 {
104a1649ec6SChicago Duan                     // Slot is not populated
105539d8c6bSEd Tanous                     asyncResp->res.jsonValue["Status"]["State"] =
106539d8c6bSEd Tanous                         resource::State::Absent;
107a1649ec6SChicago Duan                 }
108a1649ec6SChicago Duan             }
109a1649ec6SChicago Duan             else if (property.first == "Functional")
110a1649ec6SChicago Duan             {
111a1649ec6SChicago Duan                 const bool* cpuFunctional = std::get_if<bool>(&property.second);
112a1649ec6SChicago Duan                 if (cpuFunctional == nullptr)
113a1649ec6SChicago Duan                 {
114ac106bf6SEd Tanous                     messages::internalError(asyncResp->res);
115ac6a4445SGunnar Mills                     return;
116ac6a4445SGunnar Mills                 }
117e05aec50SEd Tanous                 if (!*cpuFunctional)
118a1649ec6SChicago Duan                 {
119539d8c6bSEd Tanous                     asyncResp->res.jsonValue["Status"]["Health"] =
120539d8c6bSEd Tanous                         resource::Health::Critical;
121a1649ec6SChicago Duan                 }
122a1649ec6SChicago Duan             }
123a1649ec6SChicago Duan             else if (property.first == "CoreCount")
124a1649ec6SChicago Duan             {
125a1649ec6SChicago Duan                 const uint16_t* coresCount =
126a1649ec6SChicago Duan                     std::get_if<uint16_t>(&property.second);
127a1649ec6SChicago Duan                 if (coresCount == nullptr)
128a1649ec6SChicago Duan                 {
129ac106bf6SEd Tanous                     messages::internalError(asyncResp->res);
130a1649ec6SChicago Duan                     return;
131a1649ec6SChicago Duan                 }
132ac106bf6SEd Tanous                 asyncResp->res.jsonValue["TotalCores"] = *coresCount;
133ac6a4445SGunnar Mills             }
134dc3fa667SJonathan Doman             else if (property.first == "MaxSpeedInMhz")
135dc3fa667SJonathan Doman             {
136dc3fa667SJonathan Doman                 const uint32_t* value = std::get_if<uint32_t>(&property.second);
137dc3fa667SJonathan Doman                 if (value != nullptr)
138dc3fa667SJonathan Doman                 {
139ac106bf6SEd Tanous                     asyncResp->res.jsonValue["MaxSpeedMHz"] = *value;
140dc3fa667SJonathan Doman                 }
141dc3fa667SJonathan Doman             }
142ac6a4445SGunnar Mills             else if (property.first == "Socket")
143ac6a4445SGunnar Mills             {
144ac6a4445SGunnar Mills                 const std::string* value =
145ac6a4445SGunnar Mills                     std::get_if<std::string>(&property.second);
146ac6a4445SGunnar Mills                 if (value != nullptr)
147ac6a4445SGunnar Mills                 {
148ac106bf6SEd Tanous                     asyncResp->res.jsonValue["Socket"] = *value;
149ac6a4445SGunnar Mills                 }
150ac6a4445SGunnar Mills             }
151ac6a4445SGunnar Mills             else if (property.first == "ThreadCount")
152ac6a4445SGunnar Mills             {
153dc3fa667SJonathan Doman                 const uint16_t* value = std::get_if<uint16_t>(&property.second);
154ac6a4445SGunnar Mills                 if (value != nullptr)
155ac6a4445SGunnar Mills                 {
156ac106bf6SEd Tanous                     asyncResp->res.jsonValue["TotalThreads"] = *value;
157ac6a4445SGunnar Mills                 }
158ac6a4445SGunnar Mills             }
1591930fbd4SBrandon Kim             else if (property.first == "EffectiveFamily")
160ac6a4445SGunnar Mills             {
1611930fbd4SBrandon Kim                 const uint16_t* value = std::get_if<uint16_t>(&property.second);
1626169de2cSBrad Bishop                 if (value != nullptr && *value != 2)
163ac6a4445SGunnar Mills                 {
164ac106bf6SEd Tanous                     asyncResp->res.jsonValue["ProcessorId"]["EffectiveFamily"] =
165866e4862SEd Tanous                         "0x" + intToHexString(*value, 4);
166ac6a4445SGunnar Mills                 }
167ac6a4445SGunnar Mills             }
1681930fbd4SBrandon Kim             else if (property.first == "EffectiveModel")
1691930fbd4SBrandon Kim             {
1701930fbd4SBrandon Kim                 const uint16_t* value = std::get_if<uint16_t>(&property.second);
1711930fbd4SBrandon Kim                 if (value == nullptr)
1721930fbd4SBrandon Kim                 {
173ac106bf6SEd Tanous                     messages::internalError(asyncResp->res);
1741930fbd4SBrandon Kim                     return;
1751930fbd4SBrandon Kim                 }
1766169de2cSBrad Bishop                 if (*value != 0)
1776169de2cSBrad Bishop                 {
178ac106bf6SEd Tanous                     asyncResp->res.jsonValue["ProcessorId"]["EffectiveModel"] =
179866e4862SEd Tanous                         "0x" + intToHexString(*value, 4);
1801930fbd4SBrandon Kim                 }
1816169de2cSBrad Bishop             }
182ac6a4445SGunnar Mills             else if (property.first == "Id")
183ac6a4445SGunnar Mills             {
184ac6a4445SGunnar Mills                 const uint64_t* value = std::get_if<uint64_t>(&property.second);
185ac6a4445SGunnar Mills                 if (value != nullptr && *value != 0)
186ac6a4445SGunnar Mills                 {
187ac106bf6SEd Tanous                     asyncResp->res
188ac6a4445SGunnar Mills                         .jsonValue["ProcessorId"]["IdentificationRegisters"] =
189866e4862SEd Tanous                         "0x" + intToHexString(*value, 16);
190ac6a4445SGunnar Mills                 }
191ac6a4445SGunnar Mills             }
1921930fbd4SBrandon Kim             else if (property.first == "Microcode")
1931930fbd4SBrandon Kim             {
1941930fbd4SBrandon Kim                 const uint32_t* value = std::get_if<uint32_t>(&property.second);
1951930fbd4SBrandon Kim                 if (value == nullptr)
1961930fbd4SBrandon Kim                 {
197ac106bf6SEd Tanous                     messages::internalError(asyncResp->res);
1981930fbd4SBrandon Kim                     return;
1991930fbd4SBrandon Kim                 }
2006169de2cSBrad Bishop                 if (*value != 0)
2016169de2cSBrad Bishop                 {
202ac106bf6SEd Tanous                     asyncResp->res.jsonValue["ProcessorId"]["MicrocodeInfo"] =
203866e4862SEd Tanous                         "0x" + intToHexString(*value, 8);
2041930fbd4SBrandon Kim                 }
2056169de2cSBrad Bishop             }
2061930fbd4SBrandon Kim             else if (property.first == "Step")
2071930fbd4SBrandon Kim             {
2081930fbd4SBrandon Kim                 const uint16_t* value = std::get_if<uint16_t>(&property.second);
2091930fbd4SBrandon Kim                 if (value == nullptr)
2101930fbd4SBrandon Kim                 {
211ac106bf6SEd Tanous                     messages::internalError(asyncResp->res);
2121930fbd4SBrandon Kim                     return;
2131930fbd4SBrandon Kim                 }
214b9d679d1SMichael Shen                 if (*value != std::numeric_limits<uint16_t>::max())
2156169de2cSBrad Bishop                 {
216ac106bf6SEd Tanous                     asyncResp->res.jsonValue["ProcessorId"]["Step"] =
217866e4862SEd Tanous                         "0x" + intToHexString(*value, 4);
2181930fbd4SBrandon Kim                 }
219ac6a4445SGunnar Mills             }
220ac6a4445SGunnar Mills         }
221ac6a4445SGunnar Mills     }
2226169de2cSBrad Bishop }
223ac6a4445SGunnar Mills 
224bd79bce8SPatrick Williams inline void getCpuDataByService(
225bd79bce8SPatrick Williams     std::shared_ptr<bmcweb::AsyncResp> asyncResp, const std::string& cpuId,
226bd79bce8SPatrick Williams     const std::string& service, const std::string& objPath)
227ac6a4445SGunnar Mills {
22862598e31SEd Tanous     BMCWEB_LOG_DEBUG("Get available system cpu resources by service.");
229ac6a4445SGunnar Mills 
2305eb468daSGeorge Liu     sdbusplus::message::object_path path("/xyz/openbmc_project/inventory");
2315eb468daSGeorge Liu     dbus::utility::getManagedObjects(
2325eb468daSGeorge Liu         service, path,
233ac106bf6SEd Tanous         [cpuId, service, objPath, asyncResp{std::move(asyncResp)}](
2345e7e2dc5SEd Tanous             const boost::system::error_code& ec,
235ac6a4445SGunnar Mills             const dbus::utility::ManagedObjectType& dbusData) {
236ac6a4445SGunnar Mills             if (ec)
237ac6a4445SGunnar Mills             {
23862598e31SEd Tanous                 BMCWEB_LOG_DEBUG("DBUS response error");
239ac106bf6SEd Tanous                 messages::internalError(asyncResp->res);
240ac6a4445SGunnar Mills                 return;
241ac6a4445SGunnar Mills             }
242ac106bf6SEd Tanous             asyncResp->res.jsonValue["Id"] = cpuId;
243ac106bf6SEd Tanous             asyncResp->res.jsonValue["Name"] = "Processor";
244539d8c6bSEd Tanous             asyncResp->res.jsonValue["ProcessorType"] =
245539d8c6bSEd Tanous                 processor::ProcessorType::CPU;
246ac6a4445SGunnar Mills 
247ac6a4445SGunnar Mills             for (const auto& object : dbusData)
248ac6a4445SGunnar Mills             {
249ac6a4445SGunnar Mills                 if (object.first.str == objPath)
250ac6a4445SGunnar Mills                 {
251ac106bf6SEd Tanous                     getCpuDataByInterface(asyncResp, object.second);
252ac6a4445SGunnar Mills                 }
253ac6a4445SGunnar Mills             }
254ac6a4445SGunnar Mills             return;
2555eb468daSGeorge Liu         });
256ac6a4445SGunnar Mills }
257ac6a4445SGunnar Mills 
258dfbf7de5SChris Cain /**
259dfbf7de5SChris Cain  * @brief Translates throttle cause DBUS property to redfish.
260dfbf7de5SChris Cain  *
261dfbf7de5SChris Cain  * @param[in] dbusSource    The throttle cause from DBUS
262dfbf7de5SChris Cain  *
263dfbf7de5SChris Cain  * @return Returns as a string, the throttle cause in Redfish terms. If
264dfbf7de5SChris Cain  * translation cannot be done, returns "Unknown" throttle reason.
265dfbf7de5SChris Cain  */
266dfbf7de5SChris Cain inline processor::ThrottleCause
267dfbf7de5SChris Cain     dbusToRfThrottleCause(const std::string& dbusSource)
268dfbf7de5SChris Cain {
269dfbf7de5SChris Cain     if (dbusSource ==
270dfbf7de5SChris Cain         "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.ClockLimit")
271dfbf7de5SChris Cain     {
272dfbf7de5SChris Cain         return processor::ThrottleCause::ClockLimit;
273dfbf7de5SChris Cain     }
274dfbf7de5SChris Cain     if (dbusSource ==
275dfbf7de5SChris Cain         "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.ManagementDetectedFault")
276dfbf7de5SChris Cain     {
277dfbf7de5SChris Cain         return processor::ThrottleCause::ManagementDetectedFault;
278dfbf7de5SChris Cain     }
279dfbf7de5SChris Cain     if (dbusSource ==
280dfbf7de5SChris Cain         "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.PowerLimit")
281dfbf7de5SChris Cain     {
282dfbf7de5SChris Cain         return processor::ThrottleCause::PowerLimit;
283dfbf7de5SChris Cain     }
284dfbf7de5SChris Cain     if (dbusSource ==
285dfbf7de5SChris Cain         "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.ThermalLimit")
286dfbf7de5SChris Cain     {
287dfbf7de5SChris Cain         return processor::ThrottleCause::ThermalLimit;
288dfbf7de5SChris Cain     }
289dfbf7de5SChris Cain     if (dbusSource ==
290dfbf7de5SChris Cain         "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.Unknown")
291dfbf7de5SChris Cain     {
292dfbf7de5SChris Cain         return processor::ThrottleCause::Unknown;
293dfbf7de5SChris Cain     }
294dfbf7de5SChris Cain     return processor::ThrottleCause::Invalid;
295dfbf7de5SChris Cain }
296dfbf7de5SChris Cain 
297dfbf7de5SChris Cain inline void
298ac106bf6SEd Tanous     readThrottleProperties(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
299dfbf7de5SChris Cain                            const boost::system::error_code& ec,
300dfbf7de5SChris Cain                            const dbus::utility::DBusPropertiesMap& properties)
301dfbf7de5SChris Cain {
302dfbf7de5SChris Cain     if (ec)
303dfbf7de5SChris Cain     {
30462598e31SEd Tanous         BMCWEB_LOG_ERROR("Processor Throttle getAllProperties error {}", ec);
305ac106bf6SEd Tanous         messages::internalError(asyncResp->res);
306dfbf7de5SChris Cain         return;
307dfbf7de5SChris Cain     }
308dfbf7de5SChris Cain 
309dfbf7de5SChris Cain     const bool* status = nullptr;
310dfbf7de5SChris Cain     const std::vector<std::string>* causes = nullptr;
311dfbf7de5SChris Cain 
312dfbf7de5SChris Cain     if (!sdbusplus::unpackPropertiesNoThrow(dbus_utils::UnpackErrorPrinter(),
313dfbf7de5SChris Cain                                             properties, "Throttled", status,
314dfbf7de5SChris Cain                                             "ThrottleCauses", causes))
315dfbf7de5SChris Cain     {
316ac106bf6SEd Tanous         messages::internalError(asyncResp->res);
317dfbf7de5SChris Cain         return;
318dfbf7de5SChris Cain     }
319dfbf7de5SChris Cain 
320ac106bf6SEd Tanous     asyncResp->res.jsonValue["Throttled"] = *status;
321dfbf7de5SChris Cain     nlohmann::json::array_t rCauses;
322dfbf7de5SChris Cain     for (const std::string& cause : *causes)
323dfbf7de5SChris Cain     {
324dfbf7de5SChris Cain         processor::ThrottleCause rfCause = dbusToRfThrottleCause(cause);
325dfbf7de5SChris Cain         if (rfCause == processor::ThrottleCause::Invalid)
326dfbf7de5SChris Cain         {
327ac106bf6SEd Tanous             messages::internalError(asyncResp->res);
328dfbf7de5SChris Cain             return;
329dfbf7de5SChris Cain         }
330dfbf7de5SChris Cain 
331dfbf7de5SChris Cain         rCauses.emplace_back(rfCause);
332dfbf7de5SChris Cain     }
333ac106bf6SEd Tanous     asyncResp->res.jsonValue["ThrottleCauses"] = std::move(rCauses);
334dfbf7de5SChris Cain }
335dfbf7de5SChris Cain 
336bd79bce8SPatrick Williams inline void getThrottleProperties(
337bd79bce8SPatrick Williams     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
338bd79bce8SPatrick Williams     const std::string& service, const std::string& objectPath)
339dfbf7de5SChris Cain {
34062598e31SEd Tanous     BMCWEB_LOG_DEBUG("Get processor throttle resources");
341dfbf7de5SChris Cain 
342*deae6a78SEd Tanous     dbus::utility::getAllProperties(
343*deae6a78SEd Tanous         service, objectPath, "xyz.openbmc_project.Control.Power.Throttle",
344ac106bf6SEd Tanous         [asyncResp](const boost::system::error_code& ec,
345dfbf7de5SChris Cain                     const dbus::utility::DBusPropertiesMap& properties) {
346ac106bf6SEd Tanous             readThrottleProperties(asyncResp, ec, properties);
347dfbf7de5SChris Cain         });
348dfbf7de5SChris Cain }
349dfbf7de5SChris Cain 
350ac106bf6SEd Tanous inline void getCpuAssetData(std::shared_ptr<bmcweb::AsyncResp> asyncResp,
351ac6a4445SGunnar Mills                             const std::string& service,
352ac6a4445SGunnar Mills                             const std::string& objPath)
353ac6a4445SGunnar Mills {
35462598e31SEd Tanous     BMCWEB_LOG_DEBUG("Get Cpu Asset Data");
355*deae6a78SEd Tanous     dbus::utility::getAllProperties(
356*deae6a78SEd Tanous         service, objPath, "xyz.openbmc_project.Inventory.Decorator.Asset",
357ac106bf6SEd Tanous         [objPath, asyncResp{std::move(asyncResp)}](
3585e7e2dc5SEd Tanous             const boost::system::error_code& ec,
359351053f2SKrzysztof Grobelny             const dbus::utility::DBusPropertiesMap& properties) {
360ac6a4445SGunnar Mills             if (ec)
361ac6a4445SGunnar Mills             {
36262598e31SEd Tanous                 BMCWEB_LOG_DEBUG("DBUS response error");
363ac106bf6SEd Tanous                 messages::internalError(asyncResp->res);
364ac6a4445SGunnar Mills                 return;
365ac6a4445SGunnar Mills             }
366ac6a4445SGunnar Mills 
367351053f2SKrzysztof Grobelny             const std::string* serialNumber = nullptr;
368351053f2SKrzysztof Grobelny             const std::string* model = nullptr;
369351053f2SKrzysztof Grobelny             const std::string* manufacturer = nullptr;
370351053f2SKrzysztof Grobelny             const std::string* partNumber = nullptr;
371351053f2SKrzysztof Grobelny             const std::string* sparePartNumber = nullptr;
372351053f2SKrzysztof Grobelny 
373351053f2SKrzysztof Grobelny             const bool success = sdbusplus::unpackPropertiesNoThrow(
374351053f2SKrzysztof Grobelny                 dbus_utils::UnpackErrorPrinter(), properties, "SerialNumber",
375351053f2SKrzysztof Grobelny                 serialNumber, "Model", model, "Manufacturer", manufacturer,
376351053f2SKrzysztof Grobelny                 "PartNumber", partNumber, "SparePartNumber", sparePartNumber);
377351053f2SKrzysztof Grobelny 
378351053f2SKrzysztof Grobelny             if (!success)
379ac6a4445SGunnar Mills             {
380ac106bf6SEd Tanous                 messages::internalError(asyncResp->res);
381351053f2SKrzysztof Grobelny                 return;
382ac6a4445SGunnar Mills             }
383351053f2SKrzysztof Grobelny 
384351053f2SKrzysztof Grobelny             if (serialNumber != nullptr && !serialNumber->empty())
385ac6a4445SGunnar Mills             {
386ac106bf6SEd Tanous                 asyncResp->res.jsonValue["SerialNumber"] = *serialNumber;
387351053f2SKrzysztof Grobelny             }
388351053f2SKrzysztof Grobelny 
389351053f2SKrzysztof Grobelny             if ((model != nullptr) && !model->empty())
390ac6a4445SGunnar Mills             {
391ac106bf6SEd Tanous                 asyncResp->res.jsonValue["Model"] = *model;
392ac6a4445SGunnar Mills             }
393ac6a4445SGunnar Mills 
394351053f2SKrzysztof Grobelny             if (manufacturer != nullptr)
395ac6a4445SGunnar Mills             {
396ac106bf6SEd Tanous                 asyncResp->res.jsonValue["Manufacturer"] = *manufacturer;
397ac6a4445SGunnar Mills 
398ac6a4445SGunnar Mills                 // Otherwise would be unexpected.
399351053f2SKrzysztof Grobelny                 if (manufacturer->find("Intel") != std::string::npos)
400ac6a4445SGunnar Mills                 {
401ac106bf6SEd Tanous                     asyncResp->res.jsonValue["ProcessorArchitecture"] = "x86";
402ac106bf6SEd Tanous                     asyncResp->res.jsonValue["InstructionSet"] = "x86-64";
403ac6a4445SGunnar Mills                 }
404351053f2SKrzysztof Grobelny                 else if (manufacturer->find("IBM") != std::string::npos)
405ac6a4445SGunnar Mills                 {
406ac106bf6SEd Tanous                     asyncResp->res.jsonValue["ProcessorArchitecture"] = "Power";
407ac106bf6SEd Tanous                     asyncResp->res.jsonValue["InstructionSet"] = "PowerISA";
408ac6a4445SGunnar Mills                 }
409ac6a4445SGunnar Mills             }
410cba4f448SSunnySrivastava1984 
411351053f2SKrzysztof Grobelny             if (partNumber != nullptr)
412cba4f448SSunnySrivastava1984             {
413ac106bf6SEd Tanous                 asyncResp->res.jsonValue["PartNumber"] = *partNumber;
414cba4f448SSunnySrivastava1984             }
415cba4f448SSunnySrivastava1984 
4166169de2cSBrad Bishop             if (sparePartNumber != nullptr && !sparePartNumber->empty())
417cba4f448SSunnySrivastava1984             {
418ac106bf6SEd Tanous                 asyncResp->res.jsonValue["SparePartNumber"] = *sparePartNumber;
419cba4f448SSunnySrivastava1984             }
420351053f2SKrzysztof Grobelny         });
421ac6a4445SGunnar Mills }
422ac6a4445SGunnar Mills 
423ac106bf6SEd Tanous inline void getCpuRevisionData(std::shared_ptr<bmcweb::AsyncResp> asyncResp,
424ac6a4445SGunnar Mills                                const std::string& service,
425ac6a4445SGunnar Mills                                const std::string& objPath)
426ac6a4445SGunnar Mills {
42762598e31SEd Tanous     BMCWEB_LOG_DEBUG("Get Cpu Revision Data");
428*deae6a78SEd Tanous     dbus::utility::getAllProperties(
429*deae6a78SEd Tanous         service, objPath, "xyz.openbmc_project.Inventory.Decorator.Revision",
430ac106bf6SEd Tanous         [objPath, asyncResp{std::move(asyncResp)}](
4315e7e2dc5SEd Tanous             const boost::system::error_code& ec,
432351053f2SKrzysztof Grobelny             const dbus::utility::DBusPropertiesMap& properties) {
433ac6a4445SGunnar Mills             if (ec)
434ac6a4445SGunnar Mills             {
43562598e31SEd Tanous                 BMCWEB_LOG_DEBUG("DBUS response error");
436ac106bf6SEd Tanous                 messages::internalError(asyncResp->res);
437ac6a4445SGunnar Mills                 return;
438ac6a4445SGunnar Mills             }
439ac6a4445SGunnar Mills 
440351053f2SKrzysztof Grobelny             const std::string* version = nullptr;
441351053f2SKrzysztof Grobelny 
442351053f2SKrzysztof Grobelny             const bool success = sdbusplus::unpackPropertiesNoThrow(
443bd79bce8SPatrick Williams                 dbus_utils::UnpackErrorPrinter(), properties, "Version",
444bd79bce8SPatrick Williams                 version);
445351053f2SKrzysztof Grobelny 
446351053f2SKrzysztof Grobelny             if (!success)
447ac6a4445SGunnar Mills             {
448ac106bf6SEd Tanous                 messages::internalError(asyncResp->res);
449351053f2SKrzysztof Grobelny                 return;
450351053f2SKrzysztof Grobelny             }
451351053f2SKrzysztof Grobelny 
452351053f2SKrzysztof Grobelny             if (version != nullptr)
453ac6a4445SGunnar Mills             {
454ac106bf6SEd Tanous                 asyncResp->res.jsonValue["Version"] = *version;
455ac6a4445SGunnar Mills             }
456351053f2SKrzysztof Grobelny         });
457ac6a4445SGunnar Mills }
458ac6a4445SGunnar Mills 
4598d1b46d7Szhanghch05 inline void getAcceleratorDataByService(
460ac106bf6SEd Tanous     std::shared_ptr<bmcweb::AsyncResp> asyncResp, const std::string& acclrtrId,
4618d1b46d7Szhanghch05     const std::string& service, const std::string& objPath)
462ac6a4445SGunnar Mills {
46362598e31SEd Tanous     BMCWEB_LOG_DEBUG("Get available system Accelerator resources by service.");
464*deae6a78SEd Tanous     dbus::utility::getAllProperties(
465*deae6a78SEd Tanous         service, objPath, "",
466ac106bf6SEd Tanous         [acclrtrId, asyncResp{std::move(asyncResp)}](
4675e7e2dc5SEd Tanous             const boost::system::error_code& ec,
468351053f2SKrzysztof Grobelny             const dbus::utility::DBusPropertiesMap& properties) {
469ac6a4445SGunnar Mills             if (ec)
470ac6a4445SGunnar Mills             {
47162598e31SEd Tanous                 BMCWEB_LOG_DEBUG("DBUS response error");
472ac106bf6SEd Tanous                 messages::internalError(asyncResp->res);
473ac6a4445SGunnar Mills                 return;
474ac6a4445SGunnar Mills             }
475ac6a4445SGunnar Mills 
476351053f2SKrzysztof Grobelny             const bool* functional = nullptr;
477351053f2SKrzysztof Grobelny             const bool* present = nullptr;
478351053f2SKrzysztof Grobelny 
479351053f2SKrzysztof Grobelny             const bool success = sdbusplus::unpackPropertiesNoThrow(
480351053f2SKrzysztof Grobelny                 dbus_utils::UnpackErrorPrinter(), properties, "Functional",
481351053f2SKrzysztof Grobelny                 functional, "Present", present);
482351053f2SKrzysztof Grobelny 
483351053f2SKrzysztof Grobelny             if (!success)
484ac6a4445SGunnar Mills             {
485ac106bf6SEd Tanous                 messages::internalError(asyncResp->res);
486351053f2SKrzysztof Grobelny                 return;
487ac6a4445SGunnar Mills             }
488ac6a4445SGunnar Mills 
489ac6a4445SGunnar Mills             std::string state = "Enabled";
490ac6a4445SGunnar Mills             std::string health = "OK";
491ac6a4445SGunnar Mills 
492351053f2SKrzysztof Grobelny             if (present != nullptr && !*present)
493ac6a4445SGunnar Mills             {
494ac6a4445SGunnar Mills                 state = "Absent";
495ac6a4445SGunnar Mills             }
496ac6a4445SGunnar Mills 
497351053f2SKrzysztof Grobelny             if (functional != nullptr && !*functional)
498ac6a4445SGunnar Mills             {
499ac6a4445SGunnar Mills                 if (state == "Enabled")
500ac6a4445SGunnar Mills                 {
501ac6a4445SGunnar Mills                     health = "Critical";
502ac6a4445SGunnar Mills                 }
503ac6a4445SGunnar Mills             }
504ac6a4445SGunnar Mills 
505ac106bf6SEd Tanous             asyncResp->res.jsonValue["Id"] = acclrtrId;
506ac106bf6SEd Tanous             asyncResp->res.jsonValue["Name"] = "Processor";
507ac106bf6SEd Tanous             asyncResp->res.jsonValue["Status"]["State"] = state;
508ac106bf6SEd Tanous             asyncResp->res.jsonValue["Status"]["Health"] = health;
509539d8c6bSEd Tanous             asyncResp->res.jsonValue["ProcessorType"] =
510539d8c6bSEd Tanous                 processor::ProcessorType::Accelerator;
511351053f2SKrzysztof Grobelny         });
512ac6a4445SGunnar Mills }
513ac6a4445SGunnar Mills 
514dba0c291SJonathan Doman // OperatingConfig D-Bus Types
515dba0c291SJonathan Doman using TurboProfileProperty = std::vector<std::tuple<uint32_t, size_t>>;
516dba0c291SJonathan Doman using BaseSpeedPrioritySettingsProperty =
517dba0c291SJonathan Doman     std::vector<std::tuple<uint32_t, std::vector<uint32_t>>>;
518dba0c291SJonathan Doman // uint32_t and size_t may or may not be the same type, requiring a dedup'd
519dba0c291SJonathan Doman // variant
520dba0c291SJonathan Doman 
521dba0c291SJonathan Doman /**
522dba0c291SJonathan Doman  * Fill out the HighSpeedCoreIDs in a Processor resource from the given
523dba0c291SJonathan Doman  * OperatingConfig D-Bus property.
524dba0c291SJonathan Doman  *
525ac106bf6SEd Tanous  * @param[in,out]   asyncResp           Async HTTP response.
526dba0c291SJonathan Doman  * @param[in]       baseSpeedSettings   Full list of base speed priority groups,
527dba0c291SJonathan Doman  *                                      to use to determine the list of high
528dba0c291SJonathan Doman  *                                      speed cores.
529dba0c291SJonathan Doman  */
530dba0c291SJonathan Doman inline void highSpeedCoreIdsHandler(
531ac106bf6SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
532dba0c291SJonathan Doman     const BaseSpeedPrioritySettingsProperty& baseSpeedSettings)
533dba0c291SJonathan Doman {
534dba0c291SJonathan Doman     // The D-Bus property does not indicate which bucket is the "high
535dba0c291SJonathan Doman     // priority" group, so let's discern that by looking for the one with
536dba0c291SJonathan Doman     // highest base frequency.
537dba0c291SJonathan Doman     auto highPriorityGroup = baseSpeedSettings.cend();
538dba0c291SJonathan Doman     uint32_t highestBaseSpeed = 0;
539dba0c291SJonathan Doman     for (auto it = baseSpeedSettings.cbegin(); it != baseSpeedSettings.cend();
540dba0c291SJonathan Doman          ++it)
541dba0c291SJonathan Doman     {
542dba0c291SJonathan Doman         const uint32_t baseFreq = std::get<uint32_t>(*it);
543dba0c291SJonathan Doman         if (baseFreq > highestBaseSpeed)
544dba0c291SJonathan Doman         {
545dba0c291SJonathan Doman             highestBaseSpeed = baseFreq;
546dba0c291SJonathan Doman             highPriorityGroup = it;
547dba0c291SJonathan Doman         }
548dba0c291SJonathan Doman     }
549dba0c291SJonathan Doman 
550ac106bf6SEd Tanous     nlohmann::json& jsonCoreIds = asyncResp->res.jsonValue["HighSpeedCoreIDs"];
551dba0c291SJonathan Doman     jsonCoreIds = nlohmann::json::array();
552dba0c291SJonathan Doman 
553dba0c291SJonathan Doman     // There may not be any entries in the D-Bus property, so only populate
554dba0c291SJonathan Doman     // if there was actually something there.
555dba0c291SJonathan Doman     if (highPriorityGroup != baseSpeedSettings.cend())
556dba0c291SJonathan Doman     {
557dba0c291SJonathan Doman         jsonCoreIds = std::get<std::vector<uint32_t>>(*highPriorityGroup);
558dba0c291SJonathan Doman     }
559dba0c291SJonathan Doman }
560dba0c291SJonathan Doman 
561dba0c291SJonathan Doman /**
562dba0c291SJonathan Doman  * Fill out OperatingConfig related items in a Processor resource by requesting
563dba0c291SJonathan Doman  * data from the given D-Bus object.
564dba0c291SJonathan Doman  *
565ac106bf6SEd Tanous  * @param[in,out]   asyncResp       Async HTTP response.
566dba0c291SJonathan Doman  * @param[in]       cpuId       CPU D-Bus name.
567dba0c291SJonathan Doman  * @param[in]       service     D-Bus service to query.
568dba0c291SJonathan Doman  * @param[in]       objPath     D-Bus object to query.
569dba0c291SJonathan Doman  */
570ac106bf6SEd Tanous inline void
571ac106bf6SEd Tanous     getCpuConfigData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
572ac106bf6SEd Tanous                      const std::string& cpuId, const std::string& service,
573dba0c291SJonathan Doman                      const std::string& objPath)
574dba0c291SJonathan Doman {
57562598e31SEd Tanous     BMCWEB_LOG_INFO("Getting CPU operating configs for {}", cpuId);
576dba0c291SJonathan Doman 
577dba0c291SJonathan Doman     // First, GetAll CurrentOperatingConfig properties on the object
578*deae6a78SEd Tanous     dbus::utility::getAllProperties(
579*deae6a78SEd Tanous         service, objPath,
580351053f2SKrzysztof Grobelny         "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig",
581ac106bf6SEd Tanous         [asyncResp, cpuId,
5825e7e2dc5SEd Tanous          service](const boost::system::error_code& ec,
583351053f2SKrzysztof Grobelny                   const dbus::utility::DBusPropertiesMap& properties) {
584dba0c291SJonathan Doman             if (ec)
585dba0c291SJonathan Doman             {
58662598e31SEd Tanous                 BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec, ec.message());
587ac106bf6SEd Tanous                 messages::internalError(asyncResp->res);
588dba0c291SJonathan Doman                 return;
589dba0c291SJonathan Doman             }
590dba0c291SJonathan Doman 
591ac106bf6SEd Tanous             nlohmann::json& json = asyncResp->res.jsonValue;
592dba0c291SJonathan Doman 
593351053f2SKrzysztof Grobelny             const sdbusplus::message::object_path* appliedConfig = nullptr;
594351053f2SKrzysztof Grobelny             const bool* baseSpeedPriorityEnabled = nullptr;
595351053f2SKrzysztof Grobelny 
596351053f2SKrzysztof Grobelny             const bool success = sdbusplus::unpackPropertiesNoThrow(
597351053f2SKrzysztof Grobelny                 dbus_utils::UnpackErrorPrinter(), properties, "AppliedConfig",
598351053f2SKrzysztof Grobelny                 appliedConfig, "BaseSpeedPriorityEnabled",
599351053f2SKrzysztof Grobelny                 baseSpeedPriorityEnabled);
600351053f2SKrzysztof Grobelny 
601351053f2SKrzysztof Grobelny             if (!success)
602dba0c291SJonathan Doman             {
603ac106bf6SEd Tanous                 messages::internalError(asyncResp->res);
604351053f2SKrzysztof Grobelny                 return;
605dba0c291SJonathan Doman             }
606dba0c291SJonathan Doman 
607351053f2SKrzysztof Grobelny             if (appliedConfig != nullptr)
608351053f2SKrzysztof Grobelny             {
609351053f2SKrzysztof Grobelny                 const std::string& dbusPath = appliedConfig->str;
6101476687dSEd Tanous                 nlohmann::json::object_t operatingConfig;
611ef4c65b7SEd Tanous                 operatingConfig["@odata.id"] = boost::urls::format(
612253f11b8SEd Tanous                     "/redfish/v1/Systems/{}/Processors/{}/OperatingConfigs",
613253f11b8SEd Tanous                     BMCWEB_REDFISH_SYSTEM_URI_NAME, cpuId);
6141476687dSEd Tanous                 json["OperatingConfigs"] = std::move(operatingConfig);
615dba0c291SJonathan Doman 
616dba0c291SJonathan Doman                 // Reuse the D-Bus config object name for the Redfish
617dba0c291SJonathan Doman                 // URI
618dba0c291SJonathan Doman                 size_t baseNamePos = dbusPath.rfind('/');
619dba0c291SJonathan Doman                 if (baseNamePos == std::string::npos ||
620dba0c291SJonathan Doman                     baseNamePos == (dbusPath.size() - 1))
621dba0c291SJonathan Doman                 {
622dba0c291SJonathan Doman                     // If the AppliedConfig was somehow not a valid path,
623dba0c291SJonathan Doman                     // skip adding any more properties, since everything
624dba0c291SJonathan Doman                     // else is tied to this applied config.
625ac106bf6SEd Tanous                     messages::internalError(asyncResp->res);
626351053f2SKrzysztof Grobelny                     return;
627dba0c291SJonathan Doman                 }
6281476687dSEd Tanous                 nlohmann::json::object_t appliedOperatingConfig;
629ef4c65b7SEd Tanous                 appliedOperatingConfig["@odata.id"] = boost::urls::format(
630253f11b8SEd Tanous                     "/redfish/v1/Systems/{}/Processors/{}/OperatingConfigs/{}",
631253f11b8SEd Tanous                     BMCWEB_REDFISH_SYSTEM_URI_NAME, cpuId,
632253f11b8SEd Tanous                     dbusPath.substr(baseNamePos + 1));
633bd79bce8SPatrick Williams                 json["AppliedOperatingConfig"] =
634bd79bce8SPatrick Williams                     std::move(appliedOperatingConfig);
635dba0c291SJonathan Doman 
636dba0c291SJonathan Doman                 // Once we found the current applied config, queue another
637dba0c291SJonathan Doman                 // request to read the base freq core ids out of that
638dba0c291SJonathan Doman                 // config.
639*deae6a78SEd Tanous                 dbus::utility::getProperty<BaseSpeedPrioritySettingsProperty>(
640*deae6a78SEd Tanous                     service, dbusPath,
6411e1e598dSJonathan Doman                     "xyz.openbmc_project.Inventory.Item.Cpu."
6421e1e598dSJonathan Doman                     "OperatingConfig",
6431e1e598dSJonathan Doman                     "BaseSpeedPrioritySettings",
644bd79bce8SPatrick Williams                     [asyncResp](const boost::system::error_code& ec2,
645bd79bce8SPatrick Williams                                 const BaseSpeedPrioritySettingsProperty&
646bd79bce8SPatrick Williams                                     baseSpeedList) {
6478a592810SEd Tanous                         if (ec2)
648dba0c291SJonathan Doman                         {
649bd79bce8SPatrick Williams                             BMCWEB_LOG_WARNING("D-Bus Property Get error: {}",
650bd79bce8SPatrick Williams                                                ec2);
651ac106bf6SEd Tanous                             messages::internalError(asyncResp->res);
652dba0c291SJonathan Doman                             return;
653dba0c291SJonathan Doman                         }
6541e1e598dSJonathan Doman 
655ac106bf6SEd Tanous                         highSpeedCoreIdsHandler(asyncResp, baseSpeedList);
6561e1e598dSJonathan Doman                     });
657dba0c291SJonathan Doman             }
658351053f2SKrzysztof Grobelny 
659351053f2SKrzysztof Grobelny             if (baseSpeedPriorityEnabled != nullptr)
660dba0c291SJonathan Doman             {
661dba0c291SJonathan Doman                 json["BaseSpeedPriorityState"] =
662351053f2SKrzysztof Grobelny                     *baseSpeedPriorityEnabled ? "Enabled" : "Disabled";
663dba0c291SJonathan Doman             }
664351053f2SKrzysztof Grobelny         });
665dba0c291SJonathan Doman }
666dba0c291SJonathan Doman 
667cba4f448SSunnySrivastava1984 /**
668cba4f448SSunnySrivastava1984  * @brief Fill out location info of a processor by
669cba4f448SSunnySrivastava1984  * requesting data from the given D-Bus object.
670cba4f448SSunnySrivastava1984  *
671ac106bf6SEd Tanous  * @param[in,out]   asyncResp       Async HTTP response.
672cba4f448SSunnySrivastava1984  * @param[in]       service     D-Bus service to query.
673cba4f448SSunnySrivastava1984  * @param[in]       objPath     D-Bus object to query.
674cba4f448SSunnySrivastava1984  */
675ac106bf6SEd Tanous inline void getCpuLocationCode(std::shared_ptr<bmcweb::AsyncResp> asyncResp,
676cba4f448SSunnySrivastava1984                                const std::string& service,
677cba4f448SSunnySrivastava1984                                const std::string& objPath)
678cba4f448SSunnySrivastava1984 {
67962598e31SEd Tanous     BMCWEB_LOG_DEBUG("Get Cpu Location Data");
680*deae6a78SEd Tanous     dbus::utility::getProperty<std::string>(
681*deae6a78SEd Tanous         service, objPath,
6821e1e598dSJonathan Doman         "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode",
683ac106bf6SEd Tanous         [objPath, asyncResp{std::move(asyncResp)}](
684ac106bf6SEd Tanous             const boost::system::error_code& ec, const std::string& property) {
685cba4f448SSunnySrivastava1984             if (ec)
686cba4f448SSunnySrivastava1984             {
68762598e31SEd Tanous                 BMCWEB_LOG_DEBUG("DBUS response error");
688ac106bf6SEd Tanous                 messages::internalError(asyncResp->res);
689cba4f448SSunnySrivastava1984                 return;
690cba4f448SSunnySrivastava1984             }
691cba4f448SSunnySrivastava1984 
692bd79bce8SPatrick Williams             asyncResp->res
693bd79bce8SPatrick Williams                 .jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
6941e1e598dSJonathan Doman                 property;
6951e1e598dSJonathan Doman         });
696cba4f448SSunnySrivastava1984 }
697cba4f448SSunnySrivastava1984 
698c951448aSJonathan Doman /**
69949e429caSJonathan Doman  * Populate the unique identifier in a Processor resource by requesting data
70049e429caSJonathan Doman  * from the given D-Bus object.
70149e429caSJonathan Doman  *
702ac106bf6SEd Tanous  * @param[in,out]   asyncResp   Async HTTP response.
70349e429caSJonathan Doman  * @param[in]       service     D-Bus service to query.
70449e429caSJonathan Doman  * @param[in]       objPath     D-Bus object to query.
70549e429caSJonathan Doman  */
706ac106bf6SEd Tanous inline void getCpuUniqueId(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
70749e429caSJonathan Doman                            const std::string& service,
70849e429caSJonathan Doman                            const std::string& objectPath)
70949e429caSJonathan Doman {
71062598e31SEd Tanous     BMCWEB_LOG_DEBUG("Get CPU UniqueIdentifier");
711*deae6a78SEd Tanous     dbus::utility::getProperty<std::string>(
712*deae6a78SEd Tanous         service, objectPath,
7131e1e598dSJonathan Doman         "xyz.openbmc_project.Inventory.Decorator.UniqueIdentifier",
7141e1e598dSJonathan Doman         "UniqueIdentifier",
715ac106bf6SEd Tanous         [asyncResp](const boost::system::error_code& ec,
716ac106bf6SEd Tanous                     const std::string& id) {
7171e1e598dSJonathan Doman             if (ec)
71849e429caSJonathan Doman             {
71962598e31SEd Tanous                 BMCWEB_LOG_ERROR("Failed to read cpu unique id: {}", ec);
720ac106bf6SEd Tanous                 messages::internalError(asyncResp->res);
72149e429caSJonathan Doman                 return;
72249e429caSJonathan Doman             }
723ac106bf6SEd Tanous             asyncResp->res
724ac106bf6SEd Tanous                 .jsonValue["ProcessorId"]["ProtectedIdentificationNumber"] = id;
7251e1e598dSJonathan Doman         });
72649e429caSJonathan Doman }
72749e429caSJonathan Doman 
72849e429caSJonathan Doman /**
729c951448aSJonathan Doman  * Find the D-Bus object representing the requested Processor, and call the
730c951448aSJonathan Doman  * handler with the results. If matching object is not found, add 404 error to
731c951448aSJonathan Doman  * response and don't call the handler.
732c951448aSJonathan Doman  *
733c951448aSJonathan Doman  * @param[in,out]   resp            Async HTTP response.
734c951448aSJonathan Doman  * @param[in]       processorId     Redfish Processor Id.
735c951448aSJonathan Doman  * @param[in]       handler         Callback to continue processing request upon
736c951448aSJonathan Doman  *                                  successfully finding object.
737c951448aSJonathan Doman  */
738c951448aSJonathan Doman template <typename Handler>
7398d1b46d7Szhanghch05 inline void getProcessorObject(const std::shared_ptr<bmcweb::AsyncResp>& resp,
740c951448aSJonathan Doman                                const std::string& processorId,
741c951448aSJonathan Doman                                Handler&& handler)
742ac6a4445SGunnar Mills {
74362598e31SEd Tanous     BMCWEB_LOG_DEBUG("Get available system processor resources.");
744ac6a4445SGunnar Mills 
745c951448aSJonathan Doman     // GetSubTree on all interfaces which provide info about a Processor
746dfbf7de5SChris Cain     constexpr std::array<std::string_view, 9> interfaces = {
747e99073f5SGeorge Liu         "xyz.openbmc_project.Common.UUID",
748e99073f5SGeorge Liu         "xyz.openbmc_project.Inventory.Decorator.Asset",
749e99073f5SGeorge Liu         "xyz.openbmc_project.Inventory.Decorator.Revision",
750e99073f5SGeorge Liu         "xyz.openbmc_project.Inventory.Item.Cpu",
751e99073f5SGeorge Liu         "xyz.openbmc_project.Inventory.Decorator.LocationCode",
752e99073f5SGeorge Liu         "xyz.openbmc_project.Inventory.Item.Accelerator",
753e99073f5SGeorge Liu         "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig",
754dfbf7de5SChris Cain         "xyz.openbmc_project.Inventory.Decorator.UniqueIdentifier",
755dfbf7de5SChris Cain         "xyz.openbmc_project.Control.Power.Throttle"};
756e99073f5SGeorge Liu     dbus::utility::getSubTree(
757e99073f5SGeorge Liu         "/xyz/openbmc_project/inventory", 0, interfaces,
758c951448aSJonathan Doman         [resp, processorId, handler = std::forward<Handler>(handler)](
759e99073f5SGeorge Liu             const boost::system::error_code& ec,
760e99073f5SGeorge Liu             const dbus::utility::MapperGetSubTreeResponse& subtree) {
761ac6a4445SGunnar Mills             if (ec)
762ac6a4445SGunnar Mills             {
76362598e31SEd Tanous                 BMCWEB_LOG_DEBUG("DBUS response error: {}", ec);
764c951448aSJonathan Doman                 messages::internalError(resp->res);
765ac6a4445SGunnar Mills                 return;
766ac6a4445SGunnar Mills             }
7672bab9831SJonathan Doman             for (const auto& [objectPath, serviceMap] : subtree)
768ac6a4445SGunnar Mills             {
7692bab9831SJonathan Doman                 // Ignore any objects which don't end with our desired cpu name
77011ba3979SEd Tanous                 if (!objectPath.ends_with(processorId))
771ac6a4445SGunnar Mills                 {
7722bab9831SJonathan Doman                     continue;
773ac6a4445SGunnar Mills                 }
7742bab9831SJonathan Doman 
775c951448aSJonathan Doman                 bool found = false;
776c951448aSJonathan Doman                 // Filter out objects that don't have the CPU-specific
777c951448aSJonathan Doman                 // interfaces to make sure we can return 404 on non-CPUs
778c951448aSJonathan Doman                 // (e.g. /redfish/../Processors/dimm0)
7792bab9831SJonathan Doman                 for (const auto& [serviceName, interfaceList] : serviceMap)
780ac6a4445SGunnar Mills                 {
7813544d2a7SEd Tanous                     if (std::ranges::find_first_of(interfaceList,
7823544d2a7SEd Tanous                                                    processorInterfaces) !=
7833544d2a7SEd Tanous                         std::end(interfaceList))
7842bab9831SJonathan Doman                     {
785c951448aSJonathan Doman                         found = true;
786c951448aSJonathan Doman                         break;
787c951448aSJonathan Doman                     }
788c951448aSJonathan Doman                 }
789c951448aSJonathan Doman 
790c951448aSJonathan Doman                 if (!found)
7912bab9831SJonathan Doman                 {
792c951448aSJonathan Doman                     continue;
793ac6a4445SGunnar Mills                 }
794c951448aSJonathan Doman 
795c951448aSJonathan Doman                 // Process the first object which does match our cpu name and
796c951448aSJonathan Doman                 // required interfaces, and potentially ignore any other
797c951448aSJonathan Doman                 // matching objects. Assume all interfaces we want to process
798c951448aSJonathan Doman                 // must be on the same object path.
799c951448aSJonathan Doman 
8008a592810SEd Tanous                 handler(objectPath, serviceMap);
801ac6a4445SGunnar Mills                 return;
802ac6a4445SGunnar Mills             }
803c951448aSJonathan Doman             messages::resourceNotFound(resp->res, "Processor", processorId);
804e99073f5SGeorge Liu         });
805ac6a4445SGunnar Mills }
806ac6a4445SGunnar Mills 
807bd79bce8SPatrick Williams inline void getProcessorData(
808bd79bce8SPatrick Williams     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
809bd79bce8SPatrick Williams     const std::string& processorId, const std::string& objectPath,
8105df6eda2SShantappa Teekappanavar     const dbus::utility::MapperServiceMap& serviceMap)
811c951448aSJonathan Doman {
812c951448aSJonathan Doman     for (const auto& [serviceName, interfaceList] : serviceMap)
813c951448aSJonathan Doman     {
814c951448aSJonathan Doman         for (const auto& interface : interfaceList)
815c951448aSJonathan Doman         {
816c951448aSJonathan Doman             if (interface == "xyz.openbmc_project.Inventory.Decorator.Asset")
817c951448aSJonathan Doman             {
818ac106bf6SEd Tanous                 getCpuAssetData(asyncResp, serviceName, objectPath);
819c951448aSJonathan Doman             }
8200fda0f12SGeorge Liu             else if (interface ==
8210fda0f12SGeorge Liu                      "xyz.openbmc_project.Inventory.Decorator.Revision")
822c951448aSJonathan Doman             {
823ac106bf6SEd Tanous                 getCpuRevisionData(asyncResp, serviceName, objectPath);
824c951448aSJonathan Doman             }
825c951448aSJonathan Doman             else if (interface == "xyz.openbmc_project.Inventory.Item.Cpu")
826c951448aSJonathan Doman             {
827ac106bf6SEd Tanous                 getCpuDataByService(asyncResp, processorId, serviceName,
828c951448aSJonathan Doman                                     objectPath);
829c951448aSJonathan Doman             }
8300fda0f12SGeorge Liu             else if (interface ==
8310fda0f12SGeorge Liu                      "xyz.openbmc_project.Inventory.Item.Accelerator")
832c951448aSJonathan Doman             {
833ac106bf6SEd Tanous                 getAcceleratorDataByService(asyncResp, processorId, serviceName,
834c951448aSJonathan Doman                                             objectPath);
835c951448aSJonathan Doman             }
8360fda0f12SGeorge Liu             else if (
8370fda0f12SGeorge Liu                 interface ==
8380fda0f12SGeorge Liu                 "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig")
839c951448aSJonathan Doman             {
840ac106bf6SEd Tanous                 getCpuConfigData(asyncResp, processorId, serviceName,
841ac106bf6SEd Tanous                                  objectPath);
842c951448aSJonathan Doman             }
8430fda0f12SGeorge Liu             else if (interface ==
8440fda0f12SGeorge Liu                      "xyz.openbmc_project.Inventory.Decorator.LocationCode")
845c951448aSJonathan Doman             {
846ac106bf6SEd Tanous                 getCpuLocationCode(asyncResp, serviceName, objectPath);
847c951448aSJonathan Doman             }
84871b82f26SSharad Yadav             else if (interface == "xyz.openbmc_project.Common.UUID")
84971b82f26SSharad Yadav             {
850ac106bf6SEd Tanous                 getProcessorUUID(asyncResp, serviceName, objectPath);
85171b82f26SSharad Yadav             }
8520fda0f12SGeorge Liu             else if (interface ==
8530fda0f12SGeorge Liu                      "xyz.openbmc_project.Inventory.Decorator.UniqueIdentifier")
85449e429caSJonathan Doman             {
855ac106bf6SEd Tanous                 getCpuUniqueId(asyncResp, serviceName, objectPath);
85649e429caSJonathan Doman             }
857dfbf7de5SChris Cain             else if (interface == "xyz.openbmc_project.Control.Power.Throttle")
858dfbf7de5SChris Cain             {
859ac106bf6SEd Tanous                 getThrottleProperties(asyncResp, serviceName, objectPath);
860dfbf7de5SChris Cain             }
861c951448aSJonathan Doman         }
862c951448aSJonathan Doman     }
863c951448aSJonathan Doman }
864c951448aSJonathan Doman 
865dba0c291SJonathan Doman /**
866dba0c291SJonathan Doman  * Request all the properties for the given D-Bus object and fill out the
867dba0c291SJonathan Doman  * related entries in the Redfish OperatingConfig response.
868dba0c291SJonathan Doman  *
869ac106bf6SEd Tanous  * @param[in,out]   asyncResp       Async HTTP response.
870dba0c291SJonathan Doman  * @param[in]       service     D-Bus service name to query.
871dba0c291SJonathan Doman  * @param[in]       objPath     D-Bus object to query.
872dba0c291SJonathan Doman  */
873bd79bce8SPatrick Williams inline void getOperatingConfigData(
874bd79bce8SPatrick Williams     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
875bd79bce8SPatrick Williams     const std::string& service, const std::string& objPath)
876dba0c291SJonathan Doman {
877*deae6a78SEd Tanous     dbus::utility::getAllProperties(
878*deae6a78SEd Tanous         service, objPath,
879351053f2SKrzysztof Grobelny         "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig",
880ac106bf6SEd Tanous         [asyncResp](const boost::system::error_code& ec,
881351053f2SKrzysztof Grobelny                     const dbus::utility::DBusPropertiesMap& properties) {
882dba0c291SJonathan Doman             if (ec)
883dba0c291SJonathan Doman             {
88462598e31SEd Tanous                 BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec, ec.message());
885ac106bf6SEd Tanous                 messages::internalError(asyncResp->res);
886dba0c291SJonathan Doman                 return;
887dba0c291SJonathan Doman             }
888dba0c291SJonathan Doman 
889351053f2SKrzysztof Grobelny             const size_t* availableCoreCount = nullptr;
890351053f2SKrzysztof Grobelny             const uint32_t* baseSpeed = nullptr;
891351053f2SKrzysztof Grobelny             const uint32_t* maxJunctionTemperature = nullptr;
892351053f2SKrzysztof Grobelny             const uint32_t* maxSpeed = nullptr;
893351053f2SKrzysztof Grobelny             const uint32_t* powerLimit = nullptr;
894351053f2SKrzysztof Grobelny             const TurboProfileProperty* turboProfile = nullptr;
895351053f2SKrzysztof Grobelny             const BaseSpeedPrioritySettingsProperty* baseSpeedPrioritySettings =
896351053f2SKrzysztof Grobelny                 nullptr;
897351053f2SKrzysztof Grobelny 
898351053f2SKrzysztof Grobelny             const bool success = sdbusplus::unpackPropertiesNoThrow(
899bd79bce8SPatrick Williams                 dbus_utils::UnpackErrorPrinter(), properties,
900bd79bce8SPatrick Williams                 "AvailableCoreCount", availableCoreCount, "BaseSpeed",
901bd79bce8SPatrick Williams                 baseSpeed, "MaxJunctionTemperature", maxJunctionTemperature,
902bd79bce8SPatrick Williams                 "MaxSpeed", maxSpeed, "PowerLimit", powerLimit, "TurboProfile",
903bd79bce8SPatrick Williams                 turboProfile, "BaseSpeedPrioritySettings",
904bd79bce8SPatrick Williams                 baseSpeedPrioritySettings);
905351053f2SKrzysztof Grobelny 
906351053f2SKrzysztof Grobelny             if (!success)
907dba0c291SJonathan Doman             {
908ac106bf6SEd Tanous                 messages::internalError(asyncResp->res);
909351053f2SKrzysztof Grobelny                 return;
910dba0c291SJonathan Doman             }
911dba0c291SJonathan Doman 
912ac106bf6SEd Tanous             nlohmann::json& json = asyncResp->res.jsonValue;
913351053f2SKrzysztof Grobelny 
914351053f2SKrzysztof Grobelny             if (availableCoreCount != nullptr)
915351053f2SKrzysztof Grobelny             {
916351053f2SKrzysztof Grobelny                 json["TotalAvailableCoreCount"] = *availableCoreCount;
917351053f2SKrzysztof Grobelny             }
918351053f2SKrzysztof Grobelny 
919351053f2SKrzysztof Grobelny             if (baseSpeed != nullptr)
920351053f2SKrzysztof Grobelny             {
921351053f2SKrzysztof Grobelny                 json["BaseSpeedMHz"] = *baseSpeed;
922351053f2SKrzysztof Grobelny             }
923351053f2SKrzysztof Grobelny 
924351053f2SKrzysztof Grobelny             if (maxJunctionTemperature != nullptr)
925351053f2SKrzysztof Grobelny             {
926351053f2SKrzysztof Grobelny                 json["MaxJunctionTemperatureCelsius"] = *maxJunctionTemperature;
927351053f2SKrzysztof Grobelny             }
928351053f2SKrzysztof Grobelny 
929351053f2SKrzysztof Grobelny             if (maxSpeed != nullptr)
930351053f2SKrzysztof Grobelny             {
931351053f2SKrzysztof Grobelny                 json["MaxSpeedMHz"] = *maxSpeed;
932351053f2SKrzysztof Grobelny             }
933351053f2SKrzysztof Grobelny 
934351053f2SKrzysztof Grobelny             if (powerLimit != nullptr)
935351053f2SKrzysztof Grobelny             {
936351053f2SKrzysztof Grobelny                 json["TDPWatts"] = *powerLimit;
937351053f2SKrzysztof Grobelny             }
938351053f2SKrzysztof Grobelny 
939351053f2SKrzysztof Grobelny             if (turboProfile != nullptr)
940351053f2SKrzysztof Grobelny             {
941dba0c291SJonathan Doman                 nlohmann::json& turboArray = json["TurboProfile"];
942dba0c291SJonathan Doman                 turboArray = nlohmann::json::array();
943351053f2SKrzysztof Grobelny                 for (const auto& [turboSpeed, coreCount] : *turboProfile)
944dba0c291SJonathan Doman                 {
9451476687dSEd Tanous                     nlohmann::json::object_t turbo;
9461476687dSEd Tanous                     turbo["ActiveCoreCount"] = coreCount;
9471476687dSEd Tanous                     turbo["MaxSpeedMHz"] = turboSpeed;
948b2ba3072SPatrick Williams                     turboArray.emplace_back(std::move(turbo));
949dba0c291SJonathan Doman                 }
950dba0c291SJonathan Doman             }
951dba0c291SJonathan Doman 
952351053f2SKrzysztof Grobelny             if (baseSpeedPrioritySettings != nullptr)
953351053f2SKrzysztof Grobelny             {
954bd79bce8SPatrick Williams                 nlohmann::json& baseSpeedArray =
955bd79bce8SPatrick Williams                     json["BaseSpeedPrioritySettings"];
956dba0c291SJonathan Doman                 baseSpeedArray = nlohmann::json::array();
957351053f2SKrzysztof Grobelny                 for (const auto& [baseSpeedMhz, coreList] :
958351053f2SKrzysztof Grobelny                      *baseSpeedPrioritySettings)
959dba0c291SJonathan Doman                 {
9601476687dSEd Tanous                     nlohmann::json::object_t speed;
9611476687dSEd Tanous                     speed["CoreCount"] = coreList.size();
9621476687dSEd Tanous                     speed["CoreIDs"] = coreList;
963351053f2SKrzysztof Grobelny                     speed["BaseSpeedMHz"] = baseSpeedMhz;
964b2ba3072SPatrick Williams                     baseSpeedArray.emplace_back(std::move(speed));
965dba0c291SJonathan Doman                 }
966dba0c291SJonathan Doman             }
967351053f2SKrzysztof Grobelny         });
968dba0c291SJonathan Doman }
969dba0c291SJonathan Doman 
9703cde86f1SJonathan Doman /**
9713cde86f1SJonathan Doman  * Handle the PATCH operation of the AppliedOperatingConfig property. Do basic
9723cde86f1SJonathan Doman  * validation of the input data, and then set the D-Bus property.
9733cde86f1SJonathan Doman  *
9743cde86f1SJonathan Doman  * @param[in,out]   resp            Async HTTP response.
9753cde86f1SJonathan Doman  * @param[in]       processorId     Processor's Id.
9763cde86f1SJonathan Doman  * @param[in]       appliedConfigUri    New property value to apply.
9773cde86f1SJonathan Doman  * @param[in]       cpuObjectPath   Path of CPU object to modify.
9783cde86f1SJonathan Doman  * @param[in]       serviceMap      Service map for CPU object.
9793cde86f1SJonathan Doman  */
9803cde86f1SJonathan Doman inline void patchAppliedOperatingConfig(
9813cde86f1SJonathan Doman     const std::shared_ptr<bmcweb::AsyncResp>& resp,
9823cde86f1SJonathan Doman     const std::string& processorId, const std::string& appliedConfigUri,
9835df6eda2SShantappa Teekappanavar     const std::string& cpuObjectPath,
9845df6eda2SShantappa Teekappanavar     const dbus::utility::MapperServiceMap& serviceMap)
9853cde86f1SJonathan Doman {
9863cde86f1SJonathan Doman     // Check that the property even exists by checking for the interface
9873cde86f1SJonathan Doman     const std::string* controlService = nullptr;
9883cde86f1SJonathan Doman     for (const auto& [serviceName, interfaceList] : serviceMap)
9893cde86f1SJonathan Doman     {
9903544d2a7SEd Tanous         if (std::ranges::find(interfaceList,
9913cde86f1SJonathan Doman                               "xyz.openbmc_project.Control.Processor."
9923cde86f1SJonathan Doman                               "CurrentOperatingConfig") != interfaceList.end())
9933cde86f1SJonathan Doman         {
9943cde86f1SJonathan Doman             controlService = &serviceName;
9953cde86f1SJonathan Doman             break;
9963cde86f1SJonathan Doman         }
9973cde86f1SJonathan Doman     }
9983cde86f1SJonathan Doman 
9993cde86f1SJonathan Doman     if (controlService == nullptr)
10003cde86f1SJonathan Doman     {
10013cde86f1SJonathan Doman         messages::internalError(resp->res);
10023cde86f1SJonathan Doman         return;
10033cde86f1SJonathan Doman     }
10043cde86f1SJonathan Doman 
10053cde86f1SJonathan Doman     // Check that the config URI is a child of the cpu URI being patched.
1006253f11b8SEd Tanous     std::string expectedPrefix(std::format("/redfish/v1/Systems/{}/Processors/",
1007253f11b8SEd Tanous                                            BMCWEB_REDFISH_SYSTEM_URI_NAME));
10083cde86f1SJonathan Doman     expectedPrefix += processorId;
10093cde86f1SJonathan Doman     expectedPrefix += "/OperatingConfigs/";
101011ba3979SEd Tanous     if (!appliedConfigUri.starts_with(expectedPrefix) ||
10113cde86f1SJonathan Doman         expectedPrefix.size() == appliedConfigUri.size())
10123cde86f1SJonathan Doman     {
101387c44966SAsmitha Karunanithi         messages::propertyValueIncorrect(resp->res, "AppliedOperatingConfig",
101487c44966SAsmitha Karunanithi                                          appliedConfigUri);
10153cde86f1SJonathan Doman         return;
10163cde86f1SJonathan Doman     }
10173cde86f1SJonathan Doman 
10183cde86f1SJonathan Doman     // Generate the D-Bus path of the OperatingConfig object, by assuming it's a
10193cde86f1SJonathan Doman     // direct child of the CPU object.
10203cde86f1SJonathan Doman     // Strip the expectedPrefix from the config URI to get the "filename", and
10213cde86f1SJonathan Doman     // append to the CPU's path.
10223cde86f1SJonathan Doman     std::string configBaseName = appliedConfigUri.substr(expectedPrefix.size());
10233cde86f1SJonathan Doman     sdbusplus::message::object_path configPath(cpuObjectPath);
10243cde86f1SJonathan Doman     configPath /= configBaseName;
10253cde86f1SJonathan Doman 
102662598e31SEd Tanous     BMCWEB_LOG_INFO("Setting config to {}", configPath.str);
10273cde86f1SJonathan Doman 
10283cde86f1SJonathan Doman     // Set the property, with handler to check error responses
102987c44966SAsmitha Karunanithi     setDbusProperty(
1030e93abac6SGinu George         resp, "AppliedOperatingConfig", *controlService, cpuObjectPath,
10319ae226faSGeorge Liu         "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig",
1032e93abac6SGinu George         "AppliedConfig", configPath);
10333cde86f1SJonathan Doman }
10343cde86f1SJonathan Doman 
1035bd79bce8SPatrick Williams inline void handleProcessorHead(
1036bd79bce8SPatrick Williams     crow::App& app, const crow::Request& req,
1037ac106bf6SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1038bd79bce8SPatrick Williams     const std::string& /* systemName */, const std::string& /* processorId */)
103971a24ca4SNikhil Namjoshi {
1040ac106bf6SEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
104171a24ca4SNikhil Namjoshi     {
104271a24ca4SNikhil Namjoshi         return;
104371a24ca4SNikhil Namjoshi     }
1044ac106bf6SEd Tanous     asyncResp->res.addHeader(
104571a24ca4SNikhil Namjoshi         boost::beast::http::field::link,
104671a24ca4SNikhil Namjoshi         "</redfish/v1/JsonSchemas/Processor/Processor.json>; rel=describedby");
104771a24ca4SNikhil Namjoshi }
104871a24ca4SNikhil Namjoshi 
104971a24ca4SNikhil Namjoshi inline void handleProcessorCollectionHead(
105071a24ca4SNikhil Namjoshi     crow::App& app, const crow::Request& req,
1051ac106bf6SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
105271a24ca4SNikhil Namjoshi     const std::string& /* systemName */)
105371a24ca4SNikhil Namjoshi {
1054ac106bf6SEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
105571a24ca4SNikhil Namjoshi     {
105671a24ca4SNikhil Namjoshi         return;
105771a24ca4SNikhil Namjoshi     }
1058ac106bf6SEd Tanous     asyncResp->res.addHeader(
105971a24ca4SNikhil Namjoshi         boost::beast::http::field::link,
106071a24ca4SNikhil Namjoshi         "</redfish/v1/JsonSchemas/ProcessorCollection/ProcessorCollection.json>; rel=describedby");
106171a24ca4SNikhil Namjoshi }
106271a24ca4SNikhil Namjoshi 
10637e860f15SJohn Edward Broadbent inline void requestRoutesOperatingConfigCollection(App& app)
1064dba0c291SJonathan Doman {
10657f3e84a1SEd Tanous     BMCWEB_ROUTE(app,
10667f3e84a1SEd Tanous                  "/redfish/v1/Systems/<str>/Processors/<str>/OperatingConfigs/")
1067ed398213SEd Tanous         .privileges(redfish::privileges::getOperatingConfigCollection)
1068bd79bce8SPatrick Williams         .methods(
1069bd79bce8SPatrick Williams             boost::beast::http::verb::
1070bd79bce8SPatrick Williams                 get)([&app](const crow::Request& req,
107145ca1b86SEd Tanous                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1072bd79bce8SPatrick Williams                             const std::string& systemName,
1073bd79bce8SPatrick Williams                             const std::string& cpuName) {
10743ba00073SCarson Labrado             if (!redfish::setUpRedfishRoute(app, req, asyncResp))
107545ca1b86SEd Tanous             {
107645ca1b86SEd Tanous                 return;
107745ca1b86SEd Tanous             }
10787f3e84a1SEd Tanous 
107925b54dbaSEd Tanous             if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
10807f3e84a1SEd Tanous             {
10817f3e84a1SEd Tanous                 // Option currently returns no systems.  TBD
10827f3e84a1SEd Tanous                 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
10837f3e84a1SEd Tanous                                            systemName);
10847f3e84a1SEd Tanous                 return;
10857f3e84a1SEd Tanous             }
10867f3e84a1SEd Tanous 
1087253f11b8SEd Tanous             if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
10887f3e84a1SEd Tanous             {
10897f3e84a1SEd Tanous                 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
10907f3e84a1SEd Tanous                                            systemName);
10917f3e84a1SEd Tanous                 return;
10927f3e84a1SEd Tanous             }
10938d1b46d7Szhanghch05             asyncResp->res.jsonValue["@odata.type"] =
1094dba0c291SJonathan Doman                 "#OperatingConfigCollection.OperatingConfigCollection";
1095ef4c65b7SEd Tanous             asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
1096253f11b8SEd Tanous                 "/redfish/v1/Systems/{}/Processors/{}/OperatingConfigs",
1097253f11b8SEd Tanous                 BMCWEB_REDFISH_SYSTEM_URI_NAME, cpuName);
10980fda0f12SGeorge Liu             asyncResp->res.jsonValue["Name"] = "Operating Config Collection";
1099dba0c291SJonathan Doman 
11007e860f15SJohn Edward Broadbent             // First find the matching CPU object so we know how to
11017e860f15SJohn Edward Broadbent             // constrain our search for related Config objects.
11027a1dbc48SGeorge Liu             const std::array<std::string_view, 1> interfaces = {
11037a1dbc48SGeorge Liu                 "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig"};
11047a1dbc48SGeorge Liu             dbus::utility::getSubTreePaths(
11057a1dbc48SGeorge Liu                 "/xyz/openbmc_project/inventory", 0, interfaces,
1106bd79bce8SPatrick Williams                 [asyncResp,
1107bd79bce8SPatrick Williams                  cpuName](const boost::system::error_code& ec,
1108bd79bce8SPatrick Williams                           const dbus::utility::MapperGetSubTreePathsResponse&
1109bd79bce8SPatrick Williams                               objects) {
1110dba0c291SJonathan Doman                     if (ec)
1111dba0c291SJonathan Doman                     {
1112bd79bce8SPatrick Williams                         BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec,
1113bd79bce8SPatrick Williams                                            ec.message());
1114dba0c291SJonathan Doman                         messages::internalError(asyncResp->res);
1115dba0c291SJonathan Doman                         return;
1116dba0c291SJonathan Doman                     }
1117dba0c291SJonathan Doman 
1118dba0c291SJonathan Doman                     for (const std::string& object : objects)
1119dba0c291SJonathan Doman                     {
112011ba3979SEd Tanous                         if (!object.ends_with(cpuName))
1121dba0c291SJonathan Doman                         {
1122dba0c291SJonathan Doman                             continue;
1123dba0c291SJonathan Doman                         }
1124dba0c291SJonathan Doman 
11257e860f15SJohn Edward Broadbent                         // Not expected that there will be multiple matching
11267e860f15SJohn Edward Broadbent                         // CPU objects, but if there are just use the first
11277e860f15SJohn Edward Broadbent                         // one.
1128dba0c291SJonathan Doman 
11297e860f15SJohn Edward Broadbent                         // Use the common search routine to construct the
11307e860f15SJohn Edward Broadbent                         // Collection of all Config objects under this CPU.
11317a1dbc48SGeorge Liu                         constexpr std::array<std::string_view, 1> interface{
11325a39f77aSPatrick Williams                             "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig"};
1133dba0c291SJonathan Doman                         collection_util::getCollectionMembers(
1134dba0c291SJonathan Doman                             asyncResp,
1135ef4c65b7SEd Tanous                             boost::urls::format(
1136253f11b8SEd Tanous                                 "/redfish/v1/Systems/{}/Processors/{}/OperatingConfigs",
1137253f11b8SEd Tanous                                 BMCWEB_REDFISH_SYSTEM_URI_NAME, cpuName),
113836b5f1edSLakshmi Yadlapati                             interface, object);
1139dba0c291SJonathan Doman                         return;
1140dba0c291SJonathan Doman                     }
11417a1dbc48SGeorge Liu                 });
11427e860f15SJohn Edward Broadbent         });
1143dba0c291SJonathan Doman }
1144dba0c291SJonathan Doman 
11457e860f15SJohn Edward Broadbent inline void requestRoutesOperatingConfig(App& app)
1146dba0c291SJonathan Doman {
11477e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(
11487e860f15SJohn Edward Broadbent         app,
11497f3e84a1SEd Tanous         "/redfish/v1/Systems/<str>/Processors/<str>/OperatingConfigs/<str>/")
1150ed398213SEd Tanous         .privileges(redfish::privileges::getOperatingConfig)
1151bd79bce8SPatrick Williams         .methods(
1152bd79bce8SPatrick Williams             boost::beast::http::verb::
1153bd79bce8SPatrick Williams                 get)([&app](const crow::Request& req,
115445ca1b86SEd Tanous                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1155bd79bce8SPatrick Williams                             const std::string& systemName,
1156bd79bce8SPatrick Williams                             const std::string& cpuName,
11577f3e84a1SEd Tanous                             const std::string& configName) {
11583ba00073SCarson Labrado             if (!redfish::setUpRedfishRoute(app, req, asyncResp))
115945ca1b86SEd Tanous             {
116045ca1b86SEd Tanous                 return;
116145ca1b86SEd Tanous             }
116225b54dbaSEd Tanous             if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
11637f3e84a1SEd Tanous             {
11647f3e84a1SEd Tanous                 // Option currently returns no systems.  TBD
11657f3e84a1SEd Tanous                 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
11667f3e84a1SEd Tanous                                            systemName);
11677f3e84a1SEd Tanous                 return;
11687f3e84a1SEd Tanous             }
11697f3e84a1SEd Tanous 
1170253f11b8SEd Tanous             if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
11717f3e84a1SEd Tanous             {
11727f3e84a1SEd Tanous                 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
11737f3e84a1SEd Tanous                                            systemName);
11747f3e84a1SEd Tanous                 return;
11757f3e84a1SEd Tanous             }
11767e860f15SJohn Edward Broadbent             // Ask for all objects implementing OperatingConfig so we can search
11777e860f15SJohn Edward Broadbent             // for one with a matching name
1178e99073f5SGeorge Liu             constexpr std::array<std::string_view, 1> interfaces = {
1179e99073f5SGeorge Liu                 "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig"};
1180e99073f5SGeorge Liu             dbus::utility::getSubTree(
1181e99073f5SGeorge Liu                 "/xyz/openbmc_project/inventory", 0, interfaces,
118239662a3bSEd Tanous                 [asyncResp, cpuName, configName](
1183e99073f5SGeorge Liu                     const boost::system::error_code& ec,
11845df6eda2SShantappa Teekappanavar                     const dbus::utility::MapperGetSubTreeResponse& subtree) {
1185dba0c291SJonathan Doman                     if (ec)
1186dba0c291SJonathan Doman                     {
1187bd79bce8SPatrick Williams                         BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec,
1188bd79bce8SPatrick Williams                                            ec.message());
1189dba0c291SJonathan Doman                         messages::internalError(asyncResp->res);
1190dba0c291SJonathan Doman                         return;
1191dba0c291SJonathan Doman                     }
1192bd79bce8SPatrick Williams                     const std::string expectedEnding =
1193bd79bce8SPatrick Williams                         cpuName + '/' + configName;
1194dba0c291SJonathan Doman                     for (const auto& [objectPath, serviceMap] : subtree)
1195dba0c291SJonathan Doman                     {
1196dba0c291SJonathan Doman                         // Ignore any configs without matching cpuX/configY
1197bd79bce8SPatrick Williams                         if (!objectPath.ends_with(expectedEnding) ||
1198bd79bce8SPatrick Williams                             serviceMap.empty())
1199dba0c291SJonathan Doman                         {
1200dba0c291SJonathan Doman                             continue;
1201dba0c291SJonathan Doman                         }
1202dba0c291SJonathan Doman 
1203dba0c291SJonathan Doman                         nlohmann::json& json = asyncResp->res.jsonValue;
1204bd79bce8SPatrick Williams                         json["@odata.type"] =
1205bd79bce8SPatrick Williams                             "#OperatingConfig.v1_0_0.OperatingConfig";
1206ef4c65b7SEd Tanous                         json["@odata.id"] = boost::urls::format(
1207253f11b8SEd Tanous                             "/redfish/v1/Systems/{}/Processors/{}/OperatingConfigs/{}",
1208bd79bce8SPatrick Williams                             BMCWEB_REDFISH_SYSTEM_URI_NAME, cpuName,
1209bd79bce8SPatrick Williams                             configName);
1210dba0c291SJonathan Doman                         json["Name"] = "Processor Profile";
1211dba0c291SJonathan Doman                         json["Id"] = configName;
1212dba0c291SJonathan Doman 
1213dba0c291SJonathan Doman                         // Just use the first implementation of the object - not
12147e860f15SJohn Edward Broadbent                         // expected that there would be multiple matching
12157e860f15SJohn Edward Broadbent                         // services
1216bd79bce8SPatrick Williams                         getOperatingConfigData(
1217bd79bce8SPatrick Williams                             asyncResp, serviceMap.begin()->first, objectPath);
1218dba0c291SJonathan Doman                         return;
1219dba0c291SJonathan Doman                     }
1220bd79bce8SPatrick Williams                     messages::resourceNotFound(asyncResp->res,
1221bd79bce8SPatrick Williams                                                "OperatingConfig", configName);
1222e99073f5SGeorge Liu                 });
12237e860f15SJohn Edward Broadbent         });
1224ac6a4445SGunnar Mills }
1225ac6a4445SGunnar Mills 
12267e860f15SJohn Edward Broadbent inline void requestRoutesProcessorCollection(App& app)
12277e860f15SJohn Edward Broadbent {
1228ac6a4445SGunnar Mills     /**
1229ac6a4445SGunnar Mills      * Functions triggers appropriate requests on DBus
1230ac6a4445SGunnar Mills      */
123122d268cbSEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/")
123271a24ca4SNikhil Namjoshi         .privileges(redfish::privileges::headProcessorCollection)
123371a24ca4SNikhil Namjoshi         .methods(boost::beast::http::verb::head)(
123471a24ca4SNikhil Namjoshi             std::bind_front(handleProcessorCollectionHead, std::ref(app)));
123571a24ca4SNikhil Namjoshi 
123671a24ca4SNikhil Namjoshi     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/")
1237ed398213SEd Tanous         .privileges(redfish::privileges::getProcessorCollection)
1238bd79bce8SPatrick Williams         .methods(
1239bd79bce8SPatrick Williams             boost::beast::http::verb::
1240bd79bce8SPatrick Williams                 get)([&app](const crow::Request& req,
124122d268cbSEd Tanous                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
124222d268cbSEd Tanous                             const std::string& systemName) {
12433ba00073SCarson Labrado             if (!redfish::setUpRedfishRoute(app, req, asyncResp))
124445ca1b86SEd Tanous             {
124545ca1b86SEd Tanous                 return;
124645ca1b86SEd Tanous             }
124725b54dbaSEd Tanous             if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
12487f3e84a1SEd Tanous             {
12497f3e84a1SEd Tanous                 // Option currently returns no systems.  TBD
12507f3e84a1SEd Tanous                 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
12517f3e84a1SEd Tanous                                            systemName);
12527f3e84a1SEd Tanous                 return;
12537f3e84a1SEd Tanous             }
12547f3e84a1SEd Tanous 
1255253f11b8SEd Tanous             if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
125622d268cbSEd Tanous             {
125722d268cbSEd Tanous                 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
125822d268cbSEd Tanous                                            systemName);
125922d268cbSEd Tanous                 return;
126022d268cbSEd Tanous             }
126122d268cbSEd Tanous 
126271a24ca4SNikhil Namjoshi             asyncResp->res.addHeader(
126371a24ca4SNikhil Namjoshi                 boost::beast::http::field::link,
126471a24ca4SNikhil Namjoshi                 "</redfish/v1/JsonSchemas/ProcessorCollection/ProcessorCollection.json>; rel=describedby");
126571a24ca4SNikhil Namjoshi 
12668d1b46d7Szhanghch05             asyncResp->res.jsonValue["@odata.type"] =
1267ac6a4445SGunnar Mills                 "#ProcessorCollection.ProcessorCollection";
12688d1b46d7Szhanghch05             asyncResp->res.jsonValue["Name"] = "Processor Collection";
1269ac6a4445SGunnar Mills 
12708d1b46d7Szhanghch05             asyncResp->res.jsonValue["@odata.id"] =
1271253f11b8SEd Tanous                 std::format("/redfish/v1/Systems/{}/Processors",
1272253f11b8SEd Tanous                             BMCWEB_REDFISH_SYSTEM_URI_NAME);
1273ac6a4445SGunnar Mills 
127405030b8eSGunnar Mills             collection_util::getCollectionMembers(
1275ae9031f0SWilly Tu                 asyncResp,
1276253f11b8SEd Tanous                 boost::urls::format("/redfish/v1/Systems/{}/Processors",
1277253f11b8SEd Tanous                                     BMCWEB_REDFISH_SYSTEM_URI_NAME),
127836b5f1edSLakshmi Yadlapati                 processorInterfaces, "/xyz/openbmc_project/inventory");
12797e860f15SJohn Edward Broadbent         });
1280ac6a4445SGunnar Mills }
1281ac6a4445SGunnar Mills 
12827e860f15SJohn Edward Broadbent inline void requestRoutesProcessor(App& app)
12837e860f15SJohn Edward Broadbent {
1284ac6a4445SGunnar Mills     /**
1285ac6a4445SGunnar Mills      * Functions triggers appropriate requests on DBus
1286ac6a4445SGunnar Mills      */
12877e860f15SJohn Edward Broadbent 
128822d268cbSEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/<str>/")
128971a24ca4SNikhil Namjoshi         .privileges(redfish::privileges::headProcessor)
129071a24ca4SNikhil Namjoshi         .methods(boost::beast::http::verb::head)(
129171a24ca4SNikhil Namjoshi             std::bind_front(handleProcessorHead, std::ref(app)));
129271a24ca4SNikhil Namjoshi 
129371a24ca4SNikhil Namjoshi     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/<str>/")
1294ed398213SEd Tanous         .privileges(redfish::privileges::getProcessor)
1295bd79bce8SPatrick Williams         .methods(
1296bd79bce8SPatrick Williams             boost::beast::http::verb::
1297bd79bce8SPatrick Williams                 get)([&app](const crow::Request& req,
12987e860f15SJohn Edward Broadbent                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
129922d268cbSEd Tanous                             const std::string& systemName,
13007e860f15SJohn Edward Broadbent                             const std::string& processorId) {
13013ba00073SCarson Labrado             if (!redfish::setUpRedfishRoute(app, req, asyncResp))
130245ca1b86SEd Tanous             {
130345ca1b86SEd Tanous                 return;
130445ca1b86SEd Tanous             }
130525b54dbaSEd Tanous             if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
13067f3e84a1SEd Tanous             {
13077f3e84a1SEd Tanous                 // Option currently returns no systems.  TBD
13087f3e84a1SEd Tanous                 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
13097f3e84a1SEd Tanous                                            systemName);
13107f3e84a1SEd Tanous                 return;
13117f3e84a1SEd Tanous             }
1312253f11b8SEd Tanous             if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
131322d268cbSEd Tanous             {
131422d268cbSEd Tanous                 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
131522d268cbSEd Tanous                                            systemName);
131622d268cbSEd Tanous                 return;
131722d268cbSEd Tanous             }
131822d268cbSEd Tanous 
131971a24ca4SNikhil Namjoshi             asyncResp->res.addHeader(
132071a24ca4SNikhil Namjoshi                 boost::beast::http::field::link,
132171a24ca4SNikhil Namjoshi                 "</redfish/v1/JsonSchemas/Processor/Processor.json>; rel=describedby");
13228d1b46d7Szhanghch05             asyncResp->res.jsonValue["@odata.type"] =
1323dfbf7de5SChris Cain                 "#Processor.v1_18_0.Processor";
1324bd79bce8SPatrick Williams             asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
1325bd79bce8SPatrick Williams                 "/redfish/v1/Systems/{}/Processors/{}",
1326253f11b8SEd Tanous                 BMCWEB_REDFISH_SYSTEM_URI_NAME, processorId);
1327ac6a4445SGunnar Mills 
13288a592810SEd Tanous             getProcessorObject(
13298a592810SEd Tanous                 asyncResp, processorId,
13308a592810SEd Tanous                 std::bind_front(getProcessorData, asyncResp, processorId));
13317e860f15SJohn Edward Broadbent         });
13323cde86f1SJonathan Doman 
133322d268cbSEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/<str>/")
1334ed398213SEd Tanous         .privileges(redfish::privileges::patchProcessor)
13357e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::patch)(
133645ca1b86SEd Tanous             [&app](const crow::Request& req,
13377e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
133822d268cbSEd Tanous                    const std::string& systemName,
13397e860f15SJohn Edward Broadbent                    const std::string& processorId) {
13403ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
134145ca1b86SEd Tanous                 {
134245ca1b86SEd Tanous                     return;
134345ca1b86SEd Tanous                 }
134425b54dbaSEd Tanous                 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
13457f3e84a1SEd Tanous                 {
13467f3e84a1SEd Tanous                     // Option currently returns no systems.  TBD
13477f3e84a1SEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
13487f3e84a1SEd Tanous                                                systemName);
13497f3e84a1SEd Tanous                     return;
13507f3e84a1SEd Tanous                 }
1351253f11b8SEd Tanous                 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
135222d268cbSEd Tanous                 {
135322d268cbSEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
135422d268cbSEd Tanous                                                systemName);
135522d268cbSEd Tanous                     return;
135622d268cbSEd Tanous                 }
135722d268cbSEd Tanous 
13583c569218SEd Tanous                 std::optional<std::string> appliedConfigUri;
1359bd79bce8SPatrick Williams                 if (!json_util::readJsonPatch(
1360afc474aeSMyung Bae                         req, asyncResp->res, //
1361afc474aeSMyung Bae                         "AppliedOperatingConfig/@odata.id", appliedConfigUri //
1362afc474aeSMyung Bae                         ))
13633cde86f1SJonathan Doman                 {
13643cde86f1SJonathan Doman                     return;
13653cde86f1SJonathan Doman                 }
13663cde86f1SJonathan Doman 
13673c569218SEd Tanous                 if (appliedConfigUri)
13683cde86f1SJonathan Doman                 {
13697e860f15SJohn Edward Broadbent                     // Check for 404 and find matching D-Bus object, then run
13707e860f15SJohn Edward Broadbent                     // property patch handlers if that all succeeds.
1371bd79bce8SPatrick Williams                     getProcessorObject(
13727e860f15SJohn Edward Broadbent                         asyncResp, processorId,
1373bd79bce8SPatrick Williams                         std::bind_front(patchAppliedOperatingConfig, asyncResp,
1374bd79bce8SPatrick Williams                                         processorId, *appliedConfigUri));
13753cde86f1SJonathan Doman                 }
13767e860f15SJohn Edward Broadbent             });
13773cde86f1SJonathan Doman }
1378ac6a4445SGunnar Mills 
1379ac6a4445SGunnar Mills } // namespace redfish
1380