blob: 19b059aa05fd2570da8a1cb8109a3df9fc9a3958 [file] [log] [blame]
Gunnar Millsac6a4442020-10-14 14:55:29 -05001/*
2// Copyright (c) 2018 Intel Corporation
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
16#pragma once
17
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080018#include "app.hpp"
Jonathan Doman1e1e5982021-06-11 09:36:17 -070019#include "dbus_singleton.hpp"
George Liu7a1dbc42022-12-07 16:03:22 +080020#include "dbus_utility.hpp"
Jonathan Doman1e1e5982021-06-11 09:36:17 -070021#include "error_messages.hpp"
Gunnar Millsac6a4442020-10-14 14:55:29 -050022#include "health.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080023#include "query.hpp"
24#include "registries/privilege_registry.hpp"
25#include "utils/collection.hpp"
26#include "utils/dbus_utils.hpp"
27#include "utils/json_utils.hpp"
Gunnar Millsac6a4442020-10-14 14:55:29 -050028
29#include <boost/container/flat_map.hpp>
George Liue99073f2022-12-09 11:06:16 +080030#include <boost/system/error_code.hpp>
Ed Tanousef4c65b2023-04-24 15:28:50 -070031#include <boost/url/format.hpp>
Jonathan Doman1e1e5982021-06-11 09:36:17 -070032#include <sdbusplus/asio/property.hpp>
Jonathan Domandba0c292020-12-02 15:34:13 -080033#include <sdbusplus/message/native_types.hpp>
Krzysztof Grobelny351053f2022-07-28 15:44:22 +020034#include <sdbusplus/unpack_properties.hpp>
Jonathan Domandba0c292020-12-02 15:34:13 -080035#include <sdbusplus/utility/dedup_variant.hpp>
Gunnar Millsac6a4442020-10-14 14:55:29 -050036
George Liu7a1dbc42022-12-07 16:03:22 +080037#include <array>
Michael Shenb9d679d2023-02-13 02:29:04 +000038#include <limits>
George Liu7a1dbc42022-12-07 16:03:22 +080039#include <string_view>
40
Gunnar Millsac6a4442020-10-14 14:55:29 -050041namespace redfish
42{
43
Jonathan Domanc9514482021-02-24 09:20:51 -080044// Interfaces which imply a D-Bus object represents a Processor
George Liu7a1dbc42022-12-07 16:03:22 +080045constexpr std::array<std::string_view, 2> processorInterfaces = {
Jonathan Domanc9514482021-02-24 09:20:51 -080046 "xyz.openbmc_project.Inventory.Item.Cpu",
47 "xyz.openbmc_project.Inventory.Item.Accelerator"};
Jonathan Doman2bab9832020-12-02 15:27:40 -080048
Sharad Yadav71b82f22021-05-10 15:11:39 +053049/**
50 * @brief Fill out uuid info of a processor by
51 * requesting data from the given D-Bus object.
52 *
53 * @param[in,out] aResp Async HTTP response.
54 * @param[in] service D-Bus service to query.
55 * @param[in] objPath D-Bus object to query.
56 */
57inline void getProcessorUUID(std::shared_ptr<bmcweb::AsyncResp> aResp,
58 const std::string& service,
59 const std::string& objPath)
60{
61 BMCWEB_LOG_DEBUG << "Get Processor UUID";
Jonathan Doman1e1e5982021-06-11 09:36:17 -070062 sdbusplus::asio::getProperty<std::string>(
63 *crow::connections::systemBus, service, objPath,
64 "xyz.openbmc_project.Common.UUID", "UUID",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -080065 [objPath, aResp{std::move(aResp)}](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -070066 const std::string& property) {
Ed Tanous002d39b2022-05-31 08:59:27 -070067 if (ec)
68 {
69 BMCWEB_LOG_DEBUG << "DBUS response error";
70 messages::internalError(aResp->res);
71 return;
72 }
73 aResp->res.jsonValue["UUID"] = property;
Jonathan Doman1e1e5982021-06-11 09:36:17 -070074 });
Sharad Yadav71b82f22021-05-10 15:11:39 +053075}
76
Ed Tanous711ac7a2021-12-20 09:34:41 -080077inline void getCpuDataByInterface(
78 const std::shared_ptr<bmcweb::AsyncResp>& aResp,
79 const dbus::utility::DBusInteracesMap& cpuInterfacesProperties)
Gunnar Millsac6a4442020-10-14 14:55:29 -050080{
81 BMCWEB_LOG_DEBUG << "Get CPU resources by interface.";
82
Chicago Duana1649ec2021-03-30 16:54:58 +080083 // Set the default value of state
84 aResp->res.jsonValue["Status"]["State"] = "Enabled";
85 aResp->res.jsonValue["Status"]["Health"] = "OK";
Gunnar Millsac6a4442020-10-14 14:55:29 -050086
87 for (const auto& interface : cpuInterfacesProperties)
88 {
89 for (const auto& property : interface.second)
90 {
Chicago Duana1649ec2021-03-30 16:54:58 +080091 if (property.first == "Present")
Gunnar Millsac6a4442020-10-14 14:55:29 -050092 {
Chicago Duana1649ec2021-03-30 16:54:58 +080093 const bool* cpuPresent = std::get_if<bool>(&property.second);
94 if (cpuPresent == nullptr)
Gunnar Millsac6a4442020-10-14 14:55:29 -050095 {
96 // Important property not in desired type
97 messages::internalError(aResp->res);
98 return;
99 }
Ed Tanouse05aec52022-01-25 10:28:56 -0800100 if (!*cpuPresent)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500101 {
Chicago Duana1649ec2021-03-30 16:54:58 +0800102 // Slot is not populated
Gunnar Millsac6a4442020-10-14 14:55:29 -0500103 aResp->res.jsonValue["Status"]["State"] = "Absent";
Chicago Duana1649ec2021-03-30 16:54:58 +0800104 }
105 }
106 else if (property.first == "Functional")
107 {
108 const bool* cpuFunctional = std::get_if<bool>(&property.second);
109 if (cpuFunctional == nullptr)
110 {
111 messages::internalError(aResp->res);
Gunnar Millsac6a4442020-10-14 14:55:29 -0500112 return;
113 }
Ed Tanouse05aec52022-01-25 10:28:56 -0800114 if (!*cpuFunctional)
Chicago Duana1649ec2021-03-30 16:54:58 +0800115 {
116 aResp->res.jsonValue["Status"]["Health"] = "Critical";
117 }
118 }
119 else if (property.first == "CoreCount")
120 {
121 const uint16_t* coresCount =
122 std::get_if<uint16_t>(&property.second);
123 if (coresCount == nullptr)
124 {
125 messages::internalError(aResp->res);
126 return;
127 }
Gunnar Millsac6a4442020-10-14 14:55:29 -0500128 aResp->res.jsonValue["TotalCores"] = *coresCount;
129 }
Jonathan Domandc3fa662020-10-26 23:10:24 -0700130 else if (property.first == "MaxSpeedInMhz")
131 {
132 const uint32_t* value = std::get_if<uint32_t>(&property.second);
133 if (value != nullptr)
134 {
135 aResp->res.jsonValue["MaxSpeedMHz"] = *value;
136 }
137 }
Gunnar Millsac6a4442020-10-14 14:55:29 -0500138 else if (property.first == "Socket")
139 {
140 const std::string* value =
141 std::get_if<std::string>(&property.second);
142 if (value != nullptr)
143 {
144 aResp->res.jsonValue["Socket"] = *value;
145 }
146 }
147 else if (property.first == "ThreadCount")
148 {
Jonathan Domandc3fa662020-10-26 23:10:24 -0700149 const uint16_t* value = std::get_if<uint16_t>(&property.second);
Gunnar Millsac6a4442020-10-14 14:55:29 -0500150 if (value != nullptr)
151 {
152 aResp->res.jsonValue["TotalThreads"] = *value;
153 }
154 }
Brandon Kim1930fbd2021-09-14 17:52:51 -0700155 else if (property.first == "EffectiveFamily")
Gunnar Millsac6a4442020-10-14 14:55:29 -0500156 {
Brandon Kim1930fbd2021-09-14 17:52:51 -0700157 const uint16_t* value = std::get_if<uint16_t>(&property.second);
Brad Bishop6169de22022-09-14 13:08:32 -0400158 if (value != nullptr && *value != 2)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500159 {
160 aResp->res.jsonValue["ProcessorId"]["EffectiveFamily"] =
Ed Tanous866e4862022-02-17 11:40:25 -0800161 "0x" + intToHexString(*value, 4);
Gunnar Millsac6a4442020-10-14 14:55:29 -0500162 }
163 }
Brandon Kim1930fbd2021-09-14 17:52:51 -0700164 else if (property.first == "EffectiveModel")
165 {
166 const uint16_t* value = std::get_if<uint16_t>(&property.second);
167 if (value == nullptr)
168 {
169 messages::internalError(aResp->res);
170 return;
171 }
Brad Bishop6169de22022-09-14 13:08:32 -0400172 if (*value != 0)
173 {
174 aResp->res.jsonValue["ProcessorId"]["EffectiveModel"] =
175 "0x" + intToHexString(*value, 4);
176 }
Brandon Kim1930fbd2021-09-14 17:52:51 -0700177 }
Gunnar Millsac6a4442020-10-14 14:55:29 -0500178 else if (property.first == "Id")
179 {
180 const uint64_t* value = std::get_if<uint64_t>(&property.second);
181 if (value != nullptr && *value != 0)
182 {
Gunnar Millsac6a4442020-10-14 14:55:29 -0500183 aResp->res
184 .jsonValue["ProcessorId"]["IdentificationRegisters"] =
Ed Tanous866e4862022-02-17 11:40:25 -0800185 "0x" + intToHexString(*value, 16);
Gunnar Millsac6a4442020-10-14 14:55:29 -0500186 }
187 }
Brandon Kim1930fbd2021-09-14 17:52:51 -0700188 else if (property.first == "Microcode")
189 {
190 const uint32_t* value = std::get_if<uint32_t>(&property.second);
191 if (value == nullptr)
192 {
193 messages::internalError(aResp->res);
194 return;
195 }
Brad Bishop6169de22022-09-14 13:08:32 -0400196 if (*value != 0)
197 {
198 aResp->res.jsonValue["ProcessorId"]["MicrocodeInfo"] =
199 "0x" + intToHexString(*value, 8);
200 }
Brandon Kim1930fbd2021-09-14 17:52:51 -0700201 }
202 else if (property.first == "Step")
203 {
204 const uint16_t* value = std::get_if<uint16_t>(&property.second);
205 if (value == nullptr)
206 {
207 messages::internalError(aResp->res);
208 return;
209 }
Michael Shenb9d679d2023-02-13 02:29:04 +0000210 if (*value != std::numeric_limits<uint16_t>::max())
Brad Bishop6169de22022-09-14 13:08:32 -0400211 {
212 aResp->res.jsonValue["ProcessorId"]["Step"] =
213 "0x" + intToHexString(*value, 4);
214 }
Brandon Kim1930fbd2021-09-14 17:52:51 -0700215 }
Gunnar Millsac6a4442020-10-14 14:55:29 -0500216 }
217 }
Gunnar Millsac6a4442020-10-14 14:55:29 -0500218}
219
zhanghch058d1b46d2021-04-01 11:18:24 +0800220inline void getCpuDataByService(std::shared_ptr<bmcweb::AsyncResp> aResp,
Gunnar Millsac6a4442020-10-14 14:55:29 -0500221 const std::string& cpuId,
222 const std::string& service,
223 const std::string& objPath)
224{
225 BMCWEB_LOG_DEBUG << "Get available system cpu resources by service.";
226
227 crow::connections::systemBus->async_method_call(
228 [cpuId, service, objPath, aResp{std::move(aResp)}](
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800229 const boost::system::error_code& ec,
Gunnar Millsac6a4442020-10-14 14:55:29 -0500230 const dbus::utility::ManagedObjectType& dbusData) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700231 if (ec)
232 {
233 BMCWEB_LOG_DEBUG << "DBUS response error";
234 messages::internalError(aResp->res);
235 return;
236 }
237 aResp->res.jsonValue["Id"] = cpuId;
238 aResp->res.jsonValue["Name"] = "Processor";
239 aResp->res.jsonValue["ProcessorType"] = "CPU";
Gunnar Millsac6a4442020-10-14 14:55:29 -0500240
Ed Tanous002d39b2022-05-31 08:59:27 -0700241 bool slotPresent = false;
242 std::string corePath = objPath + "/core";
243 size_t totalCores = 0;
244 for (const auto& object : dbusData)
245 {
246 if (object.first.str == objPath)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500247 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700248 getCpuDataByInterface(aResp, object.second);
249 }
Ed Tanous11ba3972022-07-11 09:50:41 -0700250 else if (object.first.str.starts_with(corePath))
Ed Tanous002d39b2022-05-31 08:59:27 -0700251 {
252 for (const auto& interface : object.second)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500253 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700254 if (interface.first == "xyz.openbmc_project.Inventory.Item")
Gunnar Millsac6a4442020-10-14 14:55:29 -0500255 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700256 for (const auto& property : interface.second)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500257 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700258 if (property.first == "Present")
Gunnar Millsac6a4442020-10-14 14:55:29 -0500259 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700260 const bool* present =
261 std::get_if<bool>(&property.second);
262 if (present != nullptr)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500263 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700264 if (*present)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500265 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700266 slotPresent = true;
267 totalCores++;
Gunnar Millsac6a4442020-10-14 14:55:29 -0500268 }
269 }
270 }
271 }
272 }
273 }
274 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700275 }
276 // In getCpuDataByInterface(), state and health are set
277 // based on the present and functional status. If core
278 // count is zero, then it has a higher precedence.
279 if (slotPresent)
280 {
281 if (totalCores == 0)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500282 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700283 // Slot is not populated, set status end return
284 aResp->res.jsonValue["Status"]["State"] = "Absent";
285 aResp->res.jsonValue["Status"]["Health"] = "OK";
Gunnar Millsac6a4442020-10-14 14:55:29 -0500286 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700287 aResp->res.jsonValue["TotalCores"] = totalCores;
288 }
289 return;
Gunnar Millsac6a4442020-10-14 14:55:29 -0500290 },
291 service, "/xyz/openbmc_project/inventory",
292 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
293}
294
zhanghch058d1b46d2021-04-01 11:18:24 +0800295inline void getCpuAssetData(std::shared_ptr<bmcweb::AsyncResp> aResp,
Gunnar Millsac6a4442020-10-14 14:55:29 -0500296 const std::string& service,
297 const std::string& objPath)
298{
299 BMCWEB_LOG_DEBUG << "Get Cpu Asset Data";
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200300 sdbusplus::asio::getAllProperties(
301 *crow::connections::systemBus, service, objPath,
302 "xyz.openbmc_project.Inventory.Decorator.Asset",
Gunnar Millsac6a4442020-10-14 14:55:29 -0500303 [objPath, aResp{std::move(aResp)}](
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800304 const boost::system::error_code& ec,
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200305 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700306 if (ec)
307 {
308 BMCWEB_LOG_DEBUG << "DBUS response error";
309 messages::internalError(aResp->res);
310 return;
311 }
312
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200313 const std::string* serialNumber = nullptr;
314 const std::string* model = nullptr;
315 const std::string* manufacturer = nullptr;
316 const std::string* partNumber = nullptr;
317 const std::string* sparePartNumber = nullptr;
318
319 const bool success = sdbusplus::unpackPropertiesNoThrow(
320 dbus_utils::UnpackErrorPrinter(), properties, "SerialNumber",
321 serialNumber, "Model", model, "Manufacturer", manufacturer,
322 "PartNumber", partNumber, "SparePartNumber", sparePartNumber);
323
324 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -0700325 {
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200326 messages::internalError(aResp->res);
327 return;
328 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700329
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200330 if (serialNumber != nullptr && !serialNumber->empty())
331 {
332 aResp->res.jsonValue["SerialNumber"] = *serialNumber;
333 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700334
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200335 if ((model != nullptr) && !model->empty())
336 {
337 aResp->res.jsonValue["Model"] = *model;
338 }
339
340 if (manufacturer != nullptr)
341 {
342 aResp->res.jsonValue["Manufacturer"] = *manufacturer;
343
344 // Otherwise would be unexpected.
345 if (manufacturer->find("Intel") != std::string::npos)
Ed Tanous002d39b2022-05-31 08:59:27 -0700346 {
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200347 aResp->res.jsonValue["ProcessorArchitecture"] = "x86";
348 aResp->res.jsonValue["InstructionSet"] = "x86-64";
Ed Tanous002d39b2022-05-31 08:59:27 -0700349 }
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200350 else if (manufacturer->find("IBM") != std::string::npos)
Ed Tanous002d39b2022-05-31 08:59:27 -0700351 {
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200352 aResp->res.jsonValue["ProcessorArchitecture"] = "Power";
353 aResp->res.jsonValue["InstructionSet"] = "PowerISA";
Ed Tanous002d39b2022-05-31 08:59:27 -0700354 }
355 }
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200356
357 if (partNumber != nullptr)
358 {
359 aResp->res.jsonValue["PartNumber"] = *partNumber;
360 }
361
Brad Bishop6169de22022-09-14 13:08:32 -0400362 if (sparePartNumber != nullptr && !sparePartNumber->empty())
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200363 {
364 aResp->res.jsonValue["SparePartNumber"] = *sparePartNumber;
365 }
366 });
Gunnar Millsac6a4442020-10-14 14:55:29 -0500367}
368
zhanghch058d1b46d2021-04-01 11:18:24 +0800369inline void getCpuRevisionData(std::shared_ptr<bmcweb::AsyncResp> aResp,
Gunnar Millsac6a4442020-10-14 14:55:29 -0500370 const std::string& service,
371 const std::string& objPath)
372{
373 BMCWEB_LOG_DEBUG << "Get Cpu Revision Data";
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200374 sdbusplus::asio::getAllProperties(
375 *crow::connections::systemBus, service, objPath,
376 "xyz.openbmc_project.Inventory.Decorator.Revision",
Gunnar Millsac6a4442020-10-14 14:55:29 -0500377 [objPath, aResp{std::move(aResp)}](
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800378 const boost::system::error_code& ec,
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200379 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700380 if (ec)
381 {
382 BMCWEB_LOG_DEBUG << "DBUS response error";
383 messages::internalError(aResp->res);
384 return;
385 }
Gunnar Millsac6a4442020-10-14 14:55:29 -0500386
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200387 const std::string* version = nullptr;
388
389 const bool success = sdbusplus::unpackPropertiesNoThrow(
390 dbus_utils::UnpackErrorPrinter(), properties, "Version", version);
391
392 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -0700393 {
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200394 messages::internalError(aResp->res);
395 return;
Ed Tanous002d39b2022-05-31 08:59:27 -0700396 }
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200397
398 if (version != nullptr)
399 {
400 aResp->res.jsonValue["Version"] = *version;
401 }
402 });
Gunnar Millsac6a4442020-10-14 14:55:29 -0500403}
404
zhanghch058d1b46d2021-04-01 11:18:24 +0800405inline void getAcceleratorDataByService(
406 std::shared_ptr<bmcweb::AsyncResp> aResp, const std::string& acclrtrId,
407 const std::string& service, const std::string& objPath)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500408{
409 BMCWEB_LOG_DEBUG
410 << "Get available system Accelerator resources by service.";
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200411 sdbusplus::asio::getAllProperties(
412 *crow::connections::systemBus, service, objPath, "",
Gunnar Millsac6a4442020-10-14 14:55:29 -0500413 [acclrtrId, aResp{std::move(aResp)}](
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800414 const boost::system::error_code& ec,
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200415 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700416 if (ec)
417 {
418 BMCWEB_LOG_DEBUG << "DBUS response error";
419 messages::internalError(aResp->res);
420 return;
421 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700422
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200423 const bool* functional = nullptr;
424 const bool* present = nullptr;
425
426 const bool success = sdbusplus::unpackPropertiesNoThrow(
427 dbus_utils::UnpackErrorPrinter(), properties, "Functional",
428 functional, "Present", present);
429
430 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -0700431 {
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200432 messages::internalError(aResp->res);
433 return;
Ed Tanous002d39b2022-05-31 08:59:27 -0700434 }
Gunnar Millsac6a4442020-10-14 14:55:29 -0500435
Ed Tanous002d39b2022-05-31 08:59:27 -0700436 std::string state = "Enabled";
437 std::string health = "OK";
Gunnar Millsac6a4442020-10-14 14:55:29 -0500438
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200439 if (present != nullptr && !*present)
Ed Tanous002d39b2022-05-31 08:59:27 -0700440 {
441 state = "Absent";
442 }
443
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200444 if (functional != nullptr && !*functional)
Ed Tanous002d39b2022-05-31 08:59:27 -0700445 {
446 if (state == "Enabled")
Gunnar Millsac6a4442020-10-14 14:55:29 -0500447 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700448 health = "Critical";
Gunnar Millsac6a4442020-10-14 14:55:29 -0500449 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700450 }
Gunnar Millsac6a4442020-10-14 14:55:29 -0500451
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200452 aResp->res.jsonValue["Id"] = acclrtrId;
453 aResp->res.jsonValue["Name"] = "Processor";
Ed Tanous002d39b2022-05-31 08:59:27 -0700454 aResp->res.jsonValue["Status"]["State"] = state;
455 aResp->res.jsonValue["Status"]["Health"] = health;
456 aResp->res.jsonValue["ProcessorType"] = "Accelerator";
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200457 });
Gunnar Millsac6a4442020-10-14 14:55:29 -0500458}
459
Jonathan Domandba0c292020-12-02 15:34:13 -0800460// OperatingConfig D-Bus Types
461using TurboProfileProperty = std::vector<std::tuple<uint32_t, size_t>>;
462using BaseSpeedPrioritySettingsProperty =
463 std::vector<std::tuple<uint32_t, std::vector<uint32_t>>>;
464// uint32_t and size_t may or may not be the same type, requiring a dedup'd
465// variant
Jonathan Domandba0c292020-12-02 15:34:13 -0800466
467/**
468 * Fill out the HighSpeedCoreIDs in a Processor resource from the given
469 * OperatingConfig D-Bus property.
470 *
471 * @param[in,out] aResp Async HTTP response.
472 * @param[in] baseSpeedSettings Full list of base speed priority groups,
473 * to use to determine the list of high
474 * speed cores.
475 */
476inline void highSpeedCoreIdsHandler(
zhanghch058d1b46d2021-04-01 11:18:24 +0800477 const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Jonathan Domandba0c292020-12-02 15:34:13 -0800478 const BaseSpeedPrioritySettingsProperty& baseSpeedSettings)
479{
480 // The D-Bus property does not indicate which bucket is the "high
481 // priority" group, so let's discern that by looking for the one with
482 // highest base frequency.
483 auto highPriorityGroup = baseSpeedSettings.cend();
484 uint32_t highestBaseSpeed = 0;
485 for (auto it = baseSpeedSettings.cbegin(); it != baseSpeedSettings.cend();
486 ++it)
487 {
488 const uint32_t baseFreq = std::get<uint32_t>(*it);
489 if (baseFreq > highestBaseSpeed)
490 {
491 highestBaseSpeed = baseFreq;
492 highPriorityGroup = it;
493 }
494 }
495
496 nlohmann::json& jsonCoreIds = aResp->res.jsonValue["HighSpeedCoreIDs"];
497 jsonCoreIds = nlohmann::json::array();
498
499 // There may not be any entries in the D-Bus property, so only populate
500 // if there was actually something there.
501 if (highPriorityGroup != baseSpeedSettings.cend())
502 {
503 jsonCoreIds = std::get<std::vector<uint32_t>>(*highPriorityGroup);
504 }
505}
506
507/**
508 * Fill out OperatingConfig related items in a Processor resource by requesting
509 * data from the given D-Bus object.
510 *
511 * @param[in,out] aResp Async HTTP response.
512 * @param[in] cpuId CPU D-Bus name.
513 * @param[in] service D-Bus service to query.
514 * @param[in] objPath D-Bus object to query.
515 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800516inline void getCpuConfigData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Jonathan Domandba0c292020-12-02 15:34:13 -0800517 const std::string& cpuId,
518 const std::string& service,
519 const std::string& objPath)
520{
521 BMCWEB_LOG_INFO << "Getting CPU operating configs for " << cpuId;
522
523 // First, GetAll CurrentOperatingConfig properties on the object
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200524 sdbusplus::asio::getAllProperties(
525 *crow::connections::systemBus, service, objPath,
526 "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig",
527 [aResp, cpuId,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800528 service](const boost::system::error_code& ec,
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200529 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700530 if (ec)
531 {
532 BMCWEB_LOG_WARNING << "D-Bus error: " << ec << ", " << ec.message();
533 messages::internalError(aResp->res);
534 return;
535 }
Jonathan Domandba0c292020-12-02 15:34:13 -0800536
Ed Tanous002d39b2022-05-31 08:59:27 -0700537 nlohmann::json& json = aResp->res.jsonValue;
Jonathan Domandba0c292020-12-02 15:34:13 -0800538
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200539 const sdbusplus::message::object_path* appliedConfig = nullptr;
540 const bool* baseSpeedPriorityEnabled = nullptr;
541
542 const bool success = sdbusplus::unpackPropertiesNoThrow(
543 dbus_utils::UnpackErrorPrinter(), properties, "AppliedConfig",
544 appliedConfig, "BaseSpeedPriorityEnabled",
545 baseSpeedPriorityEnabled);
546
547 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -0700548 {
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200549 messages::internalError(aResp->res);
550 return;
Ed Tanous002d39b2022-05-31 08:59:27 -0700551 }
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200552
553 if (appliedConfig != nullptr)
554 {
555 const std::string& dbusPath = appliedConfig->str;
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200556 nlohmann::json::object_t operatingConfig;
Ed Tanousef4c65b2023-04-24 15:28:50 -0700557 operatingConfig["@odata.id"] = boost::urls::format(
558 "/redfish/v1/Systems/system/Processors/{}/OperatingConfigs",
559 cpuId);
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200560 json["OperatingConfigs"] = std::move(operatingConfig);
561
562 // Reuse the D-Bus config object name for the Redfish
563 // URI
564 size_t baseNamePos = dbusPath.rfind('/');
565 if (baseNamePos == std::string::npos ||
566 baseNamePos == (dbusPath.size() - 1))
567 {
568 // If the AppliedConfig was somehow not a valid path,
569 // skip adding any more properties, since everything
570 // else is tied to this applied config.
571 messages::internalError(aResp->res);
572 return;
573 }
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200574 nlohmann::json::object_t appliedOperatingConfig;
Ed Tanousef4c65b2023-04-24 15:28:50 -0700575 appliedOperatingConfig["@odata.id"] = boost::urls::format(
576 "/redfish/v1/Systems/system/Processors/{}/OperatingConfigs/{}",
577 cpuId, dbusPath.substr(baseNamePos + 1));
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200578 json["AppliedOperatingConfig"] = std::move(appliedOperatingConfig);
579
580 // Once we found the current applied config, queue another
581 // request to read the base freq core ids out of that
582 // config.
583 sdbusplus::asio::getProperty<BaseSpeedPrioritySettingsProperty>(
584 *crow::connections::systemBus, service, dbusPath,
585 "xyz.openbmc_project.Inventory.Item.Cpu."
586 "OperatingConfig",
587 "BaseSpeedPrioritySettings",
588 [aResp](
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800589 const boost::system::error_code& ec2,
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200590 const BaseSpeedPrioritySettingsProperty& baseSpeedList) {
591 if (ec2)
592 {
593 BMCWEB_LOG_WARNING << "D-Bus Property Get error: " << ec2;
594 messages::internalError(aResp->res);
595 return;
596 }
597
598 highSpeedCoreIdsHandler(aResp, baseSpeedList);
599 });
600 }
601
602 if (baseSpeedPriorityEnabled != nullptr)
603 {
604 json["BaseSpeedPriorityState"] =
605 *baseSpeedPriorityEnabled ? "Enabled" : "Disabled";
606 }
607 });
Jonathan Domandba0c292020-12-02 15:34:13 -0800608}
609
SunnySrivastava1984cba4f442021-01-07 12:48:16 -0600610/**
611 * @brief Fill out location info of a processor by
612 * requesting data from the given D-Bus object.
613 *
614 * @param[in,out] aResp Async HTTP response.
615 * @param[in] service D-Bus service to query.
616 * @param[in] objPath D-Bus object to query.
617 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800618inline void getCpuLocationCode(std::shared_ptr<bmcweb::AsyncResp> aResp,
SunnySrivastava1984cba4f442021-01-07 12:48:16 -0600619 const std::string& service,
620 const std::string& objPath)
621{
622 BMCWEB_LOG_DEBUG << "Get Cpu Location Data";
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700623 sdbusplus::asio::getProperty<std::string>(
624 *crow::connections::systemBus, service, objPath,
625 "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800626 [objPath, aResp{std::move(aResp)}](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700627 const std::string& property) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700628 if (ec)
629 {
630 BMCWEB_LOG_DEBUG << "DBUS response error";
631 messages::internalError(aResp->res);
632 return;
633 }
SunnySrivastava1984cba4f442021-01-07 12:48:16 -0600634
Ed Tanous002d39b2022-05-31 08:59:27 -0700635 aResp->res.jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
636 property;
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700637 });
SunnySrivastava1984cba4f442021-01-07 12:48:16 -0600638}
639
Jonathan Domanc9514482021-02-24 09:20:51 -0800640/**
Jonathan Doman49e429c2021-03-03 13:11:44 -0800641 * Populate the unique identifier in a Processor resource by requesting data
642 * from the given D-Bus object.
643 *
644 * @param[in,out] aResp Async HTTP response.
645 * @param[in] service D-Bus service to query.
646 * @param[in] objPath D-Bus object to query.
647 */
648inline void getCpuUniqueId(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
649 const std::string& service,
650 const std::string& objectPath)
651{
652 BMCWEB_LOG_DEBUG << "Get CPU UniqueIdentifier";
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700653 sdbusplus::asio::getProperty<std::string>(
654 *crow::connections::systemBus, service, objectPath,
655 "xyz.openbmc_project.Inventory.Decorator.UniqueIdentifier",
656 "UniqueIdentifier",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800657 [aResp](const boost::system::error_code& ec, const std::string& id) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700658 if (ec)
659 {
660 BMCWEB_LOG_ERROR << "Failed to read cpu unique id: " << ec;
661 messages::internalError(aResp->res);
662 return;
663 }
664 aResp->res.jsonValue["ProcessorId"]["ProtectedIdentificationNumber"] =
665 id;
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700666 });
Jonathan Doman49e429c2021-03-03 13:11:44 -0800667}
668
669/**
Jonathan Domanc9514482021-02-24 09:20:51 -0800670 * Find the D-Bus object representing the requested Processor, and call the
671 * handler with the results. If matching object is not found, add 404 error to
672 * response and don't call the handler.
673 *
674 * @param[in,out] resp Async HTTP response.
675 * @param[in] processorId Redfish Processor Id.
676 * @param[in] handler Callback to continue processing request upon
677 * successfully finding object.
678 */
679template <typename Handler>
zhanghch058d1b46d2021-04-01 11:18:24 +0800680inline void getProcessorObject(const std::shared_ptr<bmcweb::AsyncResp>& resp,
Jonathan Domanc9514482021-02-24 09:20:51 -0800681 const std::string& processorId,
682 Handler&& handler)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500683{
684 BMCWEB_LOG_DEBUG << "Get available system processor resources.";
685
Jonathan Domanc9514482021-02-24 09:20:51 -0800686 // GetSubTree on all interfaces which provide info about a Processor
George Liue99073f2022-12-09 11:06:16 +0800687 constexpr std::array<std::string_view, 8> interfaces = {
688 "xyz.openbmc_project.Common.UUID",
689 "xyz.openbmc_project.Inventory.Decorator.Asset",
690 "xyz.openbmc_project.Inventory.Decorator.Revision",
691 "xyz.openbmc_project.Inventory.Item.Cpu",
692 "xyz.openbmc_project.Inventory.Decorator.LocationCode",
693 "xyz.openbmc_project.Inventory.Item.Accelerator",
694 "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig",
695 "xyz.openbmc_project.Inventory.Decorator.UniqueIdentifier"};
696 dbus::utility::getSubTree(
697 "/xyz/openbmc_project/inventory", 0, interfaces,
Jonathan Domanc9514482021-02-24 09:20:51 -0800698 [resp, processorId, handler = std::forward<Handler>(handler)](
George Liue99073f2022-12-09 11:06:16 +0800699 const boost::system::error_code& ec,
700 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700701 if (ec)
702 {
703 BMCWEB_LOG_DEBUG << "DBUS response error: " << ec;
704 messages::internalError(resp->res);
705 return;
706 }
707 for (const auto& [objectPath, serviceMap] : subtree)
708 {
709 // Ignore any objects which don't end with our desired cpu name
Ed Tanous11ba3972022-07-11 09:50:41 -0700710 if (!objectPath.ends_with(processorId))
Gunnar Millsac6a4442020-10-14 14:55:29 -0500711 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700712 continue;
Gunnar Millsac6a4442020-10-14 14:55:29 -0500713 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700714
715 bool found = false;
716 // Filter out objects that don't have the CPU-specific
717 // interfaces to make sure we can return 404 on non-CPUs
718 // (e.g. /redfish/../Processors/dimm0)
719 for (const auto& [serviceName, interfaceList] : serviceMap)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500720 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700721 if (std::find_first_of(
722 interfaceList.begin(), interfaceList.end(),
723 processorInterfaces.begin(),
724 processorInterfaces.end()) != interfaceList.end())
Gunnar Millsac6a4442020-10-14 14:55:29 -0500725 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700726 found = true;
727 break;
Jonathan Doman2bab9832020-12-02 15:27:40 -0800728 }
Gunnar Millsac6a4442020-10-14 14:55:29 -0500729 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700730
731 if (!found)
732 {
733 continue;
734 }
735
736 // Process the first object which does match our cpu name and
737 // required interfaces, and potentially ignore any other
738 // matching objects. Assume all interfaces we want to process
739 // must be on the same object path.
740
Ed Tanous8a592812022-06-04 09:06:59 -0700741 handler(objectPath, serviceMap);
Ed Tanous002d39b2022-05-31 08:59:27 -0700742 return;
743 }
744 messages::resourceNotFound(resp->res, "Processor", processorId);
George Liue99073f2022-12-09 11:06:16 +0800745 });
Gunnar Millsac6a4442020-10-14 14:55:29 -0500746}
747
zhanghch058d1b46d2021-04-01 11:18:24 +0800748inline void getProcessorData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Jonathan Domanc9514482021-02-24 09:20:51 -0800749 const std::string& processorId,
750 const std::string& objectPath,
Shantappa Teekappanavar5df6eda2022-01-18 12:29:28 -0600751 const dbus::utility::MapperServiceMap& serviceMap)
Jonathan Domanc9514482021-02-24 09:20:51 -0800752{
753 for (const auto& [serviceName, interfaceList] : serviceMap)
754 {
755 for (const auto& interface : interfaceList)
756 {
757 if (interface == "xyz.openbmc_project.Inventory.Decorator.Asset")
758 {
759 getCpuAssetData(aResp, serviceName, objectPath);
760 }
George Liu0fda0f12021-11-16 10:06:17 +0800761 else if (interface ==
762 "xyz.openbmc_project.Inventory.Decorator.Revision")
Jonathan Domanc9514482021-02-24 09:20:51 -0800763 {
764 getCpuRevisionData(aResp, serviceName, objectPath);
765 }
766 else if (interface == "xyz.openbmc_project.Inventory.Item.Cpu")
767 {
768 getCpuDataByService(aResp, processorId, serviceName,
769 objectPath);
770 }
George Liu0fda0f12021-11-16 10:06:17 +0800771 else if (interface ==
772 "xyz.openbmc_project.Inventory.Item.Accelerator")
Jonathan Domanc9514482021-02-24 09:20:51 -0800773 {
774 getAcceleratorDataByService(aResp, processorId, serviceName,
775 objectPath);
776 }
George Liu0fda0f12021-11-16 10:06:17 +0800777 else if (
778 interface ==
779 "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig")
Jonathan Domanc9514482021-02-24 09:20:51 -0800780 {
781 getCpuConfigData(aResp, processorId, serviceName, objectPath);
782 }
George Liu0fda0f12021-11-16 10:06:17 +0800783 else if (interface ==
784 "xyz.openbmc_project.Inventory.Decorator.LocationCode")
Jonathan Domanc9514482021-02-24 09:20:51 -0800785 {
786 getCpuLocationCode(aResp, serviceName, objectPath);
787 }
Sharad Yadav71b82f22021-05-10 15:11:39 +0530788 else if (interface == "xyz.openbmc_project.Common.UUID")
789 {
790 getProcessorUUID(aResp, serviceName, objectPath);
791 }
George Liu0fda0f12021-11-16 10:06:17 +0800792 else if (interface ==
793 "xyz.openbmc_project.Inventory.Decorator.UniqueIdentifier")
Jonathan Doman49e429c2021-03-03 13:11:44 -0800794 {
795 getCpuUniqueId(aResp, serviceName, objectPath);
796 }
Jonathan Domanc9514482021-02-24 09:20:51 -0800797 }
798 }
799}
800
Jonathan Domandba0c292020-12-02 15:34:13 -0800801/**
802 * Request all the properties for the given D-Bus object and fill out the
803 * related entries in the Redfish OperatingConfig response.
804 *
805 * @param[in,out] aResp Async HTTP response.
806 * @param[in] service D-Bus service name to query.
807 * @param[in] objPath D-Bus object to query.
808 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800809inline void
810 getOperatingConfigData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
811 const std::string& service,
812 const std::string& objPath)
Jonathan Domandba0c292020-12-02 15:34:13 -0800813{
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200814 sdbusplus::asio::getAllProperties(
815 *crow::connections::systemBus, service, objPath,
816 "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800817 [aResp](const boost::system::error_code& ec,
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200818 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700819 if (ec)
820 {
821 BMCWEB_LOG_WARNING << "D-Bus error: " << ec << ", " << ec.message();
822 messages::internalError(aResp->res);
823 return;
824 }
825
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200826 const size_t* availableCoreCount = nullptr;
827 const uint32_t* baseSpeed = nullptr;
828 const uint32_t* maxJunctionTemperature = nullptr;
829 const uint32_t* maxSpeed = nullptr;
830 const uint32_t* powerLimit = nullptr;
831 const TurboProfileProperty* turboProfile = nullptr;
832 const BaseSpeedPrioritySettingsProperty* baseSpeedPrioritySettings =
833 nullptr;
834
835 const bool success = sdbusplus::unpackPropertiesNoThrow(
836 dbus_utils::UnpackErrorPrinter(), properties, "AvailableCoreCount",
837 availableCoreCount, "BaseSpeed", baseSpeed,
838 "MaxJunctionTemperature", maxJunctionTemperature, "MaxSpeed",
839 maxSpeed, "PowerLimit", powerLimit, "TurboProfile", turboProfile,
840 "BaseSpeedPrioritySettings", baseSpeedPrioritySettings);
841
842 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -0700843 {
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200844 messages::internalError(aResp->res);
845 return;
846 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700847
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200848 nlohmann::json& json = aResp->res.jsonValue;
Ed Tanous002d39b2022-05-31 08:59:27 -0700849
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200850 if (availableCoreCount != nullptr)
851 {
852 json["TotalAvailableCoreCount"] = *availableCoreCount;
853 }
854
855 if (baseSpeed != nullptr)
856 {
857 json["BaseSpeedMHz"] = *baseSpeed;
858 }
859
860 if (maxJunctionTemperature != nullptr)
861 {
862 json["MaxJunctionTemperatureCelsius"] = *maxJunctionTemperature;
863 }
864
865 if (maxSpeed != nullptr)
866 {
867 json["MaxSpeedMHz"] = *maxSpeed;
868 }
869
870 if (powerLimit != nullptr)
871 {
872 json["TDPWatts"] = *powerLimit;
873 }
874
875 if (turboProfile != nullptr)
876 {
877 nlohmann::json& turboArray = json["TurboProfile"];
878 turboArray = nlohmann::json::array();
879 for (const auto& [turboSpeed, coreCount] : *turboProfile)
880 {
881 nlohmann::json::object_t turbo;
882 turbo["ActiveCoreCount"] = coreCount;
883 turbo["MaxSpeedMHz"] = turboSpeed;
Patrick Williamsb2ba3072023-05-12 10:27:39 -0500884 turboArray.emplace_back(std::move(turbo));
Ed Tanous002d39b2022-05-31 08:59:27 -0700885 }
886 }
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200887
888 if (baseSpeedPrioritySettings != nullptr)
889 {
890 nlohmann::json& baseSpeedArray = json["BaseSpeedPrioritySettings"];
891 baseSpeedArray = nlohmann::json::array();
892 for (const auto& [baseSpeedMhz, coreList] :
893 *baseSpeedPrioritySettings)
894 {
895 nlohmann::json::object_t speed;
896 speed["CoreCount"] = coreList.size();
897 speed["CoreIDs"] = coreList;
898 speed["BaseSpeedMHz"] = baseSpeedMhz;
Patrick Williamsb2ba3072023-05-12 10:27:39 -0500899 baseSpeedArray.emplace_back(std::move(speed));
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200900 }
901 }
902 });
Jonathan Domandba0c292020-12-02 15:34:13 -0800903}
904
Jonathan Doman3cde86f2020-12-02 14:50:45 -0800905/**
906 * Handle the D-Bus response from attempting to set the CPU's AppliedConfig
907 * property. Main task is to translate error messages into Redfish errors.
908 *
909 * @param[in,out] resp HTTP response.
910 * @param[in] setPropVal Value which we attempted to set.
911 * @param[in] ec D-Bus response error code.
912 * @param[in] msg D-Bus response message.
913 */
914inline void
915 handleAppliedConfigResponse(const std::shared_ptr<bmcweb::AsyncResp>& resp,
916 const std::string& setPropVal,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800917 const boost::system::error_code& ec,
Patrick Williams59d494e2022-07-22 19:26:55 -0500918 const sdbusplus::message_t& msg)
Jonathan Doman3cde86f2020-12-02 14:50:45 -0800919{
920 if (!ec)
921 {
922 BMCWEB_LOG_DEBUG << "Set Property succeeded";
923 return;
924 }
925
926 BMCWEB_LOG_DEBUG << "Set Property failed: " << ec;
927
928 const sd_bus_error* dbusError = msg.get_error();
929 if (dbusError == nullptr)
930 {
931 messages::internalError(resp->res);
932 return;
933 }
934
935 // The asio error code doesn't know about our custom errors, so we have to
936 // parse the error string. Some of these D-Bus -> Redfish translations are a
937 // stretch, but it's good to try to communicate something vaguely useful.
938 if (strcmp(dbusError->name,
939 "xyz.openbmc_project.Common.Error.InvalidArgument") == 0)
940 {
941 // Service did not like the object_path we tried to set.
942 messages::propertyValueIncorrect(
943 resp->res, "AppliedOperatingConfig/@odata.id", setPropVal);
944 }
945 else if (strcmp(dbusError->name,
946 "xyz.openbmc_project.Common.Error.NotAllowed") == 0)
947 {
948 // Service indicates we can never change the config for this processor.
949 messages::propertyNotWritable(resp->res, "AppliedOperatingConfig");
950 }
951 else if (strcmp(dbusError->name,
952 "xyz.openbmc_project.Common.Error.Unavailable") == 0)
953 {
954 // Service indicates the config cannot be changed right now, but maybe
955 // in a different system state.
956 messages::resourceInStandby(resp->res);
957 }
Jonathan Doman3cde86f2020-12-02 14:50:45 -0800958 else
959 {
960 messages::internalError(resp->res);
961 }
962}
963
964/**
965 * Handle the PATCH operation of the AppliedOperatingConfig property. Do basic
966 * validation of the input data, and then set the D-Bus property.
967 *
968 * @param[in,out] resp Async HTTP response.
969 * @param[in] processorId Processor's Id.
970 * @param[in] appliedConfigUri New property value to apply.
971 * @param[in] cpuObjectPath Path of CPU object to modify.
972 * @param[in] serviceMap Service map for CPU object.
973 */
974inline void patchAppliedOperatingConfig(
975 const std::shared_ptr<bmcweb::AsyncResp>& resp,
976 const std::string& processorId, const std::string& appliedConfigUri,
Shantappa Teekappanavar5df6eda2022-01-18 12:29:28 -0600977 const std::string& cpuObjectPath,
978 const dbus::utility::MapperServiceMap& serviceMap)
Jonathan Doman3cde86f2020-12-02 14:50:45 -0800979{
980 // Check that the property even exists by checking for the interface
981 const std::string* controlService = nullptr;
982 for (const auto& [serviceName, interfaceList] : serviceMap)
983 {
984 if (std::find(interfaceList.begin(), interfaceList.end(),
985 "xyz.openbmc_project.Control.Processor."
986 "CurrentOperatingConfig") != interfaceList.end())
987 {
988 controlService = &serviceName;
989 break;
990 }
991 }
992
993 if (controlService == nullptr)
994 {
995 messages::internalError(resp->res);
996 return;
997 }
998
999 // Check that the config URI is a child of the cpu URI being patched.
1000 std::string expectedPrefix("/redfish/v1/Systems/system/Processors/");
1001 expectedPrefix += processorId;
1002 expectedPrefix += "/OperatingConfigs/";
Ed Tanous11ba3972022-07-11 09:50:41 -07001003 if (!appliedConfigUri.starts_with(expectedPrefix) ||
Jonathan Doman3cde86f2020-12-02 14:50:45 -08001004 expectedPrefix.size() == appliedConfigUri.size())
1005 {
1006 messages::propertyValueIncorrect(
1007 resp->res, "AppliedOperatingConfig/@odata.id", appliedConfigUri);
1008 return;
1009 }
1010
1011 // Generate the D-Bus path of the OperatingConfig object, by assuming it's a
1012 // direct child of the CPU object.
1013 // Strip the expectedPrefix from the config URI to get the "filename", and
1014 // append to the CPU's path.
1015 std::string configBaseName = appliedConfigUri.substr(expectedPrefix.size());
1016 sdbusplus::message::object_path configPath(cpuObjectPath);
1017 configPath /= configBaseName;
1018
1019 BMCWEB_LOG_INFO << "Setting config to " << configPath.str;
1020
1021 // Set the property, with handler to check error responses
1022 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001023 [resp, appliedConfigUri](const boost::system::error_code& ec,
Patrick Williams59d494e2022-07-22 19:26:55 -05001024 const sdbusplus::message_t& msg) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001025 handleAppliedConfigResponse(resp, appliedConfigUri, ec, msg);
Jonathan Doman3cde86f2020-12-02 14:50:45 -08001026 },
1027 *controlService, cpuObjectPath, "org.freedesktop.DBus.Properties",
1028 "Set", "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig",
Ed Tanous168e20c2021-12-13 14:39:53 -08001029 "AppliedConfig", dbus::utility::DbusVariantType(std::move(configPath)));
Jonathan Doman3cde86f2020-12-02 14:50:45 -08001030}
1031
Nikhil Namjoshi71a24ca2022-11-11 01:52:32 +00001032inline void handleProcessorHead(crow::App& app, const crow::Request& req,
1033 const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1034 const std::string& /* systemName */,
1035 const std::string& /* processorId */)
1036{
1037 if (!redfish::setUpRedfishRoute(app, req, aResp))
1038 {
1039 return;
1040 }
1041 aResp->res.addHeader(
1042 boost::beast::http::field::link,
1043 "</redfish/v1/JsonSchemas/Processor/Processor.json>; rel=describedby");
1044}
1045
1046inline void handleProcessorCollectionHead(
1047 crow::App& app, const crow::Request& req,
1048 const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1049 const std::string& /* systemName */)
1050{
1051 if (!redfish::setUpRedfishRoute(app, req, aResp))
1052 {
1053 return;
1054 }
1055 aResp->res.addHeader(
1056 boost::beast::http::field::link,
1057 "</redfish/v1/JsonSchemas/ProcessorCollection/ProcessorCollection.json>; rel=describedby");
1058}
1059
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001060inline void requestRoutesOperatingConfigCollection(App& app)
Jonathan Domandba0c292020-12-02 15:34:13 -08001061{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001062 BMCWEB_ROUTE(
1063 app, "/redfish/v1/Systems/system/Processors/<str>/OperatingConfigs/")
Ed Tanoused398212021-06-09 17:05:54 -07001064 .privileges(redfish::privileges::getOperatingConfigCollection)
Ed Tanous002d39b2022-05-31 08:59:27 -07001065 .methods(boost::beast::http::verb::get)(
1066 [&app](const crow::Request& req,
1067 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1068 const std::string& cpuName) {
Carson Labrado3ba00072022-06-06 19:40:56 +00001069 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07001070 {
1071 return;
1072 }
1073 asyncResp->res.jsonValue["@odata.type"] =
1074 "#OperatingConfigCollection.OperatingConfigCollection";
Ed Tanousef4c65b2023-04-24 15:28:50 -07001075 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
1076 "/redfish/v1/Systems/system/Processors/{}/OperatingConfigs",
1077 cpuName);
Ed Tanous002d39b2022-05-31 08:59:27 -07001078 asyncResp->res.jsonValue["Name"] = "Operating Config Collection";
1079
1080 // First find the matching CPU object so we know how to
1081 // constrain our search for related Config objects.
George Liu7a1dbc42022-12-07 16:03:22 +08001082 const std::array<std::string_view, 1> interfaces = {
1083 "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig"};
1084 dbus::utility::getSubTreePaths(
1085 "/xyz/openbmc_project/inventory", 0, interfaces,
Ed Tanous002d39b2022-05-31 08:59:27 -07001086 [asyncResp, cpuName](
George Liu7a1dbc42022-12-07 16:03:22 +08001087 const boost::system::error_code& ec,
Ed Tanous002d39b2022-05-31 08:59:27 -07001088 const dbus::utility::MapperGetSubTreePathsResponse& objects) {
1089 if (ec)
Ed Tanous45ca1b82022-03-25 13:07:27 -07001090 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001091 BMCWEB_LOG_WARNING << "D-Bus error: " << ec << ", "
1092 << ec.message();
1093 messages::internalError(asyncResp->res);
Ed Tanous45ca1b82022-03-25 13:07:27 -07001094 return;
1095 }
Jonathan Domandba0c292020-12-02 15:34:13 -08001096
Ed Tanous002d39b2022-05-31 08:59:27 -07001097 for (const std::string& object : objects)
1098 {
Ed Tanous11ba3972022-07-11 09:50:41 -07001099 if (!object.ends_with(cpuName))
Ed Tanous002d39b2022-05-31 08:59:27 -07001100 {
1101 continue;
1102 }
George Liu0fda0f12021-11-16 10:06:17 +08001103
Ed Tanous002d39b2022-05-31 08:59:27 -07001104 // Not expected that there will be multiple matching
1105 // CPU objects, but if there are just use the first
1106 // one.
Jonathan Domandba0c292020-12-02 15:34:13 -08001107
Ed Tanous002d39b2022-05-31 08:59:27 -07001108 // Use the common search routine to construct the
1109 // Collection of all Config objects under this CPU.
George Liu7a1dbc42022-12-07 16:03:22 +08001110 constexpr std::array<std::string_view, 1> interface {
1111 "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig"
1112 };
Ed Tanous002d39b2022-05-31 08:59:27 -07001113 collection_util::getCollectionMembers(
1114 asyncResp,
Ed Tanousef4c65b2023-04-24 15:28:50 -07001115 boost::urls::format(
1116 "/redfish/v1/Systems/system/Processors/{}/OperatingConfigs",
1117 cpuName),
George Liu7a1dbc42022-12-07 16:03:22 +08001118 interface, object.c_str());
Ed Tanous002d39b2022-05-31 08:59:27 -07001119 return;
1120 }
George Liu7a1dbc42022-12-07 16:03:22 +08001121 });
George Liu0fda0f12021-11-16 10:06:17 +08001122 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001123}
1124
1125inline void requestRoutesOperatingConfig(App& app)
1126{
1127 BMCWEB_ROUTE(
1128 app,
1129 "/redfish/v1/Systems/system/Processors/<str>/OperatingConfigs/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001130 .privileges(redfish::privileges::getOperatingConfig)
Ed Tanous002d39b2022-05-31 08:59:27 -07001131 .methods(boost::beast::http::verb::get)(
1132 [&app](const crow::Request& req,
1133 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1134 const std::string& cpuName, const std::string& configName) {
Carson Labrado3ba00072022-06-06 19:40:56 +00001135 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07001136 {
1137 return;
1138 }
1139 // Ask for all objects implementing OperatingConfig so we can search
1140 // for one with a matching name
George Liue99073f2022-12-09 11:06:16 +08001141 constexpr std::array<std::string_view, 1> interfaces = {
1142 "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig"};
1143 dbus::utility::getSubTree(
1144 "/xyz/openbmc_project/inventory", 0, interfaces,
Ed Tanous39662a32023-02-06 15:09:46 -08001145 [asyncResp, cpuName, configName](
George Liue99073f2022-12-09 11:06:16 +08001146 const boost::system::error_code& ec,
Ed Tanous002d39b2022-05-31 08:59:27 -07001147 const dbus::utility::MapperGetSubTreeResponse& subtree) {
1148 if (ec)
Ed Tanous45ca1b82022-03-25 13:07:27 -07001149 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001150 BMCWEB_LOG_WARNING << "D-Bus error: " << ec << ", "
1151 << ec.message();
1152 messages::internalError(asyncResp->res);
Ed Tanous45ca1b82022-03-25 13:07:27 -07001153 return;
1154 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001155 const std::string expectedEnding = cpuName + '/' + configName;
1156 for (const auto& [objectPath, serviceMap] : subtree)
1157 {
1158 // Ignore any configs without matching cpuX/configY
Ed Tanous11ba3972022-07-11 09:50:41 -07001159 if (!objectPath.ends_with(expectedEnding) || serviceMap.empty())
Ed Tanous002d39b2022-05-31 08:59:27 -07001160 {
1161 continue;
1162 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001163
Ed Tanous002d39b2022-05-31 08:59:27 -07001164 nlohmann::json& json = asyncResp->res.jsonValue;
1165 json["@odata.type"] = "#OperatingConfig.v1_0_0.OperatingConfig";
Ed Tanousef4c65b2023-04-24 15:28:50 -07001166 json["@odata.id"] = boost::urls::format(
1167 "/redfish/v1/Systems/system/Processors/{}/OperatingConfigs/{}",
1168 cpuName, configName);
Ed Tanous002d39b2022-05-31 08:59:27 -07001169 json["Name"] = "Processor Profile";
1170 json["Id"] = configName;
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001171
Ed Tanous002d39b2022-05-31 08:59:27 -07001172 // Just use the first implementation of the object - not
1173 // expected that there would be multiple matching
1174 // services
1175 getOperatingConfigData(asyncResp, serviceMap.begin()->first,
1176 objectPath);
1177 return;
1178 }
1179 messages::resourceNotFound(asyncResp->res, "OperatingConfig",
1180 configName);
George Liue99073f2022-12-09 11:06:16 +08001181 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001182 });
1183}
Jonathan Domandba0c292020-12-02 15:34:13 -08001184
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001185inline void requestRoutesProcessorCollection(App& app)
Gunnar Millsac6a4442020-10-14 14:55:29 -05001186{
Gunnar Millsac6a4442020-10-14 14:55:29 -05001187 /**
1188 * Functions triggers appropriate requests on DBus
1189 */
Ed Tanous22d268c2022-05-19 09:39:07 -07001190 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/")
Nikhil Namjoshi71a24ca2022-11-11 01:52:32 +00001191 .privileges(redfish::privileges::headProcessorCollection)
1192 .methods(boost::beast::http::verb::head)(
1193 std::bind_front(handleProcessorCollectionHead, std::ref(app)));
1194
1195 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/")
Ed Tanoused398212021-06-09 17:05:54 -07001196 .privileges(redfish::privileges::getProcessorCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001197 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07001198 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07001199 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1200 const std::string& systemName) {
Carson Labrado3ba00072022-06-06 19:40:56 +00001201 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07001202 {
1203 return;
1204 }
Ed Tanous22d268c2022-05-19 09:39:07 -07001205 if (systemName != "system")
1206 {
1207 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1208 systemName);
1209 return;
1210 }
1211
Nikhil Namjoshi71a24ca2022-11-11 01:52:32 +00001212 asyncResp->res.addHeader(
1213 boost::beast::http::field::link,
1214 "</redfish/v1/JsonSchemas/ProcessorCollection/ProcessorCollection.json>; rel=describedby");
1215
Ed Tanous002d39b2022-05-31 08:59:27 -07001216 asyncResp->res.jsonValue["@odata.type"] =
1217 "#ProcessorCollection.ProcessorCollection";
1218 asyncResp->res.jsonValue["Name"] = "Processor Collection";
Gunnar Millsac6a4442020-10-14 14:55:29 -05001219
Ed Tanous002d39b2022-05-31 08:59:27 -07001220 asyncResp->res.jsonValue["@odata.id"] =
1221 "/redfish/v1/Systems/system/Processors";
Gunnar Millsac6a4442020-10-14 14:55:29 -05001222
Ed Tanous002d39b2022-05-31 08:59:27 -07001223 collection_util::getCollectionMembers(
Willy Tuae9031f2022-09-27 05:48:07 +00001224 asyncResp,
1225 boost::urls::url("/redfish/v1/Systems/system/Processors"),
George Liu7a1dbc42022-12-07 16:03:22 +08001226 processorInterfaces);
Ed Tanous002d39b2022-05-31 08:59:27 -07001227 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001228}
Gunnar Millsac6a4442020-10-14 14:55:29 -05001229
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001230inline void requestRoutesProcessor(App& app)
Gunnar Millsac6a4442020-10-14 14:55:29 -05001231{
Gunnar Millsac6a4442020-10-14 14:55:29 -05001232 /**
1233 * Functions triggers appropriate requests on DBus
1234 */
Gunnar Millsac6a4442020-10-14 14:55:29 -05001235
Ed Tanous22d268c2022-05-19 09:39:07 -07001236 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/<str>/")
Nikhil Namjoshi71a24ca2022-11-11 01:52:32 +00001237 .privileges(redfish::privileges::headProcessor)
1238 .methods(boost::beast::http::verb::head)(
1239 std::bind_front(handleProcessorHead, std::ref(app)));
1240
1241 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001242 .privileges(redfish::privileges::getProcessor)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001243 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07001244 [&app](const crow::Request& req,
1245 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous22d268c2022-05-19 09:39:07 -07001246 const std::string& systemName,
Ed Tanous45ca1b82022-03-25 13:07:27 -07001247 const std::string& processorId) {
Carson Labrado3ba00072022-06-06 19:40:56 +00001248 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07001249 {
1250 return;
1251 }
Ed Tanous22d268c2022-05-19 09:39:07 -07001252 if (systemName != "system")
1253 {
1254 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1255 systemName);
1256 return;
1257 }
1258
Nikhil Namjoshi71a24ca2022-11-11 01:52:32 +00001259 asyncResp->res.addHeader(
1260 boost::beast::http::field::link,
1261 "</redfish/v1/JsonSchemas/Processor/Processor.json>; rel=describedby");
Ed Tanous002d39b2022-05-31 08:59:27 -07001262 asyncResp->res.jsonValue["@odata.type"] =
1263 "#Processor.v1_11_0.Processor";
Ed Tanousef4c65b2023-04-24 15:28:50 -07001264 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
1265 "/redfish/v1/Systems/system/Processors/{}", processorId);
Jonathan Doman3cde86f2020-12-02 14:50:45 -08001266
Ed Tanous8a592812022-06-04 09:06:59 -07001267 getProcessorObject(
1268 asyncResp, processorId,
1269 std::bind_front(getProcessorData, asyncResp, processorId));
Ed Tanous002d39b2022-05-31 08:59:27 -07001270 });
Jonathan Doman3cde86f2020-12-02 14:50:45 -08001271
Ed Tanous22d268c2022-05-19 09:39:07 -07001272 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001273 .privileges(redfish::privileges::patchProcessor)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001274 .methods(boost::beast::http::verb::patch)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07001275 [&app](const crow::Request& req,
1276 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous22d268c2022-05-19 09:39:07 -07001277 const std::string& systemName,
Ed Tanous45ca1b82022-03-25 13:07:27 -07001278 const std::string& processorId) {
Carson Labrado3ba00072022-06-06 19:40:56 +00001279 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07001280 {
1281 return;
1282 }
Ed Tanous22d268c2022-05-19 09:39:07 -07001283 if (systemName != "system")
1284 {
1285 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1286 systemName);
1287 return;
1288 }
1289
Ed Tanous002d39b2022-05-31 08:59:27 -07001290 std::optional<nlohmann::json> appliedConfigJson;
1291 if (!json_util::readJsonPatch(req, asyncResp->res,
1292 "AppliedOperatingConfig",
1293 appliedConfigJson))
1294 {
1295 return;
1296 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001297
Ed Tanous002d39b2022-05-31 08:59:27 -07001298 if (appliedConfigJson)
1299 {
Ed Tanousf8fe53e2022-06-30 15:55:45 -07001300 std::string appliedConfigUri;
Ed Tanous002d39b2022-05-31 08:59:27 -07001301 if (!json_util::readJson(*appliedConfigJson, asyncResp->res,
1302 "@odata.id", appliedConfigUri))
1303 {
1304 return;
1305 }
1306 // Check for 404 and find matching D-Bus object, then run
1307 // property patch handlers if that all succeeds.
Ed Tanous8a592812022-06-04 09:06:59 -07001308 getProcessorObject(asyncResp, processorId,
1309 std::bind_front(patchAppliedOperatingConfig,
1310 asyncResp, processorId,
1311 appliedConfigUri));
Ed Tanous002d39b2022-05-31 08:59:27 -07001312 }
1313 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001314}
Gunnar Millsac6a4442020-10-14 14:55:29 -05001315
1316} // namespace redfish