xref: /openbmc/bmcweb/features/redfish/lib/processor.hpp (revision afc474aef028555fc0a6deb425bdad86f0a34db6)
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");
651e1e598dSJonathan Doman     sdbusplus::asio::getProperty<std::string>(
661e1e598dSJonathan Doman         *crow::connections::systemBus, service, objPath,
671e1e598dSJonathan Doman         "xyz.openbmc_project.Common.UUID", "UUID",
68ac106bf6SEd Tanous         [objPath, asyncResp{std::move(asyncResp)}](
69ac106bf6SEd Tanous             const boost::system::error_code& ec, const std::string& property) {
7071b82f26SSharad Yadav             if (ec)
7171b82f26SSharad Yadav             {
7262598e31SEd Tanous                 BMCWEB_LOG_DEBUG("DBUS response error");
73ac106bf6SEd Tanous                 messages::internalError(asyncResp->res);
7471b82f26SSharad Yadav                 return;
7571b82f26SSharad Yadav             }
76ac106bf6SEd Tanous             asyncResp->res.jsonValue["UUID"] = property;
771e1e598dSJonathan Doman         });
7871b82f26SSharad Yadav }
7971b82f26SSharad Yadav 
80711ac7a9SEd Tanous inline void getCpuDataByInterface(
81ac106bf6SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
8280f79a40SMichael Shen     const dbus::utility::DBusInterfacesMap& cpuInterfacesProperties)
83ac6a4445SGunnar Mills {
8462598e31SEd Tanous     BMCWEB_LOG_DEBUG("Get CPU resources by interface.");
85ac6a4445SGunnar Mills 
86a1649ec6SChicago Duan     // Set the default value of state
87539d8c6bSEd Tanous     asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled;
88539d8c6bSEd Tanous     asyncResp->res.jsonValue["Status"]["Health"] = resource::Health::OK;
89ac6a4445SGunnar Mills 
90ac6a4445SGunnar Mills     for (const auto& interface : cpuInterfacesProperties)
91ac6a4445SGunnar Mills     {
92ac6a4445SGunnar Mills         for (const auto& property : interface.second)
93ac6a4445SGunnar Mills         {
94a1649ec6SChicago Duan             if (property.first == "Present")
95ac6a4445SGunnar Mills             {
96a1649ec6SChicago Duan                 const bool* cpuPresent = std::get_if<bool>(&property.second);
97a1649ec6SChicago Duan                 if (cpuPresent == nullptr)
98ac6a4445SGunnar Mills                 {
99ac6a4445SGunnar Mills                     // Important property not in desired type
100ac106bf6SEd Tanous                     messages::internalError(asyncResp->res);
101ac6a4445SGunnar Mills                     return;
102ac6a4445SGunnar Mills                 }
103e05aec50SEd Tanous                 if (!*cpuPresent)
104ac6a4445SGunnar Mills                 {
105a1649ec6SChicago Duan                     // Slot is not populated
106539d8c6bSEd Tanous                     asyncResp->res.jsonValue["Status"]["State"] =
107539d8c6bSEd Tanous                         resource::State::Absent;
108a1649ec6SChicago Duan                 }
109a1649ec6SChicago Duan             }
110a1649ec6SChicago Duan             else if (property.first == "Functional")
111a1649ec6SChicago Duan             {
112a1649ec6SChicago Duan                 const bool* cpuFunctional = std::get_if<bool>(&property.second);
113a1649ec6SChicago Duan                 if (cpuFunctional == nullptr)
114a1649ec6SChicago Duan                 {
115ac106bf6SEd Tanous                     messages::internalError(asyncResp->res);
116ac6a4445SGunnar Mills                     return;
117ac6a4445SGunnar Mills                 }
118e05aec50SEd Tanous                 if (!*cpuFunctional)
119a1649ec6SChicago Duan                 {
120539d8c6bSEd Tanous                     asyncResp->res.jsonValue["Status"]["Health"] =
121539d8c6bSEd Tanous                         resource::Health::Critical;
122a1649ec6SChicago Duan                 }
123a1649ec6SChicago Duan             }
124a1649ec6SChicago Duan             else if (property.first == "CoreCount")
125a1649ec6SChicago Duan             {
126a1649ec6SChicago Duan                 const uint16_t* coresCount =
127a1649ec6SChicago Duan                     std::get_if<uint16_t>(&property.second);
128a1649ec6SChicago Duan                 if (coresCount == nullptr)
129a1649ec6SChicago Duan                 {
130ac106bf6SEd Tanous                     messages::internalError(asyncResp->res);
131a1649ec6SChicago Duan                     return;
132a1649ec6SChicago Duan                 }
133ac106bf6SEd Tanous                 asyncResp->res.jsonValue["TotalCores"] = *coresCount;
134ac6a4445SGunnar Mills             }
135dc3fa667SJonathan Doman             else if (property.first == "MaxSpeedInMhz")
136dc3fa667SJonathan Doman             {
137dc3fa667SJonathan Doman                 const uint32_t* value = std::get_if<uint32_t>(&property.second);
138dc3fa667SJonathan Doman                 if (value != nullptr)
139dc3fa667SJonathan Doman                 {
140ac106bf6SEd Tanous                     asyncResp->res.jsonValue["MaxSpeedMHz"] = *value;
141dc3fa667SJonathan Doman                 }
142dc3fa667SJonathan Doman             }
143ac6a4445SGunnar Mills             else if (property.first == "Socket")
144ac6a4445SGunnar Mills             {
145ac6a4445SGunnar Mills                 const std::string* value =
146ac6a4445SGunnar Mills                     std::get_if<std::string>(&property.second);
147ac6a4445SGunnar Mills                 if (value != nullptr)
148ac6a4445SGunnar Mills                 {
149ac106bf6SEd Tanous                     asyncResp->res.jsonValue["Socket"] = *value;
150ac6a4445SGunnar Mills                 }
151ac6a4445SGunnar Mills             }
152ac6a4445SGunnar Mills             else if (property.first == "ThreadCount")
153ac6a4445SGunnar Mills             {
154dc3fa667SJonathan Doman                 const uint16_t* value = std::get_if<uint16_t>(&property.second);
155ac6a4445SGunnar Mills                 if (value != nullptr)
156ac6a4445SGunnar Mills                 {
157ac106bf6SEd Tanous                     asyncResp->res.jsonValue["TotalThreads"] = *value;
158ac6a4445SGunnar Mills                 }
159ac6a4445SGunnar Mills             }
1601930fbd4SBrandon Kim             else if (property.first == "EffectiveFamily")
161ac6a4445SGunnar Mills             {
1621930fbd4SBrandon Kim                 const uint16_t* value = std::get_if<uint16_t>(&property.second);
1636169de2cSBrad Bishop                 if (value != nullptr && *value != 2)
164ac6a4445SGunnar Mills                 {
165ac106bf6SEd Tanous                     asyncResp->res.jsonValue["ProcessorId"]["EffectiveFamily"] =
166866e4862SEd Tanous                         "0x" + intToHexString(*value, 4);
167ac6a4445SGunnar Mills                 }
168ac6a4445SGunnar Mills             }
1691930fbd4SBrandon Kim             else if (property.first == "EffectiveModel")
1701930fbd4SBrandon Kim             {
1711930fbd4SBrandon Kim                 const uint16_t* value = std::get_if<uint16_t>(&property.second);
1721930fbd4SBrandon Kim                 if (value == nullptr)
1731930fbd4SBrandon Kim                 {
174ac106bf6SEd Tanous                     messages::internalError(asyncResp->res);
1751930fbd4SBrandon Kim                     return;
1761930fbd4SBrandon Kim                 }
1776169de2cSBrad Bishop                 if (*value != 0)
1786169de2cSBrad Bishop                 {
179ac106bf6SEd Tanous                     asyncResp->res.jsonValue["ProcessorId"]["EffectiveModel"] =
180866e4862SEd Tanous                         "0x" + intToHexString(*value, 4);
1811930fbd4SBrandon Kim                 }
1826169de2cSBrad Bishop             }
183ac6a4445SGunnar Mills             else if (property.first == "Id")
184ac6a4445SGunnar Mills             {
185ac6a4445SGunnar Mills                 const uint64_t* value = std::get_if<uint64_t>(&property.second);
186ac6a4445SGunnar Mills                 if (value != nullptr && *value != 0)
187ac6a4445SGunnar Mills                 {
188ac106bf6SEd Tanous                     asyncResp->res
189ac6a4445SGunnar Mills                         .jsonValue["ProcessorId"]["IdentificationRegisters"] =
190866e4862SEd Tanous                         "0x" + intToHexString(*value, 16);
191ac6a4445SGunnar Mills                 }
192ac6a4445SGunnar Mills             }
1931930fbd4SBrandon Kim             else if (property.first == "Microcode")
1941930fbd4SBrandon Kim             {
1951930fbd4SBrandon Kim                 const uint32_t* value = std::get_if<uint32_t>(&property.second);
1961930fbd4SBrandon Kim                 if (value == nullptr)
1971930fbd4SBrandon Kim                 {
198ac106bf6SEd Tanous                     messages::internalError(asyncResp->res);
1991930fbd4SBrandon Kim                     return;
2001930fbd4SBrandon Kim                 }
2016169de2cSBrad Bishop                 if (*value != 0)
2026169de2cSBrad Bishop                 {
203ac106bf6SEd Tanous                     asyncResp->res.jsonValue["ProcessorId"]["MicrocodeInfo"] =
204866e4862SEd Tanous                         "0x" + intToHexString(*value, 8);
2051930fbd4SBrandon Kim                 }
2066169de2cSBrad Bishop             }
2071930fbd4SBrandon Kim             else if (property.first == "Step")
2081930fbd4SBrandon Kim             {
2091930fbd4SBrandon Kim                 const uint16_t* value = std::get_if<uint16_t>(&property.second);
2101930fbd4SBrandon Kim                 if (value == nullptr)
2111930fbd4SBrandon Kim                 {
212ac106bf6SEd Tanous                     messages::internalError(asyncResp->res);
2131930fbd4SBrandon Kim                     return;
2141930fbd4SBrandon Kim                 }
215b9d679d1SMichael Shen                 if (*value != std::numeric_limits<uint16_t>::max())
2166169de2cSBrad Bishop                 {
217ac106bf6SEd Tanous                     asyncResp->res.jsonValue["ProcessorId"]["Step"] =
218866e4862SEd Tanous                         "0x" + intToHexString(*value, 4);
2191930fbd4SBrandon Kim                 }
220ac6a4445SGunnar Mills             }
221ac6a4445SGunnar Mills         }
222ac6a4445SGunnar Mills     }
2236169de2cSBrad Bishop }
224ac6a4445SGunnar Mills 
225bd79bce8SPatrick Williams inline void getCpuDataByService(
226bd79bce8SPatrick Williams     std::shared_ptr<bmcweb::AsyncResp> asyncResp, const std::string& cpuId,
227bd79bce8SPatrick Williams     const std::string& service, const std::string& objPath)
228ac6a4445SGunnar Mills {
22962598e31SEd Tanous     BMCWEB_LOG_DEBUG("Get available system cpu resources by service.");
230ac6a4445SGunnar Mills 
2315eb468daSGeorge Liu     sdbusplus::message::object_path path("/xyz/openbmc_project/inventory");
2325eb468daSGeorge Liu     dbus::utility::getManagedObjects(
2335eb468daSGeorge Liu         service, path,
234ac106bf6SEd Tanous         [cpuId, service, objPath, asyncResp{std::move(asyncResp)}](
2355e7e2dc5SEd Tanous             const boost::system::error_code& ec,
236ac6a4445SGunnar Mills             const dbus::utility::ManagedObjectType& dbusData) {
237ac6a4445SGunnar Mills             if (ec)
238ac6a4445SGunnar Mills             {
23962598e31SEd Tanous                 BMCWEB_LOG_DEBUG("DBUS response error");
240ac106bf6SEd Tanous                 messages::internalError(asyncResp->res);
241ac6a4445SGunnar Mills                 return;
242ac6a4445SGunnar Mills             }
243ac106bf6SEd Tanous             asyncResp->res.jsonValue["Id"] = cpuId;
244ac106bf6SEd Tanous             asyncResp->res.jsonValue["Name"] = "Processor";
245539d8c6bSEd Tanous             asyncResp->res.jsonValue["ProcessorType"] =
246539d8c6bSEd Tanous                 processor::ProcessorType::CPU;
247ac6a4445SGunnar Mills 
248ac6a4445SGunnar Mills             bool slotPresent = false;
249ac6a4445SGunnar Mills             std::string corePath = objPath + "/core";
250ac6a4445SGunnar Mills             size_t totalCores = 0;
251ac6a4445SGunnar Mills             for (const auto& object : dbusData)
252ac6a4445SGunnar Mills             {
253ac6a4445SGunnar Mills                 if (object.first.str == objPath)
254ac6a4445SGunnar Mills                 {
255ac106bf6SEd Tanous                     getCpuDataByInterface(asyncResp, object.second);
256ac6a4445SGunnar Mills                 }
25711ba3979SEd Tanous                 else if (object.first.str.starts_with(corePath))
258ac6a4445SGunnar Mills                 {
259ac6a4445SGunnar Mills                     for (const auto& interface : object.second)
260ac6a4445SGunnar Mills                     {
261bd79bce8SPatrick Williams                         if (interface.first ==
262bd79bce8SPatrick Williams                             "xyz.openbmc_project.Inventory.Item")
263ac6a4445SGunnar Mills                         {
264ac6a4445SGunnar Mills                             for (const auto& property : interface.second)
265ac6a4445SGunnar Mills                             {
266ac6a4445SGunnar Mills                                 if (property.first == "Present")
267ac6a4445SGunnar Mills                                 {
268ac6a4445SGunnar Mills                                     const bool* present =
269ac6a4445SGunnar Mills                                         std::get_if<bool>(&property.second);
270ac6a4445SGunnar Mills                                     if (present != nullptr)
271ac6a4445SGunnar Mills                                     {
272e05aec50SEd Tanous                                         if (*present)
273ac6a4445SGunnar Mills                                         {
274ac6a4445SGunnar Mills                                             slotPresent = true;
275ac6a4445SGunnar Mills                                             totalCores++;
276ac6a4445SGunnar Mills                                         }
277ac6a4445SGunnar Mills                                     }
278ac6a4445SGunnar Mills                                 }
279ac6a4445SGunnar Mills                             }
280ac6a4445SGunnar Mills                         }
281ac6a4445SGunnar Mills                     }
282ac6a4445SGunnar Mills                 }
283ac6a4445SGunnar Mills             }
284ac6a4445SGunnar Mills             // In getCpuDataByInterface(), state and health are set
285ac6a4445SGunnar Mills             // based on the present and functional status. If core
286ac6a4445SGunnar Mills             // count is zero, then it has a higher precedence.
287ac6a4445SGunnar Mills             if (slotPresent)
288ac6a4445SGunnar Mills             {
289ac106bf6SEd Tanous                 asyncResp->res.jsonValue["TotalCores"] = totalCores;
290ac6a4445SGunnar Mills             }
291ac6a4445SGunnar Mills             return;
2925eb468daSGeorge Liu         });
293ac6a4445SGunnar Mills }
294ac6a4445SGunnar Mills 
295dfbf7de5SChris Cain /**
296dfbf7de5SChris Cain  * @brief Translates throttle cause DBUS property to redfish.
297dfbf7de5SChris Cain  *
298dfbf7de5SChris Cain  * @param[in] dbusSource    The throttle cause from DBUS
299dfbf7de5SChris Cain  *
300dfbf7de5SChris Cain  * @return Returns as a string, the throttle cause in Redfish terms. If
301dfbf7de5SChris Cain  * translation cannot be done, returns "Unknown" throttle reason.
302dfbf7de5SChris Cain  */
303dfbf7de5SChris Cain inline processor::ThrottleCause
304dfbf7de5SChris Cain     dbusToRfThrottleCause(const std::string& dbusSource)
305dfbf7de5SChris Cain {
306dfbf7de5SChris Cain     if (dbusSource ==
307dfbf7de5SChris Cain         "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.ClockLimit")
308dfbf7de5SChris Cain     {
309dfbf7de5SChris Cain         return processor::ThrottleCause::ClockLimit;
310dfbf7de5SChris Cain     }
311dfbf7de5SChris Cain     if (dbusSource ==
312dfbf7de5SChris Cain         "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.ManagementDetectedFault")
313dfbf7de5SChris Cain     {
314dfbf7de5SChris Cain         return processor::ThrottleCause::ManagementDetectedFault;
315dfbf7de5SChris Cain     }
316dfbf7de5SChris Cain     if (dbusSource ==
317dfbf7de5SChris Cain         "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.PowerLimit")
318dfbf7de5SChris Cain     {
319dfbf7de5SChris Cain         return processor::ThrottleCause::PowerLimit;
320dfbf7de5SChris Cain     }
321dfbf7de5SChris Cain     if (dbusSource ==
322dfbf7de5SChris Cain         "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.ThermalLimit")
323dfbf7de5SChris Cain     {
324dfbf7de5SChris Cain         return processor::ThrottleCause::ThermalLimit;
325dfbf7de5SChris Cain     }
326dfbf7de5SChris Cain     if (dbusSource ==
327dfbf7de5SChris Cain         "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.Unknown")
328dfbf7de5SChris Cain     {
329dfbf7de5SChris Cain         return processor::ThrottleCause::Unknown;
330dfbf7de5SChris Cain     }
331dfbf7de5SChris Cain     return processor::ThrottleCause::Invalid;
332dfbf7de5SChris Cain }
333dfbf7de5SChris Cain 
334dfbf7de5SChris Cain inline void
335ac106bf6SEd Tanous     readThrottleProperties(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
336dfbf7de5SChris Cain                            const boost::system::error_code& ec,
337dfbf7de5SChris Cain                            const dbus::utility::DBusPropertiesMap& properties)
338dfbf7de5SChris Cain {
339dfbf7de5SChris Cain     if (ec)
340dfbf7de5SChris Cain     {
34162598e31SEd Tanous         BMCWEB_LOG_ERROR("Processor Throttle getAllProperties error {}", ec);
342ac106bf6SEd Tanous         messages::internalError(asyncResp->res);
343dfbf7de5SChris Cain         return;
344dfbf7de5SChris Cain     }
345dfbf7de5SChris Cain 
346dfbf7de5SChris Cain     const bool* status = nullptr;
347dfbf7de5SChris Cain     const std::vector<std::string>* causes = nullptr;
348dfbf7de5SChris Cain 
349dfbf7de5SChris Cain     if (!sdbusplus::unpackPropertiesNoThrow(dbus_utils::UnpackErrorPrinter(),
350dfbf7de5SChris Cain                                             properties, "Throttled", status,
351dfbf7de5SChris Cain                                             "ThrottleCauses", causes))
352dfbf7de5SChris Cain     {
353ac106bf6SEd Tanous         messages::internalError(asyncResp->res);
354dfbf7de5SChris Cain         return;
355dfbf7de5SChris Cain     }
356dfbf7de5SChris Cain 
357ac106bf6SEd Tanous     asyncResp->res.jsonValue["Throttled"] = *status;
358dfbf7de5SChris Cain     nlohmann::json::array_t rCauses;
359dfbf7de5SChris Cain     for (const std::string& cause : *causes)
360dfbf7de5SChris Cain     {
361dfbf7de5SChris Cain         processor::ThrottleCause rfCause = dbusToRfThrottleCause(cause);
362dfbf7de5SChris Cain         if (rfCause == processor::ThrottleCause::Invalid)
363dfbf7de5SChris Cain         {
364ac106bf6SEd Tanous             messages::internalError(asyncResp->res);
365dfbf7de5SChris Cain             return;
366dfbf7de5SChris Cain         }
367dfbf7de5SChris Cain 
368dfbf7de5SChris Cain         rCauses.emplace_back(rfCause);
369dfbf7de5SChris Cain     }
370ac106bf6SEd Tanous     asyncResp->res.jsonValue["ThrottleCauses"] = std::move(rCauses);
371dfbf7de5SChris Cain }
372dfbf7de5SChris Cain 
373bd79bce8SPatrick Williams inline void getThrottleProperties(
374bd79bce8SPatrick Williams     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
375bd79bce8SPatrick Williams     const std::string& service, const std::string& objectPath)
376dfbf7de5SChris Cain {
37762598e31SEd Tanous     BMCWEB_LOG_DEBUG("Get processor throttle resources");
378dfbf7de5SChris Cain 
379dfbf7de5SChris Cain     sdbusplus::asio::getAllProperties(
380dfbf7de5SChris Cain         *crow::connections::systemBus, service, objectPath,
381dfbf7de5SChris Cain         "xyz.openbmc_project.Control.Power.Throttle",
382ac106bf6SEd Tanous         [asyncResp](const boost::system::error_code& ec,
383dfbf7de5SChris Cain                     const dbus::utility::DBusPropertiesMap& properties) {
384ac106bf6SEd Tanous             readThrottleProperties(asyncResp, ec, properties);
385dfbf7de5SChris Cain         });
386dfbf7de5SChris Cain }
387dfbf7de5SChris Cain 
388ac106bf6SEd Tanous inline void getCpuAssetData(std::shared_ptr<bmcweb::AsyncResp> asyncResp,
389ac6a4445SGunnar Mills                             const std::string& service,
390ac6a4445SGunnar Mills                             const std::string& objPath)
391ac6a4445SGunnar Mills {
39262598e31SEd Tanous     BMCWEB_LOG_DEBUG("Get Cpu Asset Data");
393351053f2SKrzysztof Grobelny     sdbusplus::asio::getAllProperties(
394351053f2SKrzysztof Grobelny         *crow::connections::systemBus, service, objPath,
395351053f2SKrzysztof Grobelny         "xyz.openbmc_project.Inventory.Decorator.Asset",
396ac106bf6SEd Tanous         [objPath, asyncResp{std::move(asyncResp)}](
3975e7e2dc5SEd Tanous             const boost::system::error_code& ec,
398351053f2SKrzysztof Grobelny             const dbus::utility::DBusPropertiesMap& properties) {
399ac6a4445SGunnar Mills             if (ec)
400ac6a4445SGunnar Mills             {
40162598e31SEd Tanous                 BMCWEB_LOG_DEBUG("DBUS response error");
402ac106bf6SEd Tanous                 messages::internalError(asyncResp->res);
403ac6a4445SGunnar Mills                 return;
404ac6a4445SGunnar Mills             }
405ac6a4445SGunnar Mills 
406351053f2SKrzysztof Grobelny             const std::string* serialNumber = nullptr;
407351053f2SKrzysztof Grobelny             const std::string* model = nullptr;
408351053f2SKrzysztof Grobelny             const std::string* manufacturer = nullptr;
409351053f2SKrzysztof Grobelny             const std::string* partNumber = nullptr;
410351053f2SKrzysztof Grobelny             const std::string* sparePartNumber = nullptr;
411351053f2SKrzysztof Grobelny 
412351053f2SKrzysztof Grobelny             const bool success = sdbusplus::unpackPropertiesNoThrow(
413351053f2SKrzysztof Grobelny                 dbus_utils::UnpackErrorPrinter(), properties, "SerialNumber",
414351053f2SKrzysztof Grobelny                 serialNumber, "Model", model, "Manufacturer", manufacturer,
415351053f2SKrzysztof Grobelny                 "PartNumber", partNumber, "SparePartNumber", sparePartNumber);
416351053f2SKrzysztof Grobelny 
417351053f2SKrzysztof Grobelny             if (!success)
418ac6a4445SGunnar Mills             {
419ac106bf6SEd Tanous                 messages::internalError(asyncResp->res);
420351053f2SKrzysztof Grobelny                 return;
421ac6a4445SGunnar Mills             }
422351053f2SKrzysztof Grobelny 
423351053f2SKrzysztof Grobelny             if (serialNumber != nullptr && !serialNumber->empty())
424ac6a4445SGunnar Mills             {
425ac106bf6SEd Tanous                 asyncResp->res.jsonValue["SerialNumber"] = *serialNumber;
426351053f2SKrzysztof Grobelny             }
427351053f2SKrzysztof Grobelny 
428351053f2SKrzysztof Grobelny             if ((model != nullptr) && !model->empty())
429ac6a4445SGunnar Mills             {
430ac106bf6SEd Tanous                 asyncResp->res.jsonValue["Model"] = *model;
431ac6a4445SGunnar Mills             }
432ac6a4445SGunnar Mills 
433351053f2SKrzysztof Grobelny             if (manufacturer != nullptr)
434ac6a4445SGunnar Mills             {
435ac106bf6SEd Tanous                 asyncResp->res.jsonValue["Manufacturer"] = *manufacturer;
436ac6a4445SGunnar Mills 
437ac6a4445SGunnar Mills                 // Otherwise would be unexpected.
438351053f2SKrzysztof Grobelny                 if (manufacturer->find("Intel") != std::string::npos)
439ac6a4445SGunnar Mills                 {
440ac106bf6SEd Tanous                     asyncResp->res.jsonValue["ProcessorArchitecture"] = "x86";
441ac106bf6SEd Tanous                     asyncResp->res.jsonValue["InstructionSet"] = "x86-64";
442ac6a4445SGunnar Mills                 }
443351053f2SKrzysztof Grobelny                 else if (manufacturer->find("IBM") != std::string::npos)
444ac6a4445SGunnar Mills                 {
445ac106bf6SEd Tanous                     asyncResp->res.jsonValue["ProcessorArchitecture"] = "Power";
446ac106bf6SEd Tanous                     asyncResp->res.jsonValue["InstructionSet"] = "PowerISA";
447ac6a4445SGunnar Mills                 }
448ac6a4445SGunnar Mills             }
449cba4f448SSunnySrivastava1984 
450351053f2SKrzysztof Grobelny             if (partNumber != nullptr)
451cba4f448SSunnySrivastava1984             {
452ac106bf6SEd Tanous                 asyncResp->res.jsonValue["PartNumber"] = *partNumber;
453cba4f448SSunnySrivastava1984             }
454cba4f448SSunnySrivastava1984 
4556169de2cSBrad Bishop             if (sparePartNumber != nullptr && !sparePartNumber->empty())
456cba4f448SSunnySrivastava1984             {
457ac106bf6SEd Tanous                 asyncResp->res.jsonValue["SparePartNumber"] = *sparePartNumber;
458cba4f448SSunnySrivastava1984             }
459351053f2SKrzysztof Grobelny         });
460ac6a4445SGunnar Mills }
461ac6a4445SGunnar Mills 
462ac106bf6SEd Tanous inline void getCpuRevisionData(std::shared_ptr<bmcweb::AsyncResp> asyncResp,
463ac6a4445SGunnar Mills                                const std::string& service,
464ac6a4445SGunnar Mills                                const std::string& objPath)
465ac6a4445SGunnar Mills {
46662598e31SEd Tanous     BMCWEB_LOG_DEBUG("Get Cpu Revision Data");
467351053f2SKrzysztof Grobelny     sdbusplus::asio::getAllProperties(
468351053f2SKrzysztof Grobelny         *crow::connections::systemBus, service, objPath,
469351053f2SKrzysztof Grobelny         "xyz.openbmc_project.Inventory.Decorator.Revision",
470ac106bf6SEd Tanous         [objPath, asyncResp{std::move(asyncResp)}](
4715e7e2dc5SEd Tanous             const boost::system::error_code& ec,
472351053f2SKrzysztof Grobelny             const dbus::utility::DBusPropertiesMap& properties) {
473ac6a4445SGunnar Mills             if (ec)
474ac6a4445SGunnar Mills             {
47562598e31SEd Tanous                 BMCWEB_LOG_DEBUG("DBUS response error");
476ac106bf6SEd Tanous                 messages::internalError(asyncResp->res);
477ac6a4445SGunnar Mills                 return;
478ac6a4445SGunnar Mills             }
479ac6a4445SGunnar Mills 
480351053f2SKrzysztof Grobelny             const std::string* version = nullptr;
481351053f2SKrzysztof Grobelny 
482351053f2SKrzysztof Grobelny             const bool success = sdbusplus::unpackPropertiesNoThrow(
483bd79bce8SPatrick Williams                 dbus_utils::UnpackErrorPrinter(), properties, "Version",
484bd79bce8SPatrick Williams                 version);
485351053f2SKrzysztof Grobelny 
486351053f2SKrzysztof Grobelny             if (!success)
487ac6a4445SGunnar Mills             {
488ac106bf6SEd Tanous                 messages::internalError(asyncResp->res);
489351053f2SKrzysztof Grobelny                 return;
490351053f2SKrzysztof Grobelny             }
491351053f2SKrzysztof Grobelny 
492351053f2SKrzysztof Grobelny             if (version != nullptr)
493ac6a4445SGunnar Mills             {
494ac106bf6SEd Tanous                 asyncResp->res.jsonValue["Version"] = *version;
495ac6a4445SGunnar Mills             }
496351053f2SKrzysztof Grobelny         });
497ac6a4445SGunnar Mills }
498ac6a4445SGunnar Mills 
4998d1b46d7Szhanghch05 inline void getAcceleratorDataByService(
500ac106bf6SEd Tanous     std::shared_ptr<bmcweb::AsyncResp> asyncResp, const std::string& acclrtrId,
5018d1b46d7Szhanghch05     const std::string& service, const std::string& objPath)
502ac6a4445SGunnar Mills {
50362598e31SEd Tanous     BMCWEB_LOG_DEBUG("Get available system Accelerator resources by service.");
504351053f2SKrzysztof Grobelny     sdbusplus::asio::getAllProperties(
505351053f2SKrzysztof Grobelny         *crow::connections::systemBus, service, objPath, "",
506ac106bf6SEd Tanous         [acclrtrId, asyncResp{std::move(asyncResp)}](
5075e7e2dc5SEd Tanous             const boost::system::error_code& ec,
508351053f2SKrzysztof Grobelny             const dbus::utility::DBusPropertiesMap& properties) {
509ac6a4445SGunnar Mills             if (ec)
510ac6a4445SGunnar Mills             {
51162598e31SEd Tanous                 BMCWEB_LOG_DEBUG("DBUS response error");
512ac106bf6SEd Tanous                 messages::internalError(asyncResp->res);
513ac6a4445SGunnar Mills                 return;
514ac6a4445SGunnar Mills             }
515ac6a4445SGunnar Mills 
516351053f2SKrzysztof Grobelny             const bool* functional = nullptr;
517351053f2SKrzysztof Grobelny             const bool* present = nullptr;
518351053f2SKrzysztof Grobelny 
519351053f2SKrzysztof Grobelny             const bool success = sdbusplus::unpackPropertiesNoThrow(
520351053f2SKrzysztof Grobelny                 dbus_utils::UnpackErrorPrinter(), properties, "Functional",
521351053f2SKrzysztof Grobelny                 functional, "Present", present);
522351053f2SKrzysztof Grobelny 
523351053f2SKrzysztof Grobelny             if (!success)
524ac6a4445SGunnar Mills             {
525ac106bf6SEd Tanous                 messages::internalError(asyncResp->res);
526351053f2SKrzysztof Grobelny                 return;
527ac6a4445SGunnar Mills             }
528ac6a4445SGunnar Mills 
529ac6a4445SGunnar Mills             std::string state = "Enabled";
530ac6a4445SGunnar Mills             std::string health = "OK";
531ac6a4445SGunnar Mills 
532351053f2SKrzysztof Grobelny             if (present != nullptr && !*present)
533ac6a4445SGunnar Mills             {
534ac6a4445SGunnar Mills                 state = "Absent";
535ac6a4445SGunnar Mills             }
536ac6a4445SGunnar Mills 
537351053f2SKrzysztof Grobelny             if (functional != nullptr && !*functional)
538ac6a4445SGunnar Mills             {
539ac6a4445SGunnar Mills                 if (state == "Enabled")
540ac6a4445SGunnar Mills                 {
541ac6a4445SGunnar Mills                     health = "Critical";
542ac6a4445SGunnar Mills                 }
543ac6a4445SGunnar Mills             }
544ac6a4445SGunnar Mills 
545ac106bf6SEd Tanous             asyncResp->res.jsonValue["Id"] = acclrtrId;
546ac106bf6SEd Tanous             asyncResp->res.jsonValue["Name"] = "Processor";
547ac106bf6SEd Tanous             asyncResp->res.jsonValue["Status"]["State"] = state;
548ac106bf6SEd Tanous             asyncResp->res.jsonValue["Status"]["Health"] = health;
549539d8c6bSEd Tanous             asyncResp->res.jsonValue["ProcessorType"] =
550539d8c6bSEd Tanous                 processor::ProcessorType::Accelerator;
551351053f2SKrzysztof Grobelny         });
552ac6a4445SGunnar Mills }
553ac6a4445SGunnar Mills 
554dba0c291SJonathan Doman // OperatingConfig D-Bus Types
555dba0c291SJonathan Doman using TurboProfileProperty = std::vector<std::tuple<uint32_t, size_t>>;
556dba0c291SJonathan Doman using BaseSpeedPrioritySettingsProperty =
557dba0c291SJonathan Doman     std::vector<std::tuple<uint32_t, std::vector<uint32_t>>>;
558dba0c291SJonathan Doman // uint32_t and size_t may or may not be the same type, requiring a dedup'd
559dba0c291SJonathan Doman // variant
560dba0c291SJonathan Doman 
561dba0c291SJonathan Doman /**
562dba0c291SJonathan Doman  * Fill out the HighSpeedCoreIDs in a Processor resource from the given
563dba0c291SJonathan Doman  * OperatingConfig D-Bus property.
564dba0c291SJonathan Doman  *
565ac106bf6SEd Tanous  * @param[in,out]   asyncResp           Async HTTP response.
566dba0c291SJonathan Doman  * @param[in]       baseSpeedSettings   Full list of base speed priority groups,
567dba0c291SJonathan Doman  *                                      to use to determine the list of high
568dba0c291SJonathan Doman  *                                      speed cores.
569dba0c291SJonathan Doman  */
570dba0c291SJonathan Doman inline void highSpeedCoreIdsHandler(
571ac106bf6SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
572dba0c291SJonathan Doman     const BaseSpeedPrioritySettingsProperty& baseSpeedSettings)
573dba0c291SJonathan Doman {
574dba0c291SJonathan Doman     // The D-Bus property does not indicate which bucket is the "high
575dba0c291SJonathan Doman     // priority" group, so let's discern that by looking for the one with
576dba0c291SJonathan Doman     // highest base frequency.
577dba0c291SJonathan Doman     auto highPriorityGroup = baseSpeedSettings.cend();
578dba0c291SJonathan Doman     uint32_t highestBaseSpeed = 0;
579dba0c291SJonathan Doman     for (auto it = baseSpeedSettings.cbegin(); it != baseSpeedSettings.cend();
580dba0c291SJonathan Doman          ++it)
581dba0c291SJonathan Doman     {
582dba0c291SJonathan Doman         const uint32_t baseFreq = std::get<uint32_t>(*it);
583dba0c291SJonathan Doman         if (baseFreq > highestBaseSpeed)
584dba0c291SJonathan Doman         {
585dba0c291SJonathan Doman             highestBaseSpeed = baseFreq;
586dba0c291SJonathan Doman             highPriorityGroup = it;
587dba0c291SJonathan Doman         }
588dba0c291SJonathan Doman     }
589dba0c291SJonathan Doman 
590ac106bf6SEd Tanous     nlohmann::json& jsonCoreIds = asyncResp->res.jsonValue["HighSpeedCoreIDs"];
591dba0c291SJonathan Doman     jsonCoreIds = nlohmann::json::array();
592dba0c291SJonathan Doman 
593dba0c291SJonathan Doman     // There may not be any entries in the D-Bus property, so only populate
594dba0c291SJonathan Doman     // if there was actually something there.
595dba0c291SJonathan Doman     if (highPriorityGroup != baseSpeedSettings.cend())
596dba0c291SJonathan Doman     {
597dba0c291SJonathan Doman         jsonCoreIds = std::get<std::vector<uint32_t>>(*highPriorityGroup);
598dba0c291SJonathan Doman     }
599dba0c291SJonathan Doman }
600dba0c291SJonathan Doman 
601dba0c291SJonathan Doman /**
602dba0c291SJonathan Doman  * Fill out OperatingConfig related items in a Processor resource by requesting
603dba0c291SJonathan Doman  * data from the given D-Bus object.
604dba0c291SJonathan Doman  *
605ac106bf6SEd Tanous  * @param[in,out]   asyncResp       Async HTTP response.
606dba0c291SJonathan Doman  * @param[in]       cpuId       CPU D-Bus name.
607dba0c291SJonathan Doman  * @param[in]       service     D-Bus service to query.
608dba0c291SJonathan Doman  * @param[in]       objPath     D-Bus object to query.
609dba0c291SJonathan Doman  */
610ac106bf6SEd Tanous inline void
611ac106bf6SEd Tanous     getCpuConfigData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
612ac106bf6SEd Tanous                      const std::string& cpuId, const std::string& service,
613dba0c291SJonathan Doman                      const std::string& objPath)
614dba0c291SJonathan Doman {
61562598e31SEd Tanous     BMCWEB_LOG_INFO("Getting CPU operating configs for {}", cpuId);
616dba0c291SJonathan Doman 
617dba0c291SJonathan Doman     // First, GetAll CurrentOperatingConfig properties on the object
618351053f2SKrzysztof Grobelny     sdbusplus::asio::getAllProperties(
619351053f2SKrzysztof Grobelny         *crow::connections::systemBus, service, objPath,
620351053f2SKrzysztof Grobelny         "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig",
621ac106bf6SEd Tanous         [asyncResp, cpuId,
6225e7e2dc5SEd Tanous          service](const boost::system::error_code& ec,
623351053f2SKrzysztof Grobelny                   const dbus::utility::DBusPropertiesMap& properties) {
624dba0c291SJonathan Doman             if (ec)
625dba0c291SJonathan Doman             {
62662598e31SEd Tanous                 BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec, ec.message());
627ac106bf6SEd Tanous                 messages::internalError(asyncResp->res);
628dba0c291SJonathan Doman                 return;
629dba0c291SJonathan Doman             }
630dba0c291SJonathan Doman 
631ac106bf6SEd Tanous             nlohmann::json& json = asyncResp->res.jsonValue;
632dba0c291SJonathan Doman 
633351053f2SKrzysztof Grobelny             const sdbusplus::message::object_path* appliedConfig = nullptr;
634351053f2SKrzysztof Grobelny             const bool* baseSpeedPriorityEnabled = nullptr;
635351053f2SKrzysztof Grobelny 
636351053f2SKrzysztof Grobelny             const bool success = sdbusplus::unpackPropertiesNoThrow(
637351053f2SKrzysztof Grobelny                 dbus_utils::UnpackErrorPrinter(), properties, "AppliedConfig",
638351053f2SKrzysztof Grobelny                 appliedConfig, "BaseSpeedPriorityEnabled",
639351053f2SKrzysztof Grobelny                 baseSpeedPriorityEnabled);
640351053f2SKrzysztof Grobelny 
641351053f2SKrzysztof Grobelny             if (!success)
642dba0c291SJonathan Doman             {
643ac106bf6SEd Tanous                 messages::internalError(asyncResp->res);
644351053f2SKrzysztof Grobelny                 return;
645dba0c291SJonathan Doman             }
646dba0c291SJonathan Doman 
647351053f2SKrzysztof Grobelny             if (appliedConfig != nullptr)
648351053f2SKrzysztof Grobelny             {
649351053f2SKrzysztof Grobelny                 const std::string& dbusPath = appliedConfig->str;
6501476687dSEd Tanous                 nlohmann::json::object_t operatingConfig;
651ef4c65b7SEd Tanous                 operatingConfig["@odata.id"] = boost::urls::format(
652253f11b8SEd Tanous                     "/redfish/v1/Systems/{}/Processors/{}/OperatingConfigs",
653253f11b8SEd Tanous                     BMCWEB_REDFISH_SYSTEM_URI_NAME, cpuId);
6541476687dSEd Tanous                 json["OperatingConfigs"] = std::move(operatingConfig);
655dba0c291SJonathan Doman 
656dba0c291SJonathan Doman                 // Reuse the D-Bus config object name for the Redfish
657dba0c291SJonathan Doman                 // URI
658dba0c291SJonathan Doman                 size_t baseNamePos = dbusPath.rfind('/');
659dba0c291SJonathan Doman                 if (baseNamePos == std::string::npos ||
660dba0c291SJonathan Doman                     baseNamePos == (dbusPath.size() - 1))
661dba0c291SJonathan Doman                 {
662dba0c291SJonathan Doman                     // If the AppliedConfig was somehow not a valid path,
663dba0c291SJonathan Doman                     // skip adding any more properties, since everything
664dba0c291SJonathan Doman                     // else is tied to this applied config.
665ac106bf6SEd Tanous                     messages::internalError(asyncResp->res);
666351053f2SKrzysztof Grobelny                     return;
667dba0c291SJonathan Doman                 }
6681476687dSEd Tanous                 nlohmann::json::object_t appliedOperatingConfig;
669ef4c65b7SEd Tanous                 appliedOperatingConfig["@odata.id"] = boost::urls::format(
670253f11b8SEd Tanous                     "/redfish/v1/Systems/{}/Processors/{}/OperatingConfigs/{}",
671253f11b8SEd Tanous                     BMCWEB_REDFISH_SYSTEM_URI_NAME, cpuId,
672253f11b8SEd Tanous                     dbusPath.substr(baseNamePos + 1));
673bd79bce8SPatrick Williams                 json["AppliedOperatingConfig"] =
674bd79bce8SPatrick Williams                     std::move(appliedOperatingConfig);
675dba0c291SJonathan Doman 
676dba0c291SJonathan Doman                 // Once we found the current applied config, queue another
677dba0c291SJonathan Doman                 // request to read the base freq core ids out of that
678dba0c291SJonathan Doman                 // config.
679002d39b4SEd Tanous                 sdbusplus::asio::getProperty<BaseSpeedPrioritySettingsProperty>(
6801e1e598dSJonathan Doman                     *crow::connections::systemBus, service, dbusPath,
6811e1e598dSJonathan Doman                     "xyz.openbmc_project.Inventory.Item.Cpu."
6821e1e598dSJonathan Doman                     "OperatingConfig",
6831e1e598dSJonathan Doman                     "BaseSpeedPrioritySettings",
684bd79bce8SPatrick Williams                     [asyncResp](const boost::system::error_code& ec2,
685bd79bce8SPatrick Williams                                 const BaseSpeedPrioritySettingsProperty&
686bd79bce8SPatrick Williams                                     baseSpeedList) {
6878a592810SEd Tanous                         if (ec2)
688dba0c291SJonathan Doman                         {
689bd79bce8SPatrick Williams                             BMCWEB_LOG_WARNING("D-Bus Property Get error: {}",
690bd79bce8SPatrick Williams                                                ec2);
691ac106bf6SEd Tanous                             messages::internalError(asyncResp->res);
692dba0c291SJonathan Doman                             return;
693dba0c291SJonathan Doman                         }
6941e1e598dSJonathan Doman 
695ac106bf6SEd Tanous                         highSpeedCoreIdsHandler(asyncResp, baseSpeedList);
6961e1e598dSJonathan Doman                     });
697dba0c291SJonathan Doman             }
698351053f2SKrzysztof Grobelny 
699351053f2SKrzysztof Grobelny             if (baseSpeedPriorityEnabled != nullptr)
700dba0c291SJonathan Doman             {
701dba0c291SJonathan Doman                 json["BaseSpeedPriorityState"] =
702351053f2SKrzysztof Grobelny                     *baseSpeedPriorityEnabled ? "Enabled" : "Disabled";
703dba0c291SJonathan Doman             }
704351053f2SKrzysztof Grobelny         });
705dba0c291SJonathan Doman }
706dba0c291SJonathan Doman 
707cba4f448SSunnySrivastava1984 /**
708cba4f448SSunnySrivastava1984  * @brief Fill out location info of a processor by
709cba4f448SSunnySrivastava1984  * requesting data from the given D-Bus object.
710cba4f448SSunnySrivastava1984  *
711ac106bf6SEd Tanous  * @param[in,out]   asyncResp       Async HTTP response.
712cba4f448SSunnySrivastava1984  * @param[in]       service     D-Bus service to query.
713cba4f448SSunnySrivastava1984  * @param[in]       objPath     D-Bus object to query.
714cba4f448SSunnySrivastava1984  */
715ac106bf6SEd Tanous inline void getCpuLocationCode(std::shared_ptr<bmcweb::AsyncResp> asyncResp,
716cba4f448SSunnySrivastava1984                                const std::string& service,
717cba4f448SSunnySrivastava1984                                const std::string& objPath)
718cba4f448SSunnySrivastava1984 {
71962598e31SEd Tanous     BMCWEB_LOG_DEBUG("Get Cpu Location Data");
7201e1e598dSJonathan Doman     sdbusplus::asio::getProperty<std::string>(
7211e1e598dSJonathan Doman         *crow::connections::systemBus, service, objPath,
7221e1e598dSJonathan Doman         "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode",
723ac106bf6SEd Tanous         [objPath, asyncResp{std::move(asyncResp)}](
724ac106bf6SEd Tanous             const boost::system::error_code& ec, const std::string& property) {
725cba4f448SSunnySrivastava1984             if (ec)
726cba4f448SSunnySrivastava1984             {
72762598e31SEd Tanous                 BMCWEB_LOG_DEBUG("DBUS response error");
728ac106bf6SEd Tanous                 messages::internalError(asyncResp->res);
729cba4f448SSunnySrivastava1984                 return;
730cba4f448SSunnySrivastava1984             }
731cba4f448SSunnySrivastava1984 
732bd79bce8SPatrick Williams             asyncResp->res
733bd79bce8SPatrick Williams                 .jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
7341e1e598dSJonathan Doman                 property;
7351e1e598dSJonathan Doman         });
736cba4f448SSunnySrivastava1984 }
737cba4f448SSunnySrivastava1984 
738c951448aSJonathan Doman /**
73949e429caSJonathan Doman  * Populate the unique identifier in a Processor resource by requesting data
74049e429caSJonathan Doman  * from the given D-Bus object.
74149e429caSJonathan Doman  *
742ac106bf6SEd Tanous  * @param[in,out]   asyncResp   Async HTTP response.
74349e429caSJonathan Doman  * @param[in]       service     D-Bus service to query.
74449e429caSJonathan Doman  * @param[in]       objPath     D-Bus object to query.
74549e429caSJonathan Doman  */
746ac106bf6SEd Tanous inline void getCpuUniqueId(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
74749e429caSJonathan Doman                            const std::string& service,
74849e429caSJonathan Doman                            const std::string& objectPath)
74949e429caSJonathan Doman {
75062598e31SEd Tanous     BMCWEB_LOG_DEBUG("Get CPU UniqueIdentifier");
7511e1e598dSJonathan Doman     sdbusplus::asio::getProperty<std::string>(
7521e1e598dSJonathan Doman         *crow::connections::systemBus, service, objectPath,
7531e1e598dSJonathan Doman         "xyz.openbmc_project.Inventory.Decorator.UniqueIdentifier",
7541e1e598dSJonathan Doman         "UniqueIdentifier",
755ac106bf6SEd Tanous         [asyncResp](const boost::system::error_code& ec,
756ac106bf6SEd Tanous                     const std::string& id) {
7571e1e598dSJonathan Doman             if (ec)
75849e429caSJonathan Doman             {
75962598e31SEd Tanous                 BMCWEB_LOG_ERROR("Failed to read cpu unique id: {}", ec);
760ac106bf6SEd Tanous                 messages::internalError(asyncResp->res);
76149e429caSJonathan Doman                 return;
76249e429caSJonathan Doman             }
763ac106bf6SEd Tanous             asyncResp->res
764ac106bf6SEd Tanous                 .jsonValue["ProcessorId"]["ProtectedIdentificationNumber"] = id;
7651e1e598dSJonathan Doman         });
76649e429caSJonathan Doman }
76749e429caSJonathan Doman 
76849e429caSJonathan Doman /**
769c951448aSJonathan Doman  * Find the D-Bus object representing the requested Processor, and call the
770c951448aSJonathan Doman  * handler with the results. If matching object is not found, add 404 error to
771c951448aSJonathan Doman  * response and don't call the handler.
772c951448aSJonathan Doman  *
773c951448aSJonathan Doman  * @param[in,out]   resp            Async HTTP response.
774c951448aSJonathan Doman  * @param[in]       processorId     Redfish Processor Id.
775c951448aSJonathan Doman  * @param[in]       handler         Callback to continue processing request upon
776c951448aSJonathan Doman  *                                  successfully finding object.
777c951448aSJonathan Doman  */
778c951448aSJonathan Doman template <typename Handler>
7798d1b46d7Szhanghch05 inline void getProcessorObject(const std::shared_ptr<bmcweb::AsyncResp>& resp,
780c951448aSJonathan Doman                                const std::string& processorId,
781c951448aSJonathan Doman                                Handler&& handler)
782ac6a4445SGunnar Mills {
78362598e31SEd Tanous     BMCWEB_LOG_DEBUG("Get available system processor resources.");
784ac6a4445SGunnar Mills 
785c951448aSJonathan Doman     // GetSubTree on all interfaces which provide info about a Processor
786dfbf7de5SChris Cain     constexpr std::array<std::string_view, 9> interfaces = {
787e99073f5SGeorge Liu         "xyz.openbmc_project.Common.UUID",
788e99073f5SGeorge Liu         "xyz.openbmc_project.Inventory.Decorator.Asset",
789e99073f5SGeorge Liu         "xyz.openbmc_project.Inventory.Decorator.Revision",
790e99073f5SGeorge Liu         "xyz.openbmc_project.Inventory.Item.Cpu",
791e99073f5SGeorge Liu         "xyz.openbmc_project.Inventory.Decorator.LocationCode",
792e99073f5SGeorge Liu         "xyz.openbmc_project.Inventory.Item.Accelerator",
793e99073f5SGeorge Liu         "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig",
794dfbf7de5SChris Cain         "xyz.openbmc_project.Inventory.Decorator.UniqueIdentifier",
795dfbf7de5SChris Cain         "xyz.openbmc_project.Control.Power.Throttle"};
796e99073f5SGeorge Liu     dbus::utility::getSubTree(
797e99073f5SGeorge Liu         "/xyz/openbmc_project/inventory", 0, interfaces,
798c951448aSJonathan Doman         [resp, processorId, handler = std::forward<Handler>(handler)](
799e99073f5SGeorge Liu             const boost::system::error_code& ec,
800e99073f5SGeorge Liu             const dbus::utility::MapperGetSubTreeResponse& subtree) {
801ac6a4445SGunnar Mills             if (ec)
802ac6a4445SGunnar Mills             {
80362598e31SEd Tanous                 BMCWEB_LOG_DEBUG("DBUS response error: {}", ec);
804c951448aSJonathan Doman                 messages::internalError(resp->res);
805ac6a4445SGunnar Mills                 return;
806ac6a4445SGunnar Mills             }
8072bab9831SJonathan Doman             for (const auto& [objectPath, serviceMap] : subtree)
808ac6a4445SGunnar Mills             {
8092bab9831SJonathan Doman                 // Ignore any objects which don't end with our desired cpu name
81011ba3979SEd Tanous                 if (!objectPath.ends_with(processorId))
811ac6a4445SGunnar Mills                 {
8122bab9831SJonathan Doman                     continue;
813ac6a4445SGunnar Mills                 }
8142bab9831SJonathan Doman 
815c951448aSJonathan Doman                 bool found = false;
816c951448aSJonathan Doman                 // Filter out objects that don't have the CPU-specific
817c951448aSJonathan Doman                 // interfaces to make sure we can return 404 on non-CPUs
818c951448aSJonathan Doman                 // (e.g. /redfish/../Processors/dimm0)
8192bab9831SJonathan Doman                 for (const auto& [serviceName, interfaceList] : serviceMap)
820ac6a4445SGunnar Mills                 {
8213544d2a7SEd Tanous                     if (std::ranges::find_first_of(interfaceList,
8223544d2a7SEd Tanous                                                    processorInterfaces) !=
8233544d2a7SEd Tanous                         std::end(interfaceList))
8242bab9831SJonathan Doman                     {
825c951448aSJonathan Doman                         found = true;
826c951448aSJonathan Doman                         break;
827c951448aSJonathan Doman                     }
828c951448aSJonathan Doman                 }
829c951448aSJonathan Doman 
830c951448aSJonathan Doman                 if (!found)
8312bab9831SJonathan Doman                 {
832c951448aSJonathan Doman                     continue;
833ac6a4445SGunnar Mills                 }
834c951448aSJonathan Doman 
835c951448aSJonathan Doman                 // Process the first object which does match our cpu name and
836c951448aSJonathan Doman                 // required interfaces, and potentially ignore any other
837c951448aSJonathan Doman                 // matching objects. Assume all interfaces we want to process
838c951448aSJonathan Doman                 // must be on the same object path.
839c951448aSJonathan Doman 
8408a592810SEd Tanous                 handler(objectPath, serviceMap);
841ac6a4445SGunnar Mills                 return;
842ac6a4445SGunnar Mills             }
843c951448aSJonathan Doman             messages::resourceNotFound(resp->res, "Processor", processorId);
844e99073f5SGeorge Liu         });
845ac6a4445SGunnar Mills }
846ac6a4445SGunnar Mills 
847bd79bce8SPatrick Williams inline void getProcessorData(
848bd79bce8SPatrick Williams     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
849bd79bce8SPatrick Williams     const std::string& processorId, const std::string& objectPath,
8505df6eda2SShantappa Teekappanavar     const dbus::utility::MapperServiceMap& serviceMap)
851c951448aSJonathan Doman {
852c951448aSJonathan Doman     for (const auto& [serviceName, interfaceList] : serviceMap)
853c951448aSJonathan Doman     {
854c951448aSJonathan Doman         for (const auto& interface : interfaceList)
855c951448aSJonathan Doman         {
856c951448aSJonathan Doman             if (interface == "xyz.openbmc_project.Inventory.Decorator.Asset")
857c951448aSJonathan Doman             {
858ac106bf6SEd Tanous                 getCpuAssetData(asyncResp, serviceName, objectPath);
859c951448aSJonathan Doman             }
8600fda0f12SGeorge Liu             else if (interface ==
8610fda0f12SGeorge Liu                      "xyz.openbmc_project.Inventory.Decorator.Revision")
862c951448aSJonathan Doman             {
863ac106bf6SEd Tanous                 getCpuRevisionData(asyncResp, serviceName, objectPath);
864c951448aSJonathan Doman             }
865c951448aSJonathan Doman             else if (interface == "xyz.openbmc_project.Inventory.Item.Cpu")
866c951448aSJonathan Doman             {
867ac106bf6SEd Tanous                 getCpuDataByService(asyncResp, processorId, serviceName,
868c951448aSJonathan Doman                                     objectPath);
869c951448aSJonathan Doman             }
8700fda0f12SGeorge Liu             else if (interface ==
8710fda0f12SGeorge Liu                      "xyz.openbmc_project.Inventory.Item.Accelerator")
872c951448aSJonathan Doman             {
873ac106bf6SEd Tanous                 getAcceleratorDataByService(asyncResp, processorId, serviceName,
874c951448aSJonathan Doman                                             objectPath);
875c951448aSJonathan Doman             }
8760fda0f12SGeorge Liu             else if (
8770fda0f12SGeorge Liu                 interface ==
8780fda0f12SGeorge Liu                 "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig")
879c951448aSJonathan Doman             {
880ac106bf6SEd Tanous                 getCpuConfigData(asyncResp, processorId, serviceName,
881ac106bf6SEd Tanous                                  objectPath);
882c951448aSJonathan Doman             }
8830fda0f12SGeorge Liu             else if (interface ==
8840fda0f12SGeorge Liu                      "xyz.openbmc_project.Inventory.Decorator.LocationCode")
885c951448aSJonathan Doman             {
886ac106bf6SEd Tanous                 getCpuLocationCode(asyncResp, serviceName, objectPath);
887c951448aSJonathan Doman             }
88871b82f26SSharad Yadav             else if (interface == "xyz.openbmc_project.Common.UUID")
88971b82f26SSharad Yadav             {
890ac106bf6SEd Tanous                 getProcessorUUID(asyncResp, serviceName, objectPath);
89171b82f26SSharad Yadav             }
8920fda0f12SGeorge Liu             else if (interface ==
8930fda0f12SGeorge Liu                      "xyz.openbmc_project.Inventory.Decorator.UniqueIdentifier")
89449e429caSJonathan Doman             {
895ac106bf6SEd Tanous                 getCpuUniqueId(asyncResp, serviceName, objectPath);
89649e429caSJonathan Doman             }
897dfbf7de5SChris Cain             else if (interface == "xyz.openbmc_project.Control.Power.Throttle")
898dfbf7de5SChris Cain             {
899ac106bf6SEd Tanous                 getThrottleProperties(asyncResp, serviceName, objectPath);
900dfbf7de5SChris Cain             }
901c951448aSJonathan Doman         }
902c951448aSJonathan Doman     }
903c951448aSJonathan Doman }
904c951448aSJonathan Doman 
905dba0c291SJonathan Doman /**
906dba0c291SJonathan Doman  * Request all the properties for the given D-Bus object and fill out the
907dba0c291SJonathan Doman  * related entries in the Redfish OperatingConfig response.
908dba0c291SJonathan Doman  *
909ac106bf6SEd Tanous  * @param[in,out]   asyncResp       Async HTTP response.
910dba0c291SJonathan Doman  * @param[in]       service     D-Bus service name to query.
911dba0c291SJonathan Doman  * @param[in]       objPath     D-Bus object to query.
912dba0c291SJonathan Doman  */
913bd79bce8SPatrick Williams inline void getOperatingConfigData(
914bd79bce8SPatrick Williams     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
915bd79bce8SPatrick Williams     const std::string& service, const std::string& objPath)
916dba0c291SJonathan Doman {
917351053f2SKrzysztof Grobelny     sdbusplus::asio::getAllProperties(
918351053f2SKrzysztof Grobelny         *crow::connections::systemBus, service, objPath,
919351053f2SKrzysztof Grobelny         "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig",
920ac106bf6SEd Tanous         [asyncResp](const boost::system::error_code& ec,
921351053f2SKrzysztof Grobelny                     const dbus::utility::DBusPropertiesMap& properties) {
922dba0c291SJonathan Doman             if (ec)
923dba0c291SJonathan Doman             {
92462598e31SEd Tanous                 BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec, ec.message());
925ac106bf6SEd Tanous                 messages::internalError(asyncResp->res);
926dba0c291SJonathan Doman                 return;
927dba0c291SJonathan Doman             }
928dba0c291SJonathan Doman 
929351053f2SKrzysztof Grobelny             const size_t* availableCoreCount = nullptr;
930351053f2SKrzysztof Grobelny             const uint32_t* baseSpeed = nullptr;
931351053f2SKrzysztof Grobelny             const uint32_t* maxJunctionTemperature = nullptr;
932351053f2SKrzysztof Grobelny             const uint32_t* maxSpeed = nullptr;
933351053f2SKrzysztof Grobelny             const uint32_t* powerLimit = nullptr;
934351053f2SKrzysztof Grobelny             const TurboProfileProperty* turboProfile = nullptr;
935351053f2SKrzysztof Grobelny             const BaseSpeedPrioritySettingsProperty* baseSpeedPrioritySettings =
936351053f2SKrzysztof Grobelny                 nullptr;
937351053f2SKrzysztof Grobelny 
938351053f2SKrzysztof Grobelny             const bool success = sdbusplus::unpackPropertiesNoThrow(
939bd79bce8SPatrick Williams                 dbus_utils::UnpackErrorPrinter(), properties,
940bd79bce8SPatrick Williams                 "AvailableCoreCount", availableCoreCount, "BaseSpeed",
941bd79bce8SPatrick Williams                 baseSpeed, "MaxJunctionTemperature", maxJunctionTemperature,
942bd79bce8SPatrick Williams                 "MaxSpeed", maxSpeed, "PowerLimit", powerLimit, "TurboProfile",
943bd79bce8SPatrick Williams                 turboProfile, "BaseSpeedPrioritySettings",
944bd79bce8SPatrick Williams                 baseSpeedPrioritySettings);
945351053f2SKrzysztof Grobelny 
946351053f2SKrzysztof Grobelny             if (!success)
947dba0c291SJonathan Doman             {
948ac106bf6SEd Tanous                 messages::internalError(asyncResp->res);
949351053f2SKrzysztof Grobelny                 return;
950dba0c291SJonathan Doman             }
951dba0c291SJonathan Doman 
952ac106bf6SEd Tanous             nlohmann::json& json = asyncResp->res.jsonValue;
953351053f2SKrzysztof Grobelny 
954351053f2SKrzysztof Grobelny             if (availableCoreCount != nullptr)
955351053f2SKrzysztof Grobelny             {
956351053f2SKrzysztof Grobelny                 json["TotalAvailableCoreCount"] = *availableCoreCount;
957351053f2SKrzysztof Grobelny             }
958351053f2SKrzysztof Grobelny 
959351053f2SKrzysztof Grobelny             if (baseSpeed != nullptr)
960351053f2SKrzysztof Grobelny             {
961351053f2SKrzysztof Grobelny                 json["BaseSpeedMHz"] = *baseSpeed;
962351053f2SKrzysztof Grobelny             }
963351053f2SKrzysztof Grobelny 
964351053f2SKrzysztof Grobelny             if (maxJunctionTemperature != nullptr)
965351053f2SKrzysztof Grobelny             {
966351053f2SKrzysztof Grobelny                 json["MaxJunctionTemperatureCelsius"] = *maxJunctionTemperature;
967351053f2SKrzysztof Grobelny             }
968351053f2SKrzysztof Grobelny 
969351053f2SKrzysztof Grobelny             if (maxSpeed != nullptr)
970351053f2SKrzysztof Grobelny             {
971351053f2SKrzysztof Grobelny                 json["MaxSpeedMHz"] = *maxSpeed;
972351053f2SKrzysztof Grobelny             }
973351053f2SKrzysztof Grobelny 
974351053f2SKrzysztof Grobelny             if (powerLimit != nullptr)
975351053f2SKrzysztof Grobelny             {
976351053f2SKrzysztof Grobelny                 json["TDPWatts"] = *powerLimit;
977351053f2SKrzysztof Grobelny             }
978351053f2SKrzysztof Grobelny 
979351053f2SKrzysztof Grobelny             if (turboProfile != nullptr)
980351053f2SKrzysztof Grobelny             {
981dba0c291SJonathan Doman                 nlohmann::json& turboArray = json["TurboProfile"];
982dba0c291SJonathan Doman                 turboArray = nlohmann::json::array();
983351053f2SKrzysztof Grobelny                 for (const auto& [turboSpeed, coreCount] : *turboProfile)
984dba0c291SJonathan Doman                 {
9851476687dSEd Tanous                     nlohmann::json::object_t turbo;
9861476687dSEd Tanous                     turbo["ActiveCoreCount"] = coreCount;
9871476687dSEd Tanous                     turbo["MaxSpeedMHz"] = turboSpeed;
988b2ba3072SPatrick Williams                     turboArray.emplace_back(std::move(turbo));
989dba0c291SJonathan Doman                 }
990dba0c291SJonathan Doman             }
991dba0c291SJonathan Doman 
992351053f2SKrzysztof Grobelny             if (baseSpeedPrioritySettings != nullptr)
993351053f2SKrzysztof Grobelny             {
994bd79bce8SPatrick Williams                 nlohmann::json& baseSpeedArray =
995bd79bce8SPatrick Williams                     json["BaseSpeedPrioritySettings"];
996dba0c291SJonathan Doman                 baseSpeedArray = nlohmann::json::array();
997351053f2SKrzysztof Grobelny                 for (const auto& [baseSpeedMhz, coreList] :
998351053f2SKrzysztof Grobelny                      *baseSpeedPrioritySettings)
999dba0c291SJonathan Doman                 {
10001476687dSEd Tanous                     nlohmann::json::object_t speed;
10011476687dSEd Tanous                     speed["CoreCount"] = coreList.size();
10021476687dSEd Tanous                     speed["CoreIDs"] = coreList;
1003351053f2SKrzysztof Grobelny                     speed["BaseSpeedMHz"] = baseSpeedMhz;
1004b2ba3072SPatrick Williams                     baseSpeedArray.emplace_back(std::move(speed));
1005dba0c291SJonathan Doman                 }
1006dba0c291SJonathan Doman             }
1007351053f2SKrzysztof Grobelny         });
1008dba0c291SJonathan Doman }
1009dba0c291SJonathan Doman 
10103cde86f1SJonathan Doman /**
10113cde86f1SJonathan Doman  * Handle the PATCH operation of the AppliedOperatingConfig property. Do basic
10123cde86f1SJonathan Doman  * validation of the input data, and then set the D-Bus property.
10133cde86f1SJonathan Doman  *
10143cde86f1SJonathan Doman  * @param[in,out]   resp            Async HTTP response.
10153cde86f1SJonathan Doman  * @param[in]       processorId     Processor's Id.
10163cde86f1SJonathan Doman  * @param[in]       appliedConfigUri    New property value to apply.
10173cde86f1SJonathan Doman  * @param[in]       cpuObjectPath   Path of CPU object to modify.
10183cde86f1SJonathan Doman  * @param[in]       serviceMap      Service map for CPU object.
10193cde86f1SJonathan Doman  */
10203cde86f1SJonathan Doman inline void patchAppliedOperatingConfig(
10213cde86f1SJonathan Doman     const std::shared_ptr<bmcweb::AsyncResp>& resp,
10223cde86f1SJonathan Doman     const std::string& processorId, const std::string& appliedConfigUri,
10235df6eda2SShantappa Teekappanavar     const std::string& cpuObjectPath,
10245df6eda2SShantappa Teekappanavar     const dbus::utility::MapperServiceMap& serviceMap)
10253cde86f1SJonathan Doman {
10263cde86f1SJonathan Doman     // Check that the property even exists by checking for the interface
10273cde86f1SJonathan Doman     const std::string* controlService = nullptr;
10283cde86f1SJonathan Doman     for (const auto& [serviceName, interfaceList] : serviceMap)
10293cde86f1SJonathan Doman     {
10303544d2a7SEd Tanous         if (std::ranges::find(interfaceList,
10313cde86f1SJonathan Doman                               "xyz.openbmc_project.Control.Processor."
10323cde86f1SJonathan Doman                               "CurrentOperatingConfig") != interfaceList.end())
10333cde86f1SJonathan Doman         {
10343cde86f1SJonathan Doman             controlService = &serviceName;
10353cde86f1SJonathan Doman             break;
10363cde86f1SJonathan Doman         }
10373cde86f1SJonathan Doman     }
10383cde86f1SJonathan Doman 
10393cde86f1SJonathan Doman     if (controlService == nullptr)
10403cde86f1SJonathan Doman     {
10413cde86f1SJonathan Doman         messages::internalError(resp->res);
10423cde86f1SJonathan Doman         return;
10433cde86f1SJonathan Doman     }
10443cde86f1SJonathan Doman 
10453cde86f1SJonathan Doman     // Check that the config URI is a child of the cpu URI being patched.
1046253f11b8SEd Tanous     std::string expectedPrefix(std::format("/redfish/v1/Systems/{}/Processors/",
1047253f11b8SEd Tanous                                            BMCWEB_REDFISH_SYSTEM_URI_NAME));
10483cde86f1SJonathan Doman     expectedPrefix += processorId;
10493cde86f1SJonathan Doman     expectedPrefix += "/OperatingConfigs/";
105011ba3979SEd Tanous     if (!appliedConfigUri.starts_with(expectedPrefix) ||
10513cde86f1SJonathan Doman         expectedPrefix.size() == appliedConfigUri.size())
10523cde86f1SJonathan Doman     {
105387c44966SAsmitha Karunanithi         messages::propertyValueIncorrect(resp->res, "AppliedOperatingConfig",
105487c44966SAsmitha Karunanithi                                          appliedConfigUri);
10553cde86f1SJonathan Doman         return;
10563cde86f1SJonathan Doman     }
10573cde86f1SJonathan Doman 
10583cde86f1SJonathan Doman     // Generate the D-Bus path of the OperatingConfig object, by assuming it's a
10593cde86f1SJonathan Doman     // direct child of the CPU object.
10603cde86f1SJonathan Doman     // Strip the expectedPrefix from the config URI to get the "filename", and
10613cde86f1SJonathan Doman     // append to the CPU's path.
10623cde86f1SJonathan Doman     std::string configBaseName = appliedConfigUri.substr(expectedPrefix.size());
10633cde86f1SJonathan Doman     sdbusplus::message::object_path configPath(cpuObjectPath);
10643cde86f1SJonathan Doman     configPath /= configBaseName;
10653cde86f1SJonathan Doman 
106662598e31SEd Tanous     BMCWEB_LOG_INFO("Setting config to {}", configPath.str);
10673cde86f1SJonathan Doman 
10683cde86f1SJonathan Doman     // Set the property, with handler to check error responses
106987c44966SAsmitha Karunanithi     setDbusProperty(
1070e93abac6SGinu George         resp, "AppliedOperatingConfig", *controlService, cpuObjectPath,
10719ae226faSGeorge Liu         "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig",
1072e93abac6SGinu George         "AppliedConfig", configPath);
10733cde86f1SJonathan Doman }
10743cde86f1SJonathan Doman 
1075bd79bce8SPatrick Williams inline void handleProcessorHead(
1076bd79bce8SPatrick Williams     crow::App& app, const crow::Request& req,
1077ac106bf6SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1078bd79bce8SPatrick Williams     const std::string& /* systemName */, const std::string& /* processorId */)
107971a24ca4SNikhil Namjoshi {
1080ac106bf6SEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
108171a24ca4SNikhil Namjoshi     {
108271a24ca4SNikhil Namjoshi         return;
108371a24ca4SNikhil Namjoshi     }
1084ac106bf6SEd Tanous     asyncResp->res.addHeader(
108571a24ca4SNikhil Namjoshi         boost::beast::http::field::link,
108671a24ca4SNikhil Namjoshi         "</redfish/v1/JsonSchemas/Processor/Processor.json>; rel=describedby");
108771a24ca4SNikhil Namjoshi }
108871a24ca4SNikhil Namjoshi 
108971a24ca4SNikhil Namjoshi inline void handleProcessorCollectionHead(
109071a24ca4SNikhil Namjoshi     crow::App& app, const crow::Request& req,
1091ac106bf6SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
109271a24ca4SNikhil Namjoshi     const std::string& /* systemName */)
109371a24ca4SNikhil Namjoshi {
1094ac106bf6SEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
109571a24ca4SNikhil Namjoshi     {
109671a24ca4SNikhil Namjoshi         return;
109771a24ca4SNikhil Namjoshi     }
1098ac106bf6SEd Tanous     asyncResp->res.addHeader(
109971a24ca4SNikhil Namjoshi         boost::beast::http::field::link,
110071a24ca4SNikhil Namjoshi         "</redfish/v1/JsonSchemas/ProcessorCollection/ProcessorCollection.json>; rel=describedby");
110171a24ca4SNikhil Namjoshi }
110271a24ca4SNikhil Namjoshi 
11037e860f15SJohn Edward Broadbent inline void requestRoutesOperatingConfigCollection(App& app)
1104dba0c291SJonathan Doman {
11057f3e84a1SEd Tanous     BMCWEB_ROUTE(app,
11067f3e84a1SEd Tanous                  "/redfish/v1/Systems/<str>/Processors/<str>/OperatingConfigs/")
1107ed398213SEd Tanous         .privileges(redfish::privileges::getOperatingConfigCollection)
1108bd79bce8SPatrick Williams         .methods(
1109bd79bce8SPatrick Williams             boost::beast::http::verb::
1110bd79bce8SPatrick Williams                 get)([&app](const crow::Request& req,
111145ca1b86SEd Tanous                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1112bd79bce8SPatrick Williams                             const std::string& systemName,
1113bd79bce8SPatrick Williams                             const std::string& cpuName) {
11143ba00073SCarson Labrado             if (!redfish::setUpRedfishRoute(app, req, asyncResp))
111545ca1b86SEd Tanous             {
111645ca1b86SEd Tanous                 return;
111745ca1b86SEd Tanous             }
11187f3e84a1SEd Tanous 
111925b54dbaSEd Tanous             if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
11207f3e84a1SEd Tanous             {
11217f3e84a1SEd Tanous                 // Option currently returns no systems.  TBD
11227f3e84a1SEd Tanous                 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
11237f3e84a1SEd Tanous                                            systemName);
11247f3e84a1SEd Tanous                 return;
11257f3e84a1SEd Tanous             }
11267f3e84a1SEd Tanous 
1127253f11b8SEd Tanous             if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
11287f3e84a1SEd Tanous             {
11297f3e84a1SEd Tanous                 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
11307f3e84a1SEd Tanous                                            systemName);
11317f3e84a1SEd Tanous                 return;
11327f3e84a1SEd Tanous             }
11338d1b46d7Szhanghch05             asyncResp->res.jsonValue["@odata.type"] =
1134dba0c291SJonathan Doman                 "#OperatingConfigCollection.OperatingConfigCollection";
1135ef4c65b7SEd Tanous             asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
1136253f11b8SEd Tanous                 "/redfish/v1/Systems/{}/Processors/{}/OperatingConfigs",
1137253f11b8SEd Tanous                 BMCWEB_REDFISH_SYSTEM_URI_NAME, cpuName);
11380fda0f12SGeorge Liu             asyncResp->res.jsonValue["Name"] = "Operating Config Collection";
1139dba0c291SJonathan Doman 
11407e860f15SJohn Edward Broadbent             // First find the matching CPU object so we know how to
11417e860f15SJohn Edward Broadbent             // constrain our search for related Config objects.
11427a1dbc48SGeorge Liu             const std::array<std::string_view, 1> interfaces = {
11437a1dbc48SGeorge Liu                 "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig"};
11447a1dbc48SGeorge Liu             dbus::utility::getSubTreePaths(
11457a1dbc48SGeorge Liu                 "/xyz/openbmc_project/inventory", 0, interfaces,
1146bd79bce8SPatrick Williams                 [asyncResp,
1147bd79bce8SPatrick Williams                  cpuName](const boost::system::error_code& ec,
1148bd79bce8SPatrick Williams                           const dbus::utility::MapperGetSubTreePathsResponse&
1149bd79bce8SPatrick Williams                               objects) {
1150dba0c291SJonathan Doman                     if (ec)
1151dba0c291SJonathan Doman                     {
1152bd79bce8SPatrick Williams                         BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec,
1153bd79bce8SPatrick Williams                                            ec.message());
1154dba0c291SJonathan Doman                         messages::internalError(asyncResp->res);
1155dba0c291SJonathan Doman                         return;
1156dba0c291SJonathan Doman                     }
1157dba0c291SJonathan Doman 
1158dba0c291SJonathan Doman                     for (const std::string& object : objects)
1159dba0c291SJonathan Doman                     {
116011ba3979SEd Tanous                         if (!object.ends_with(cpuName))
1161dba0c291SJonathan Doman                         {
1162dba0c291SJonathan Doman                             continue;
1163dba0c291SJonathan Doman                         }
1164dba0c291SJonathan Doman 
11657e860f15SJohn Edward Broadbent                         // Not expected that there will be multiple matching
11667e860f15SJohn Edward Broadbent                         // CPU objects, but if there are just use the first
11677e860f15SJohn Edward Broadbent                         // one.
1168dba0c291SJonathan Doman 
11697e860f15SJohn Edward Broadbent                         // Use the common search routine to construct the
11707e860f15SJohn Edward Broadbent                         // Collection of all Config objects under this CPU.
11717a1dbc48SGeorge Liu                         constexpr std::array<std::string_view, 1> interface{
11725a39f77aSPatrick Williams                             "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig"};
1173dba0c291SJonathan Doman                         collection_util::getCollectionMembers(
1174dba0c291SJonathan Doman                             asyncResp,
1175ef4c65b7SEd Tanous                             boost::urls::format(
1176253f11b8SEd Tanous                                 "/redfish/v1/Systems/{}/Processors/{}/OperatingConfigs",
1177253f11b8SEd Tanous                                 BMCWEB_REDFISH_SYSTEM_URI_NAME, cpuName),
117836b5f1edSLakshmi Yadlapati                             interface, object);
1179dba0c291SJonathan Doman                         return;
1180dba0c291SJonathan Doman                     }
11817a1dbc48SGeorge Liu                 });
11827e860f15SJohn Edward Broadbent         });
1183dba0c291SJonathan Doman }
1184dba0c291SJonathan Doman 
11857e860f15SJohn Edward Broadbent inline void requestRoutesOperatingConfig(App& app)
1186dba0c291SJonathan Doman {
11877e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(
11887e860f15SJohn Edward Broadbent         app,
11897f3e84a1SEd Tanous         "/redfish/v1/Systems/<str>/Processors/<str>/OperatingConfigs/<str>/")
1190ed398213SEd Tanous         .privileges(redfish::privileges::getOperatingConfig)
1191bd79bce8SPatrick Williams         .methods(
1192bd79bce8SPatrick Williams             boost::beast::http::verb::
1193bd79bce8SPatrick Williams                 get)([&app](const crow::Request& req,
119445ca1b86SEd Tanous                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1195bd79bce8SPatrick Williams                             const std::string& systemName,
1196bd79bce8SPatrick Williams                             const std::string& cpuName,
11977f3e84a1SEd Tanous                             const std::string& configName) {
11983ba00073SCarson Labrado             if (!redfish::setUpRedfishRoute(app, req, asyncResp))
119945ca1b86SEd Tanous             {
120045ca1b86SEd Tanous                 return;
120145ca1b86SEd Tanous             }
120225b54dbaSEd Tanous             if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
12037f3e84a1SEd Tanous             {
12047f3e84a1SEd Tanous                 // Option currently returns no systems.  TBD
12057f3e84a1SEd Tanous                 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
12067f3e84a1SEd Tanous                                            systemName);
12077f3e84a1SEd Tanous                 return;
12087f3e84a1SEd Tanous             }
12097f3e84a1SEd Tanous 
1210253f11b8SEd Tanous             if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
12117f3e84a1SEd Tanous             {
12127f3e84a1SEd Tanous                 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
12137f3e84a1SEd Tanous                                            systemName);
12147f3e84a1SEd Tanous                 return;
12157f3e84a1SEd Tanous             }
12167e860f15SJohn Edward Broadbent             // Ask for all objects implementing OperatingConfig so we can search
12177e860f15SJohn Edward Broadbent             // for one with a matching name
1218e99073f5SGeorge Liu             constexpr std::array<std::string_view, 1> interfaces = {
1219e99073f5SGeorge Liu                 "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig"};
1220e99073f5SGeorge Liu             dbus::utility::getSubTree(
1221e99073f5SGeorge Liu                 "/xyz/openbmc_project/inventory", 0, interfaces,
122239662a3bSEd Tanous                 [asyncResp, cpuName, configName](
1223e99073f5SGeorge Liu                     const boost::system::error_code& ec,
12245df6eda2SShantappa Teekappanavar                     const dbus::utility::MapperGetSubTreeResponse& subtree) {
1225dba0c291SJonathan Doman                     if (ec)
1226dba0c291SJonathan Doman                     {
1227bd79bce8SPatrick Williams                         BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec,
1228bd79bce8SPatrick Williams                                            ec.message());
1229dba0c291SJonathan Doman                         messages::internalError(asyncResp->res);
1230dba0c291SJonathan Doman                         return;
1231dba0c291SJonathan Doman                     }
1232bd79bce8SPatrick Williams                     const std::string expectedEnding =
1233bd79bce8SPatrick Williams                         cpuName + '/' + configName;
1234dba0c291SJonathan Doman                     for (const auto& [objectPath, serviceMap] : subtree)
1235dba0c291SJonathan Doman                     {
1236dba0c291SJonathan Doman                         // Ignore any configs without matching cpuX/configY
1237bd79bce8SPatrick Williams                         if (!objectPath.ends_with(expectedEnding) ||
1238bd79bce8SPatrick Williams                             serviceMap.empty())
1239dba0c291SJonathan Doman                         {
1240dba0c291SJonathan Doman                             continue;
1241dba0c291SJonathan Doman                         }
1242dba0c291SJonathan Doman 
1243dba0c291SJonathan Doman                         nlohmann::json& json = asyncResp->res.jsonValue;
1244bd79bce8SPatrick Williams                         json["@odata.type"] =
1245bd79bce8SPatrick Williams                             "#OperatingConfig.v1_0_0.OperatingConfig";
1246ef4c65b7SEd Tanous                         json["@odata.id"] = boost::urls::format(
1247253f11b8SEd Tanous                             "/redfish/v1/Systems/{}/Processors/{}/OperatingConfigs/{}",
1248bd79bce8SPatrick Williams                             BMCWEB_REDFISH_SYSTEM_URI_NAME, cpuName,
1249bd79bce8SPatrick Williams                             configName);
1250dba0c291SJonathan Doman                         json["Name"] = "Processor Profile";
1251dba0c291SJonathan Doman                         json["Id"] = configName;
1252dba0c291SJonathan Doman 
1253dba0c291SJonathan Doman                         // Just use the first implementation of the object - not
12547e860f15SJohn Edward Broadbent                         // expected that there would be multiple matching
12557e860f15SJohn Edward Broadbent                         // services
1256bd79bce8SPatrick Williams                         getOperatingConfigData(
1257bd79bce8SPatrick Williams                             asyncResp, serviceMap.begin()->first, objectPath);
1258dba0c291SJonathan Doman                         return;
1259dba0c291SJonathan Doman                     }
1260bd79bce8SPatrick Williams                     messages::resourceNotFound(asyncResp->res,
1261bd79bce8SPatrick Williams                                                "OperatingConfig", configName);
1262e99073f5SGeorge Liu                 });
12637e860f15SJohn Edward Broadbent         });
1264ac6a4445SGunnar Mills }
1265ac6a4445SGunnar Mills 
12667e860f15SJohn Edward Broadbent inline void requestRoutesProcessorCollection(App& app)
12677e860f15SJohn Edward Broadbent {
1268ac6a4445SGunnar Mills     /**
1269ac6a4445SGunnar Mills      * Functions triggers appropriate requests on DBus
1270ac6a4445SGunnar Mills      */
127122d268cbSEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/")
127271a24ca4SNikhil Namjoshi         .privileges(redfish::privileges::headProcessorCollection)
127371a24ca4SNikhil Namjoshi         .methods(boost::beast::http::verb::head)(
127471a24ca4SNikhil Namjoshi             std::bind_front(handleProcessorCollectionHead, std::ref(app)));
127571a24ca4SNikhil Namjoshi 
127671a24ca4SNikhil Namjoshi     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/")
1277ed398213SEd Tanous         .privileges(redfish::privileges::getProcessorCollection)
1278bd79bce8SPatrick Williams         .methods(
1279bd79bce8SPatrick Williams             boost::beast::http::verb::
1280bd79bce8SPatrick Williams                 get)([&app](const crow::Request& req,
128122d268cbSEd Tanous                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
128222d268cbSEd Tanous                             const std::string& systemName) {
12833ba00073SCarson Labrado             if (!redfish::setUpRedfishRoute(app, req, asyncResp))
128445ca1b86SEd Tanous             {
128545ca1b86SEd Tanous                 return;
128645ca1b86SEd Tanous             }
128725b54dbaSEd Tanous             if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
12887f3e84a1SEd Tanous             {
12897f3e84a1SEd Tanous                 // Option currently returns no systems.  TBD
12907f3e84a1SEd Tanous                 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
12917f3e84a1SEd Tanous                                            systemName);
12927f3e84a1SEd Tanous                 return;
12937f3e84a1SEd Tanous             }
12947f3e84a1SEd Tanous 
1295253f11b8SEd Tanous             if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
129622d268cbSEd Tanous             {
129722d268cbSEd Tanous                 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
129822d268cbSEd Tanous                                            systemName);
129922d268cbSEd Tanous                 return;
130022d268cbSEd Tanous             }
130122d268cbSEd Tanous 
130271a24ca4SNikhil Namjoshi             asyncResp->res.addHeader(
130371a24ca4SNikhil Namjoshi                 boost::beast::http::field::link,
130471a24ca4SNikhil Namjoshi                 "</redfish/v1/JsonSchemas/ProcessorCollection/ProcessorCollection.json>; rel=describedby");
130571a24ca4SNikhil Namjoshi 
13068d1b46d7Szhanghch05             asyncResp->res.jsonValue["@odata.type"] =
1307ac6a4445SGunnar Mills                 "#ProcessorCollection.ProcessorCollection";
13088d1b46d7Szhanghch05             asyncResp->res.jsonValue["Name"] = "Processor Collection";
1309ac6a4445SGunnar Mills 
13108d1b46d7Szhanghch05             asyncResp->res.jsonValue["@odata.id"] =
1311253f11b8SEd Tanous                 std::format("/redfish/v1/Systems/{}/Processors",
1312253f11b8SEd Tanous                             BMCWEB_REDFISH_SYSTEM_URI_NAME);
1313ac6a4445SGunnar Mills 
131405030b8eSGunnar Mills             collection_util::getCollectionMembers(
1315ae9031f0SWilly Tu                 asyncResp,
1316253f11b8SEd Tanous                 boost::urls::format("/redfish/v1/Systems/{}/Processors",
1317253f11b8SEd Tanous                                     BMCWEB_REDFISH_SYSTEM_URI_NAME),
131836b5f1edSLakshmi Yadlapati                 processorInterfaces, "/xyz/openbmc_project/inventory");
13197e860f15SJohn Edward Broadbent         });
1320ac6a4445SGunnar Mills }
1321ac6a4445SGunnar Mills 
13227e860f15SJohn Edward Broadbent inline void requestRoutesProcessor(App& app)
13237e860f15SJohn Edward Broadbent {
1324ac6a4445SGunnar Mills     /**
1325ac6a4445SGunnar Mills      * Functions triggers appropriate requests on DBus
1326ac6a4445SGunnar Mills      */
13277e860f15SJohn Edward Broadbent 
132822d268cbSEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/<str>/")
132971a24ca4SNikhil Namjoshi         .privileges(redfish::privileges::headProcessor)
133071a24ca4SNikhil Namjoshi         .methods(boost::beast::http::verb::head)(
133171a24ca4SNikhil Namjoshi             std::bind_front(handleProcessorHead, std::ref(app)));
133271a24ca4SNikhil Namjoshi 
133371a24ca4SNikhil Namjoshi     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/<str>/")
1334ed398213SEd Tanous         .privileges(redfish::privileges::getProcessor)
1335bd79bce8SPatrick Williams         .methods(
1336bd79bce8SPatrick Williams             boost::beast::http::verb::
1337bd79bce8SPatrick Williams                 get)([&app](const crow::Request& req,
13387e860f15SJohn Edward Broadbent                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
133922d268cbSEd Tanous                             const std::string& systemName,
13407e860f15SJohn Edward Broadbent                             const std::string& processorId) {
13413ba00073SCarson Labrado             if (!redfish::setUpRedfishRoute(app, req, asyncResp))
134245ca1b86SEd Tanous             {
134345ca1b86SEd Tanous                 return;
134445ca1b86SEd Tanous             }
134525b54dbaSEd Tanous             if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
13467f3e84a1SEd Tanous             {
13477f3e84a1SEd Tanous                 // Option currently returns no systems.  TBD
13487f3e84a1SEd Tanous                 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
13497f3e84a1SEd Tanous                                            systemName);
13507f3e84a1SEd Tanous                 return;
13517f3e84a1SEd Tanous             }
1352253f11b8SEd Tanous             if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
135322d268cbSEd Tanous             {
135422d268cbSEd Tanous                 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
135522d268cbSEd Tanous                                            systemName);
135622d268cbSEd Tanous                 return;
135722d268cbSEd Tanous             }
135822d268cbSEd Tanous 
135971a24ca4SNikhil Namjoshi             asyncResp->res.addHeader(
136071a24ca4SNikhil Namjoshi                 boost::beast::http::field::link,
136171a24ca4SNikhil Namjoshi                 "</redfish/v1/JsonSchemas/Processor/Processor.json>; rel=describedby");
13628d1b46d7Szhanghch05             asyncResp->res.jsonValue["@odata.type"] =
1363dfbf7de5SChris Cain                 "#Processor.v1_18_0.Processor";
1364bd79bce8SPatrick Williams             asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
1365bd79bce8SPatrick Williams                 "/redfish/v1/Systems/{}/Processors/{}",
1366253f11b8SEd Tanous                 BMCWEB_REDFISH_SYSTEM_URI_NAME, processorId);
1367ac6a4445SGunnar Mills 
13688a592810SEd Tanous             getProcessorObject(
13698a592810SEd Tanous                 asyncResp, processorId,
13708a592810SEd Tanous                 std::bind_front(getProcessorData, asyncResp, processorId));
13717e860f15SJohn Edward Broadbent         });
13723cde86f1SJonathan Doman 
137322d268cbSEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/<str>/")
1374ed398213SEd Tanous         .privileges(redfish::privileges::patchProcessor)
13757e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::patch)(
137645ca1b86SEd Tanous             [&app](const crow::Request& req,
13777e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
137822d268cbSEd Tanous                    const std::string& systemName,
13797e860f15SJohn Edward Broadbent                    const std::string& processorId) {
13803ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
138145ca1b86SEd Tanous                 {
138245ca1b86SEd Tanous                     return;
138345ca1b86SEd Tanous                 }
138425b54dbaSEd Tanous                 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
13857f3e84a1SEd Tanous                 {
13867f3e84a1SEd Tanous                     // Option currently returns no systems.  TBD
13877f3e84a1SEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
13887f3e84a1SEd Tanous                                                systemName);
13897f3e84a1SEd Tanous                     return;
13907f3e84a1SEd Tanous                 }
1391253f11b8SEd Tanous                 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
139222d268cbSEd Tanous                 {
139322d268cbSEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
139422d268cbSEd Tanous                                                systemName);
139522d268cbSEd Tanous                     return;
139622d268cbSEd Tanous                 }
139722d268cbSEd Tanous 
13983c569218SEd Tanous                 std::optional<std::string> appliedConfigUri;
1399bd79bce8SPatrick Williams                 if (!json_util::readJsonPatch(
1400*afc474aeSMyung Bae                         req, asyncResp->res, //
1401*afc474aeSMyung Bae                         "AppliedOperatingConfig/@odata.id", appliedConfigUri //
1402*afc474aeSMyung Bae                         ))
14033cde86f1SJonathan Doman                 {
14043cde86f1SJonathan Doman                     return;
14053cde86f1SJonathan Doman                 }
14063cde86f1SJonathan Doman 
14073c569218SEd Tanous                 if (appliedConfigUri)
14083cde86f1SJonathan Doman                 {
14097e860f15SJohn Edward Broadbent                     // Check for 404 and find matching D-Bus object, then run
14107e860f15SJohn Edward Broadbent                     // property patch handlers if that all succeeds.
1411bd79bce8SPatrick Williams                     getProcessorObject(
14127e860f15SJohn Edward Broadbent                         asyncResp, processorId,
1413bd79bce8SPatrick Williams                         std::bind_front(patchAppliedOperatingConfig, asyncResp,
1414bd79bce8SPatrick Williams                                         processorId, *appliedConfigUri));
14153cde86f1SJonathan Doman                 }
14167e860f15SJohn Edward Broadbent             });
14173cde86f1SJonathan Doman }
1418ac6a4445SGunnar Mills 
1419ac6a4445SGunnar Mills } // namespace redfish
1420