blob: 4566e4bd8f0cb6f07e49f9b53c325569812d5ad1 [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>
Jonathan Doman1e1e5982021-06-11 09:36:17 -070031#include <sdbusplus/asio/property.hpp>
Jonathan Domandba0c292020-12-02 15:34:13 -080032#include <sdbusplus/message/native_types.hpp>
Krzysztof Grobelny351053f2022-07-28 15:44:22 +020033#include <sdbusplus/unpack_properties.hpp>
Jonathan Domandba0c292020-12-02 15:34:13 -080034#include <sdbusplus/utility/dedup_variant.hpp>
Gunnar Millsac6a4442020-10-14 14:55:29 -050035
George Liu7a1dbc42022-12-07 16:03:22 +080036#include <array>
Michael Shenb9d679d2023-02-13 02:29:04 +000037#include <limits>
George Liu7a1dbc42022-12-07 16:03:22 +080038#include <string_view>
39
Gunnar Millsac6a4442020-10-14 14:55:29 -050040namespace redfish
41{
42
Jonathan Domanc9514482021-02-24 09:20:51 -080043// Interfaces which imply a D-Bus object represents a Processor
George Liu7a1dbc42022-12-07 16:03:22 +080044constexpr std::array<std::string_view, 2> processorInterfaces = {
Jonathan Domanc9514482021-02-24 09:20:51 -080045 "xyz.openbmc_project.Inventory.Item.Cpu",
46 "xyz.openbmc_project.Inventory.Item.Accelerator"};
Jonathan Doman2bab9832020-12-02 15:27:40 -080047
Sharad Yadav71b82f22021-05-10 15:11:39 +053048/**
49 * @brief Fill out uuid info of a processor by
50 * requesting data from the given D-Bus object.
51 *
52 * @param[in,out] aResp Async HTTP response.
53 * @param[in] service D-Bus service to query.
54 * @param[in] objPath D-Bus object to query.
55 */
56inline void getProcessorUUID(std::shared_ptr<bmcweb::AsyncResp> aResp,
57 const std::string& service,
58 const std::string& objPath)
59{
60 BMCWEB_LOG_DEBUG << "Get Processor UUID";
Jonathan Doman1e1e5982021-06-11 09:36:17 -070061 sdbusplus::asio::getProperty<std::string>(
62 *crow::connections::systemBus, service, objPath,
63 "xyz.openbmc_project.Common.UUID", "UUID",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -080064 [objPath, aResp{std::move(aResp)}](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -070065 const std::string& property) {
Ed Tanous002d39b2022-05-31 08:59:27 -070066 if (ec)
67 {
68 BMCWEB_LOG_DEBUG << "DBUS response error";
69 messages::internalError(aResp->res);
70 return;
71 }
72 aResp->res.jsonValue["UUID"] = property;
Jonathan Doman1e1e5982021-06-11 09:36:17 -070073 });
Sharad Yadav71b82f22021-05-10 15:11:39 +053074}
75
Ed Tanous711ac7a2021-12-20 09:34:41 -080076inline void getCpuDataByInterface(
77 const std::shared_ptr<bmcweb::AsyncResp>& aResp,
78 const dbus::utility::DBusInteracesMap& cpuInterfacesProperties)
Gunnar Millsac6a4442020-10-14 14:55:29 -050079{
80 BMCWEB_LOG_DEBUG << "Get CPU resources by interface.";
81
Chicago Duana1649ec2021-03-30 16:54:58 +080082 // Set the default value of state
83 aResp->res.jsonValue["Status"]["State"] = "Enabled";
84 aResp->res.jsonValue["Status"]["Health"] = "OK";
Gunnar Millsac6a4442020-10-14 14:55:29 -050085
86 for (const auto& interface : cpuInterfacesProperties)
87 {
88 for (const auto& property : interface.second)
89 {
Chicago Duana1649ec2021-03-30 16:54:58 +080090 if (property.first == "Present")
Gunnar Millsac6a4442020-10-14 14:55:29 -050091 {
Chicago Duana1649ec2021-03-30 16:54:58 +080092 const bool* cpuPresent = std::get_if<bool>(&property.second);
93 if (cpuPresent == nullptr)
Gunnar Millsac6a4442020-10-14 14:55:29 -050094 {
95 // Important property not in desired type
96 messages::internalError(aResp->res);
97 return;
98 }
Ed Tanouse05aec52022-01-25 10:28:56 -080099 if (!*cpuPresent)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500100 {
Chicago Duana1649ec2021-03-30 16:54:58 +0800101 // Slot is not populated
Gunnar Millsac6a4442020-10-14 14:55:29 -0500102 aResp->res.jsonValue["Status"]["State"] = "Absent";
Chicago Duana1649ec2021-03-30 16:54:58 +0800103 }
104 }
105 else if (property.first == "Functional")
106 {
107 const bool* cpuFunctional = std::get_if<bool>(&property.second);
108 if (cpuFunctional == nullptr)
109 {
110 messages::internalError(aResp->res);
Gunnar Millsac6a4442020-10-14 14:55:29 -0500111 return;
112 }
Ed Tanouse05aec52022-01-25 10:28:56 -0800113 if (!*cpuFunctional)
Chicago Duana1649ec2021-03-30 16:54:58 +0800114 {
115 aResp->res.jsonValue["Status"]["Health"] = "Critical";
116 }
117 }
118 else if (property.first == "CoreCount")
119 {
120 const uint16_t* coresCount =
121 std::get_if<uint16_t>(&property.second);
122 if (coresCount == nullptr)
123 {
124 messages::internalError(aResp->res);
125 return;
126 }
Gunnar Millsac6a4442020-10-14 14:55:29 -0500127 aResp->res.jsonValue["TotalCores"] = *coresCount;
128 }
Jonathan Domandc3fa662020-10-26 23:10:24 -0700129 else if (property.first == "MaxSpeedInMhz")
130 {
131 const uint32_t* value = std::get_if<uint32_t>(&property.second);
132 if (value != nullptr)
133 {
134 aResp->res.jsonValue["MaxSpeedMHz"] = *value;
135 }
136 }
Gunnar Millsac6a4442020-10-14 14:55:29 -0500137 else if (property.first == "Socket")
138 {
139 const std::string* value =
140 std::get_if<std::string>(&property.second);
141 if (value != nullptr)
142 {
143 aResp->res.jsonValue["Socket"] = *value;
144 }
145 }
146 else if (property.first == "ThreadCount")
147 {
Jonathan Domandc3fa662020-10-26 23:10:24 -0700148 const uint16_t* value = std::get_if<uint16_t>(&property.second);
Gunnar Millsac6a4442020-10-14 14:55:29 -0500149 if (value != nullptr)
150 {
151 aResp->res.jsonValue["TotalThreads"] = *value;
152 }
153 }
Brandon Kim1930fbd2021-09-14 17:52:51 -0700154 else if (property.first == "EffectiveFamily")
Gunnar Millsac6a4442020-10-14 14:55:29 -0500155 {
Brandon Kim1930fbd2021-09-14 17:52:51 -0700156 const uint16_t* value = std::get_if<uint16_t>(&property.second);
Brad Bishop6169de22022-09-14 13:08:32 -0400157 if (value != nullptr && *value != 2)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500158 {
159 aResp->res.jsonValue["ProcessorId"]["EffectiveFamily"] =
Ed Tanous866e4862022-02-17 11:40:25 -0800160 "0x" + intToHexString(*value, 4);
Gunnar Millsac6a4442020-10-14 14:55:29 -0500161 }
162 }
Brandon Kim1930fbd2021-09-14 17:52:51 -0700163 else if (property.first == "EffectiveModel")
164 {
165 const uint16_t* value = std::get_if<uint16_t>(&property.second);
166 if (value == nullptr)
167 {
168 messages::internalError(aResp->res);
169 return;
170 }
Brad Bishop6169de22022-09-14 13:08:32 -0400171 if (*value != 0)
172 {
173 aResp->res.jsonValue["ProcessorId"]["EffectiveModel"] =
174 "0x" + intToHexString(*value, 4);
175 }
Brandon Kim1930fbd2021-09-14 17:52:51 -0700176 }
Gunnar Millsac6a4442020-10-14 14:55:29 -0500177 else if (property.first == "Id")
178 {
179 const uint64_t* value = std::get_if<uint64_t>(&property.second);
180 if (value != nullptr && *value != 0)
181 {
Gunnar Millsac6a4442020-10-14 14:55:29 -0500182 aResp->res
183 .jsonValue["ProcessorId"]["IdentificationRegisters"] =
Ed Tanous866e4862022-02-17 11:40:25 -0800184 "0x" + intToHexString(*value, 16);
Gunnar Millsac6a4442020-10-14 14:55:29 -0500185 }
186 }
Brandon Kim1930fbd2021-09-14 17:52:51 -0700187 else if (property.first == "Microcode")
188 {
189 const uint32_t* value = std::get_if<uint32_t>(&property.second);
190 if (value == nullptr)
191 {
192 messages::internalError(aResp->res);
193 return;
194 }
Brad Bishop6169de22022-09-14 13:08:32 -0400195 if (*value != 0)
196 {
197 aResp->res.jsonValue["ProcessorId"]["MicrocodeInfo"] =
198 "0x" + intToHexString(*value, 8);
199 }
Brandon Kim1930fbd2021-09-14 17:52:51 -0700200 }
201 else if (property.first == "Step")
202 {
203 const uint16_t* value = std::get_if<uint16_t>(&property.second);
204 if (value == nullptr)
205 {
206 messages::internalError(aResp->res);
207 return;
208 }
Michael Shenb9d679d2023-02-13 02:29:04 +0000209 if (*value != std::numeric_limits<uint16_t>::max())
Brad Bishop6169de22022-09-14 13:08:32 -0400210 {
211 aResp->res.jsonValue["ProcessorId"]["Step"] =
212 "0x" + intToHexString(*value, 4);
213 }
Brandon Kim1930fbd2021-09-14 17:52:51 -0700214 }
Gunnar Millsac6a4442020-10-14 14:55:29 -0500215 }
216 }
Gunnar Millsac6a4442020-10-14 14:55:29 -0500217}
218
zhanghch058d1b46d2021-04-01 11:18:24 +0800219inline void getCpuDataByService(std::shared_ptr<bmcweb::AsyncResp> aResp,
Gunnar Millsac6a4442020-10-14 14:55:29 -0500220 const std::string& cpuId,
221 const std::string& service,
222 const std::string& objPath)
223{
224 BMCWEB_LOG_DEBUG << "Get available system cpu resources by service.";
225
226 crow::connections::systemBus->async_method_call(
227 [cpuId, service, objPath, aResp{std::move(aResp)}](
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800228 const boost::system::error_code& ec,
Gunnar Millsac6a4442020-10-14 14:55:29 -0500229 const dbus::utility::ManagedObjectType& dbusData) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700230 if (ec)
231 {
232 BMCWEB_LOG_DEBUG << "DBUS response error";
233 messages::internalError(aResp->res);
234 return;
235 }
236 aResp->res.jsonValue["Id"] = cpuId;
237 aResp->res.jsonValue["Name"] = "Processor";
238 aResp->res.jsonValue["ProcessorType"] = "CPU";
Gunnar Millsac6a4442020-10-14 14:55:29 -0500239
Ed Tanous002d39b2022-05-31 08:59:27 -0700240 bool slotPresent = false;
241 std::string corePath = objPath + "/core";
242 size_t totalCores = 0;
243 for (const auto& object : dbusData)
244 {
245 if (object.first.str == objPath)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500246 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700247 getCpuDataByInterface(aResp, object.second);
248 }
Ed Tanous11ba3972022-07-11 09:50:41 -0700249 else if (object.first.str.starts_with(corePath))
Ed Tanous002d39b2022-05-31 08:59:27 -0700250 {
251 for (const auto& interface : object.second)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500252 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700253 if (interface.first == "xyz.openbmc_project.Inventory.Item")
Gunnar Millsac6a4442020-10-14 14:55:29 -0500254 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700255 for (const auto& property : interface.second)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500256 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700257 if (property.first == "Present")
Gunnar Millsac6a4442020-10-14 14:55:29 -0500258 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700259 const bool* present =
260 std::get_if<bool>(&property.second);
261 if (present != nullptr)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500262 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700263 if (*present)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500264 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700265 slotPresent = true;
266 totalCores++;
Gunnar Millsac6a4442020-10-14 14:55:29 -0500267 }
268 }
269 }
270 }
271 }
272 }
273 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700274 }
275 // In getCpuDataByInterface(), state and health are set
276 // based on the present and functional status. If core
277 // count is zero, then it has a higher precedence.
278 if (slotPresent)
279 {
280 if (totalCores == 0)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500281 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700282 // Slot is not populated, set status end return
283 aResp->res.jsonValue["Status"]["State"] = "Absent";
284 aResp->res.jsonValue["Status"]["Health"] = "OK";
Gunnar Millsac6a4442020-10-14 14:55:29 -0500285 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700286 aResp->res.jsonValue["TotalCores"] = totalCores;
287 }
288 return;
Gunnar Millsac6a4442020-10-14 14:55:29 -0500289 },
290 service, "/xyz/openbmc_project/inventory",
291 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
292}
293
zhanghch058d1b46d2021-04-01 11:18:24 +0800294inline void getCpuAssetData(std::shared_ptr<bmcweb::AsyncResp> aResp,
Gunnar Millsac6a4442020-10-14 14:55:29 -0500295 const std::string& service,
296 const std::string& objPath)
297{
298 BMCWEB_LOG_DEBUG << "Get Cpu Asset Data";
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200299 sdbusplus::asio::getAllProperties(
300 *crow::connections::systemBus, service, objPath,
301 "xyz.openbmc_project.Inventory.Decorator.Asset",
Gunnar Millsac6a4442020-10-14 14:55:29 -0500302 [objPath, aResp{std::move(aResp)}](
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800303 const boost::system::error_code& ec,
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200304 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700305 if (ec)
306 {
307 BMCWEB_LOG_DEBUG << "DBUS response error";
308 messages::internalError(aResp->res);
309 return;
310 }
311
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200312 const std::string* serialNumber = nullptr;
313 const std::string* model = nullptr;
314 const std::string* manufacturer = nullptr;
315 const std::string* partNumber = nullptr;
316 const std::string* sparePartNumber = nullptr;
317
318 const bool success = sdbusplus::unpackPropertiesNoThrow(
319 dbus_utils::UnpackErrorPrinter(), properties, "SerialNumber",
320 serialNumber, "Model", model, "Manufacturer", manufacturer,
321 "PartNumber", partNumber, "SparePartNumber", sparePartNumber);
322
323 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -0700324 {
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200325 messages::internalError(aResp->res);
326 return;
327 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700328
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200329 if (serialNumber != nullptr && !serialNumber->empty())
330 {
331 aResp->res.jsonValue["SerialNumber"] = *serialNumber;
332 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700333
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200334 if ((model != nullptr) && !model->empty())
335 {
336 aResp->res.jsonValue["Model"] = *model;
337 }
338
339 if (manufacturer != nullptr)
340 {
341 aResp->res.jsonValue["Manufacturer"] = *manufacturer;
342
343 // Otherwise would be unexpected.
344 if (manufacturer->find("Intel") != std::string::npos)
Ed Tanous002d39b2022-05-31 08:59:27 -0700345 {
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200346 aResp->res.jsonValue["ProcessorArchitecture"] = "x86";
347 aResp->res.jsonValue["InstructionSet"] = "x86-64";
Ed Tanous002d39b2022-05-31 08:59:27 -0700348 }
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200349 else if (manufacturer->find("IBM") != std::string::npos)
Ed Tanous002d39b2022-05-31 08:59:27 -0700350 {
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200351 aResp->res.jsonValue["ProcessorArchitecture"] = "Power";
352 aResp->res.jsonValue["InstructionSet"] = "PowerISA";
Ed Tanous002d39b2022-05-31 08:59:27 -0700353 }
354 }
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200355
356 if (partNumber != nullptr)
357 {
358 aResp->res.jsonValue["PartNumber"] = *partNumber;
359 }
360
Brad Bishop6169de22022-09-14 13:08:32 -0400361 if (sparePartNumber != nullptr && !sparePartNumber->empty())
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200362 {
363 aResp->res.jsonValue["SparePartNumber"] = *sparePartNumber;
364 }
365 });
Gunnar Millsac6a4442020-10-14 14:55:29 -0500366}
367
zhanghch058d1b46d2021-04-01 11:18:24 +0800368inline void getCpuRevisionData(std::shared_ptr<bmcweb::AsyncResp> aResp,
Gunnar Millsac6a4442020-10-14 14:55:29 -0500369 const std::string& service,
370 const std::string& objPath)
371{
372 BMCWEB_LOG_DEBUG << "Get Cpu Revision Data";
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200373 sdbusplus::asio::getAllProperties(
374 *crow::connections::systemBus, service, objPath,
375 "xyz.openbmc_project.Inventory.Decorator.Revision",
Gunnar Millsac6a4442020-10-14 14:55:29 -0500376 [objPath, aResp{std::move(aResp)}](
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800377 const boost::system::error_code& ec,
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200378 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700379 if (ec)
380 {
381 BMCWEB_LOG_DEBUG << "DBUS response error";
382 messages::internalError(aResp->res);
383 return;
384 }
Gunnar Millsac6a4442020-10-14 14:55:29 -0500385
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200386 const std::string* version = nullptr;
387
388 const bool success = sdbusplus::unpackPropertiesNoThrow(
389 dbus_utils::UnpackErrorPrinter(), properties, "Version", version);
390
391 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -0700392 {
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200393 messages::internalError(aResp->res);
394 return;
Ed Tanous002d39b2022-05-31 08:59:27 -0700395 }
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200396
397 if (version != nullptr)
398 {
399 aResp->res.jsonValue["Version"] = *version;
400 }
401 });
Gunnar Millsac6a4442020-10-14 14:55:29 -0500402}
403
zhanghch058d1b46d2021-04-01 11:18:24 +0800404inline void getAcceleratorDataByService(
405 std::shared_ptr<bmcweb::AsyncResp> aResp, const std::string& acclrtrId,
406 const std::string& service, const std::string& objPath)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500407{
408 BMCWEB_LOG_DEBUG
409 << "Get available system Accelerator resources by service.";
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200410 sdbusplus::asio::getAllProperties(
411 *crow::connections::systemBus, service, objPath, "",
Gunnar Millsac6a4442020-10-14 14:55:29 -0500412 [acclrtrId, aResp{std::move(aResp)}](
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800413 const boost::system::error_code& ec,
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200414 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700415 if (ec)
416 {
417 BMCWEB_LOG_DEBUG << "DBUS response error";
418 messages::internalError(aResp->res);
419 return;
420 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700421
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200422 const bool* functional = nullptr;
423 const bool* present = nullptr;
424
425 const bool success = sdbusplus::unpackPropertiesNoThrow(
426 dbus_utils::UnpackErrorPrinter(), properties, "Functional",
427 functional, "Present", present);
428
429 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -0700430 {
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200431 messages::internalError(aResp->res);
432 return;
Ed Tanous002d39b2022-05-31 08:59:27 -0700433 }
Gunnar Millsac6a4442020-10-14 14:55:29 -0500434
Ed Tanous002d39b2022-05-31 08:59:27 -0700435 std::string state = "Enabled";
436 std::string health = "OK";
Gunnar Millsac6a4442020-10-14 14:55:29 -0500437
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200438 if (present != nullptr && !*present)
Ed Tanous002d39b2022-05-31 08:59:27 -0700439 {
440 state = "Absent";
441 }
442
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200443 if (functional != nullptr && !*functional)
Ed Tanous002d39b2022-05-31 08:59:27 -0700444 {
445 if (state == "Enabled")
Gunnar Millsac6a4442020-10-14 14:55:29 -0500446 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700447 health = "Critical";
Gunnar Millsac6a4442020-10-14 14:55:29 -0500448 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700449 }
Gunnar Millsac6a4442020-10-14 14:55:29 -0500450
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200451 aResp->res.jsonValue["Id"] = acclrtrId;
452 aResp->res.jsonValue["Name"] = "Processor";
Ed Tanous002d39b2022-05-31 08:59:27 -0700453 aResp->res.jsonValue["Status"]["State"] = state;
454 aResp->res.jsonValue["Status"]["Health"] = health;
455 aResp->res.jsonValue["ProcessorType"] = "Accelerator";
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200456 });
Gunnar Millsac6a4442020-10-14 14:55:29 -0500457}
458
Jonathan Domandba0c292020-12-02 15:34:13 -0800459// OperatingConfig D-Bus Types
460using TurboProfileProperty = std::vector<std::tuple<uint32_t, size_t>>;
461using BaseSpeedPrioritySettingsProperty =
462 std::vector<std::tuple<uint32_t, std::vector<uint32_t>>>;
463// uint32_t and size_t may or may not be the same type, requiring a dedup'd
464// variant
Jonathan Domandba0c292020-12-02 15:34:13 -0800465
466/**
467 * Fill out the HighSpeedCoreIDs in a Processor resource from the given
468 * OperatingConfig D-Bus property.
469 *
470 * @param[in,out] aResp Async HTTP response.
471 * @param[in] baseSpeedSettings Full list of base speed priority groups,
472 * to use to determine the list of high
473 * speed cores.
474 */
475inline void highSpeedCoreIdsHandler(
zhanghch058d1b46d2021-04-01 11:18:24 +0800476 const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Jonathan Domandba0c292020-12-02 15:34:13 -0800477 const BaseSpeedPrioritySettingsProperty& baseSpeedSettings)
478{
479 // The D-Bus property does not indicate which bucket is the "high
480 // priority" group, so let's discern that by looking for the one with
481 // highest base frequency.
482 auto highPriorityGroup = baseSpeedSettings.cend();
483 uint32_t highestBaseSpeed = 0;
484 for (auto it = baseSpeedSettings.cbegin(); it != baseSpeedSettings.cend();
485 ++it)
486 {
487 const uint32_t baseFreq = std::get<uint32_t>(*it);
488 if (baseFreq > highestBaseSpeed)
489 {
490 highestBaseSpeed = baseFreq;
491 highPriorityGroup = it;
492 }
493 }
494
495 nlohmann::json& jsonCoreIds = aResp->res.jsonValue["HighSpeedCoreIDs"];
496 jsonCoreIds = nlohmann::json::array();
497
498 // There may not be any entries in the D-Bus property, so only populate
499 // if there was actually something there.
500 if (highPriorityGroup != baseSpeedSettings.cend())
501 {
502 jsonCoreIds = std::get<std::vector<uint32_t>>(*highPriorityGroup);
503 }
504}
505
506/**
507 * Fill out OperatingConfig related items in a Processor resource by requesting
508 * data from the given D-Bus object.
509 *
510 * @param[in,out] aResp Async HTTP response.
511 * @param[in] cpuId CPU D-Bus name.
512 * @param[in] service D-Bus service to query.
513 * @param[in] objPath D-Bus object to query.
514 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800515inline void getCpuConfigData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Jonathan Domandba0c292020-12-02 15:34:13 -0800516 const std::string& cpuId,
517 const std::string& service,
518 const std::string& objPath)
519{
520 BMCWEB_LOG_INFO << "Getting CPU operating configs for " << cpuId;
521
522 // First, GetAll CurrentOperatingConfig properties on the object
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200523 sdbusplus::asio::getAllProperties(
524 *crow::connections::systemBus, service, objPath,
525 "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig",
526 [aResp, cpuId,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800527 service](const boost::system::error_code& ec,
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200528 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700529 if (ec)
530 {
531 BMCWEB_LOG_WARNING << "D-Bus error: " << ec << ", " << ec.message();
532 messages::internalError(aResp->res);
533 return;
534 }
Jonathan Domandba0c292020-12-02 15:34:13 -0800535
Ed Tanous002d39b2022-05-31 08:59:27 -0700536 nlohmann::json& json = aResp->res.jsonValue;
Jonathan Domandba0c292020-12-02 15:34:13 -0800537
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200538 const sdbusplus::message::object_path* appliedConfig = nullptr;
539 const bool* baseSpeedPriorityEnabled = nullptr;
540
541 const bool success = sdbusplus::unpackPropertiesNoThrow(
542 dbus_utils::UnpackErrorPrinter(), properties, "AppliedConfig",
543 appliedConfig, "BaseSpeedPriorityEnabled",
544 baseSpeedPriorityEnabled);
545
546 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -0700547 {
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200548 messages::internalError(aResp->res);
549 return;
Ed Tanous002d39b2022-05-31 08:59:27 -0700550 }
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200551
552 if (appliedConfig != nullptr)
553 {
554 const std::string& dbusPath = appliedConfig->str;
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200555 nlohmann::json::object_t operatingConfig;
Willy Tueddfc432022-09-26 16:46:38 +0000556 operatingConfig["@odata.id"] = crow::utility::urlFromPieces(
557 "redfish", "v1", "Systems", "system", "Processors", cpuId,
558 "OperatingConfigs");
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200559 json["OperatingConfigs"] = std::move(operatingConfig);
560
561 // Reuse the D-Bus config object name for the Redfish
562 // URI
563 size_t baseNamePos = dbusPath.rfind('/');
564 if (baseNamePos == std::string::npos ||
565 baseNamePos == (dbusPath.size() - 1))
566 {
567 // If the AppliedConfig was somehow not a valid path,
568 // skip adding any more properties, since everything
569 // else is tied to this applied config.
570 messages::internalError(aResp->res);
571 return;
572 }
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200573 nlohmann::json::object_t appliedOperatingConfig;
Willy Tueddfc432022-09-26 16:46:38 +0000574 appliedOperatingConfig["@odata.id"] = crow::utility::urlFromPieces(
575 "redfish", "v1", "Systems", "system", "Processors", cpuId,
576 "OperatingConfigs", dbusPath.substr(baseNamePos + 1));
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200577 json["AppliedOperatingConfig"] = std::move(appliedOperatingConfig);
578
579 // Once we found the current applied config, queue another
580 // request to read the base freq core ids out of that
581 // config.
582 sdbusplus::asio::getProperty<BaseSpeedPrioritySettingsProperty>(
583 *crow::connections::systemBus, service, dbusPath,
584 "xyz.openbmc_project.Inventory.Item.Cpu."
585 "OperatingConfig",
586 "BaseSpeedPrioritySettings",
587 [aResp](
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800588 const boost::system::error_code& ec2,
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200589 const BaseSpeedPrioritySettingsProperty& baseSpeedList) {
590 if (ec2)
591 {
592 BMCWEB_LOG_WARNING << "D-Bus Property Get error: " << ec2;
593 messages::internalError(aResp->res);
594 return;
595 }
596
597 highSpeedCoreIdsHandler(aResp, baseSpeedList);
598 });
599 }
600
601 if (baseSpeedPriorityEnabled != nullptr)
602 {
603 json["BaseSpeedPriorityState"] =
604 *baseSpeedPriorityEnabled ? "Enabled" : "Disabled";
605 }
606 });
Jonathan Domandba0c292020-12-02 15:34:13 -0800607}
608
SunnySrivastava1984cba4f442021-01-07 12:48:16 -0600609/**
610 * @brief Fill out location info of a processor by
611 * requesting data from the given D-Bus object.
612 *
613 * @param[in,out] aResp Async HTTP response.
614 * @param[in] service D-Bus service to query.
615 * @param[in] objPath D-Bus object to query.
616 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800617inline void getCpuLocationCode(std::shared_ptr<bmcweb::AsyncResp> aResp,
SunnySrivastava1984cba4f442021-01-07 12:48:16 -0600618 const std::string& service,
619 const std::string& objPath)
620{
621 BMCWEB_LOG_DEBUG << "Get Cpu Location Data";
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700622 sdbusplus::asio::getProperty<std::string>(
623 *crow::connections::systemBus, service, objPath,
624 "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800625 [objPath, aResp{std::move(aResp)}](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700626 const std::string& property) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700627 if (ec)
628 {
629 BMCWEB_LOG_DEBUG << "DBUS response error";
630 messages::internalError(aResp->res);
631 return;
632 }
SunnySrivastava1984cba4f442021-01-07 12:48:16 -0600633
Ed Tanous002d39b2022-05-31 08:59:27 -0700634 aResp->res.jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
635 property;
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700636 });
SunnySrivastava1984cba4f442021-01-07 12:48:16 -0600637}
638
Jonathan Domanc9514482021-02-24 09:20:51 -0800639/**
Jonathan Doman49e429c2021-03-03 13:11:44 -0800640 * Populate the unique identifier in a Processor resource by requesting data
641 * from the given D-Bus object.
642 *
643 * @param[in,out] aResp Async HTTP response.
644 * @param[in] service D-Bus service to query.
645 * @param[in] objPath D-Bus object to query.
646 */
647inline void getCpuUniqueId(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
648 const std::string& service,
649 const std::string& objectPath)
650{
651 BMCWEB_LOG_DEBUG << "Get CPU UniqueIdentifier";
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700652 sdbusplus::asio::getProperty<std::string>(
653 *crow::connections::systemBus, service, objectPath,
654 "xyz.openbmc_project.Inventory.Decorator.UniqueIdentifier",
655 "UniqueIdentifier",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800656 [aResp](const boost::system::error_code& ec, const std::string& id) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700657 if (ec)
658 {
659 BMCWEB_LOG_ERROR << "Failed to read cpu unique id: " << ec;
660 messages::internalError(aResp->res);
661 return;
662 }
663 aResp->res.jsonValue["ProcessorId"]["ProtectedIdentificationNumber"] =
664 id;
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700665 });
Jonathan Doman49e429c2021-03-03 13:11:44 -0800666}
667
668/**
Jonathan Domanc9514482021-02-24 09:20:51 -0800669 * Find the D-Bus object representing the requested Processor, and call the
670 * handler with the results. If matching object is not found, add 404 error to
671 * response and don't call the handler.
672 *
673 * @param[in,out] resp Async HTTP response.
674 * @param[in] processorId Redfish Processor Id.
675 * @param[in] handler Callback to continue processing request upon
676 * successfully finding object.
677 */
678template <typename Handler>
zhanghch058d1b46d2021-04-01 11:18:24 +0800679inline void getProcessorObject(const std::shared_ptr<bmcweb::AsyncResp>& resp,
Jonathan Domanc9514482021-02-24 09:20:51 -0800680 const std::string& processorId,
681 Handler&& handler)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500682{
683 BMCWEB_LOG_DEBUG << "Get available system processor resources.";
684
Jonathan Domanc9514482021-02-24 09:20:51 -0800685 // GetSubTree on all interfaces which provide info about a Processor
George Liue99073f2022-12-09 11:06:16 +0800686 constexpr std::array<std::string_view, 8> interfaces = {
687 "xyz.openbmc_project.Common.UUID",
688 "xyz.openbmc_project.Inventory.Decorator.Asset",
689 "xyz.openbmc_project.Inventory.Decorator.Revision",
690 "xyz.openbmc_project.Inventory.Item.Cpu",
691 "xyz.openbmc_project.Inventory.Decorator.LocationCode",
692 "xyz.openbmc_project.Inventory.Item.Accelerator",
693 "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig",
694 "xyz.openbmc_project.Inventory.Decorator.UniqueIdentifier"};
695 dbus::utility::getSubTree(
696 "/xyz/openbmc_project/inventory", 0, interfaces,
Jonathan Domanc9514482021-02-24 09:20:51 -0800697 [resp, processorId, handler = std::forward<Handler>(handler)](
George Liue99073f2022-12-09 11:06:16 +0800698 const boost::system::error_code& ec,
699 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700700 if (ec)
701 {
702 BMCWEB_LOG_DEBUG << "DBUS response error: " << ec;
703 messages::internalError(resp->res);
704 return;
705 }
706 for (const auto& [objectPath, serviceMap] : subtree)
707 {
708 // Ignore any objects which don't end with our desired cpu name
Ed Tanous11ba3972022-07-11 09:50:41 -0700709 if (!objectPath.ends_with(processorId))
Gunnar Millsac6a4442020-10-14 14:55:29 -0500710 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700711 continue;
Gunnar Millsac6a4442020-10-14 14:55:29 -0500712 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700713
714 bool found = false;
715 // Filter out objects that don't have the CPU-specific
716 // interfaces to make sure we can return 404 on non-CPUs
717 // (e.g. /redfish/../Processors/dimm0)
718 for (const auto& [serviceName, interfaceList] : serviceMap)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500719 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700720 if (std::find_first_of(
721 interfaceList.begin(), interfaceList.end(),
722 processorInterfaces.begin(),
723 processorInterfaces.end()) != interfaceList.end())
Gunnar Millsac6a4442020-10-14 14:55:29 -0500724 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700725 found = true;
726 break;
Jonathan Doman2bab9832020-12-02 15:27:40 -0800727 }
Gunnar Millsac6a4442020-10-14 14:55:29 -0500728 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700729
730 if (!found)
731 {
732 continue;
733 }
734
735 // Process the first object which does match our cpu name and
736 // required interfaces, and potentially ignore any other
737 // matching objects. Assume all interfaces we want to process
738 // must be on the same object path.
739
Ed Tanous8a592812022-06-04 09:06:59 -0700740 handler(objectPath, serviceMap);
Ed Tanous002d39b2022-05-31 08:59:27 -0700741 return;
742 }
743 messages::resourceNotFound(resp->res, "Processor", processorId);
George Liue99073f2022-12-09 11:06:16 +0800744 });
Gunnar Millsac6a4442020-10-14 14:55:29 -0500745}
746
zhanghch058d1b46d2021-04-01 11:18:24 +0800747inline void getProcessorData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Jonathan Domanc9514482021-02-24 09:20:51 -0800748 const std::string& processorId,
749 const std::string& objectPath,
Shantappa Teekappanavar5df6eda2022-01-18 12:29:28 -0600750 const dbus::utility::MapperServiceMap& serviceMap)
Jonathan Domanc9514482021-02-24 09:20:51 -0800751{
752 for (const auto& [serviceName, interfaceList] : serviceMap)
753 {
754 for (const auto& interface : interfaceList)
755 {
756 if (interface == "xyz.openbmc_project.Inventory.Decorator.Asset")
757 {
758 getCpuAssetData(aResp, serviceName, objectPath);
759 }
George Liu0fda0f12021-11-16 10:06:17 +0800760 else if (interface ==
761 "xyz.openbmc_project.Inventory.Decorator.Revision")
Jonathan Domanc9514482021-02-24 09:20:51 -0800762 {
763 getCpuRevisionData(aResp, serviceName, objectPath);
764 }
765 else if (interface == "xyz.openbmc_project.Inventory.Item.Cpu")
766 {
767 getCpuDataByService(aResp, processorId, serviceName,
768 objectPath);
769 }
George Liu0fda0f12021-11-16 10:06:17 +0800770 else if (interface ==
771 "xyz.openbmc_project.Inventory.Item.Accelerator")
Jonathan Domanc9514482021-02-24 09:20:51 -0800772 {
773 getAcceleratorDataByService(aResp, processorId, serviceName,
774 objectPath);
775 }
George Liu0fda0f12021-11-16 10:06:17 +0800776 else if (
777 interface ==
778 "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig")
Jonathan Domanc9514482021-02-24 09:20:51 -0800779 {
780 getCpuConfigData(aResp, processorId, serviceName, objectPath);
781 }
George Liu0fda0f12021-11-16 10:06:17 +0800782 else if (interface ==
783 "xyz.openbmc_project.Inventory.Decorator.LocationCode")
Jonathan Domanc9514482021-02-24 09:20:51 -0800784 {
785 getCpuLocationCode(aResp, serviceName, objectPath);
786 }
Sharad Yadav71b82f22021-05-10 15:11:39 +0530787 else if (interface == "xyz.openbmc_project.Common.UUID")
788 {
789 getProcessorUUID(aResp, serviceName, objectPath);
790 }
George Liu0fda0f12021-11-16 10:06:17 +0800791 else if (interface ==
792 "xyz.openbmc_project.Inventory.Decorator.UniqueIdentifier")
Jonathan Doman49e429c2021-03-03 13:11:44 -0800793 {
794 getCpuUniqueId(aResp, serviceName, objectPath);
795 }
Jonathan Domanc9514482021-02-24 09:20:51 -0800796 }
797 }
798}
799
Jonathan Domandba0c292020-12-02 15:34:13 -0800800/**
801 * Request all the properties for the given D-Bus object and fill out the
802 * related entries in the Redfish OperatingConfig response.
803 *
804 * @param[in,out] aResp Async HTTP response.
805 * @param[in] service D-Bus service name to query.
806 * @param[in] objPath D-Bus object to query.
807 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800808inline void
809 getOperatingConfigData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
810 const std::string& service,
811 const std::string& objPath)
Jonathan Domandba0c292020-12-02 15:34:13 -0800812{
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200813 sdbusplus::asio::getAllProperties(
814 *crow::connections::systemBus, service, objPath,
815 "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800816 [aResp](const boost::system::error_code& ec,
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200817 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700818 if (ec)
819 {
820 BMCWEB_LOG_WARNING << "D-Bus error: " << ec << ", " << ec.message();
821 messages::internalError(aResp->res);
822 return;
823 }
824
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200825 const size_t* availableCoreCount = nullptr;
826 const uint32_t* baseSpeed = nullptr;
827 const uint32_t* maxJunctionTemperature = nullptr;
828 const uint32_t* maxSpeed = nullptr;
829 const uint32_t* powerLimit = nullptr;
830 const TurboProfileProperty* turboProfile = nullptr;
831 const BaseSpeedPrioritySettingsProperty* baseSpeedPrioritySettings =
832 nullptr;
833
834 const bool success = sdbusplus::unpackPropertiesNoThrow(
835 dbus_utils::UnpackErrorPrinter(), properties, "AvailableCoreCount",
836 availableCoreCount, "BaseSpeed", baseSpeed,
837 "MaxJunctionTemperature", maxJunctionTemperature, "MaxSpeed",
838 maxSpeed, "PowerLimit", powerLimit, "TurboProfile", turboProfile,
839 "BaseSpeedPrioritySettings", baseSpeedPrioritySettings);
840
841 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -0700842 {
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200843 messages::internalError(aResp->res);
844 return;
845 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700846
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200847 nlohmann::json& json = aResp->res.jsonValue;
Ed Tanous002d39b2022-05-31 08:59:27 -0700848
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200849 if (availableCoreCount != nullptr)
850 {
851 json["TotalAvailableCoreCount"] = *availableCoreCount;
852 }
853
854 if (baseSpeed != nullptr)
855 {
856 json["BaseSpeedMHz"] = *baseSpeed;
857 }
858
859 if (maxJunctionTemperature != nullptr)
860 {
861 json["MaxJunctionTemperatureCelsius"] = *maxJunctionTemperature;
862 }
863
864 if (maxSpeed != nullptr)
865 {
866 json["MaxSpeedMHz"] = *maxSpeed;
867 }
868
869 if (powerLimit != nullptr)
870 {
871 json["TDPWatts"] = *powerLimit;
872 }
873
874 if (turboProfile != nullptr)
875 {
876 nlohmann::json& turboArray = json["TurboProfile"];
877 turboArray = nlohmann::json::array();
878 for (const auto& [turboSpeed, coreCount] : *turboProfile)
879 {
880 nlohmann::json::object_t turbo;
881 turbo["ActiveCoreCount"] = coreCount;
882 turbo["MaxSpeedMHz"] = turboSpeed;
883 turboArray.push_back(std::move(turbo));
Ed Tanous002d39b2022-05-31 08:59:27 -0700884 }
885 }
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200886
887 if (baseSpeedPrioritySettings != nullptr)
888 {
889 nlohmann::json& baseSpeedArray = json["BaseSpeedPrioritySettings"];
890 baseSpeedArray = nlohmann::json::array();
891 for (const auto& [baseSpeedMhz, coreList] :
892 *baseSpeedPrioritySettings)
893 {
894 nlohmann::json::object_t speed;
895 speed["CoreCount"] = coreList.size();
896 speed["CoreIDs"] = coreList;
897 speed["BaseSpeedMHz"] = baseSpeedMhz;
898 baseSpeedArray.push_back(std::move(speed));
899 }
900 }
901 });
Jonathan Domandba0c292020-12-02 15:34:13 -0800902}
903
Jonathan Doman3cde86f2020-12-02 14:50:45 -0800904/**
905 * Handle the D-Bus response from attempting to set the CPU's AppliedConfig
906 * property. Main task is to translate error messages into Redfish errors.
907 *
908 * @param[in,out] resp HTTP response.
909 * @param[in] setPropVal Value which we attempted to set.
910 * @param[in] ec D-Bus response error code.
911 * @param[in] msg D-Bus response message.
912 */
913inline void
914 handleAppliedConfigResponse(const std::shared_ptr<bmcweb::AsyncResp>& resp,
915 const std::string& setPropVal,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800916 const boost::system::error_code& ec,
Patrick Williams59d494e2022-07-22 19:26:55 -0500917 const sdbusplus::message_t& msg)
Jonathan Doman3cde86f2020-12-02 14:50:45 -0800918{
919 if (!ec)
920 {
921 BMCWEB_LOG_DEBUG << "Set Property succeeded";
922 return;
923 }
924
925 BMCWEB_LOG_DEBUG << "Set Property failed: " << ec;
926
927 const sd_bus_error* dbusError = msg.get_error();
928 if (dbusError == nullptr)
929 {
930 messages::internalError(resp->res);
931 return;
932 }
933
934 // The asio error code doesn't know about our custom errors, so we have to
935 // parse the error string. Some of these D-Bus -> Redfish translations are a
936 // stretch, but it's good to try to communicate something vaguely useful.
937 if (strcmp(dbusError->name,
938 "xyz.openbmc_project.Common.Error.InvalidArgument") == 0)
939 {
940 // Service did not like the object_path we tried to set.
941 messages::propertyValueIncorrect(
942 resp->res, "AppliedOperatingConfig/@odata.id", setPropVal);
943 }
944 else if (strcmp(dbusError->name,
945 "xyz.openbmc_project.Common.Error.NotAllowed") == 0)
946 {
947 // Service indicates we can never change the config for this processor.
948 messages::propertyNotWritable(resp->res, "AppliedOperatingConfig");
949 }
950 else if (strcmp(dbusError->name,
951 "xyz.openbmc_project.Common.Error.Unavailable") == 0)
952 {
953 // Service indicates the config cannot be changed right now, but maybe
954 // in a different system state.
955 messages::resourceInStandby(resp->res);
956 }
Jonathan Doman3cde86f2020-12-02 14:50:45 -0800957 else
958 {
959 messages::internalError(resp->res);
960 }
961}
962
963/**
964 * Handle the PATCH operation of the AppliedOperatingConfig property. Do basic
965 * validation of the input data, and then set the D-Bus property.
966 *
967 * @param[in,out] resp Async HTTP response.
968 * @param[in] processorId Processor's Id.
969 * @param[in] appliedConfigUri New property value to apply.
970 * @param[in] cpuObjectPath Path of CPU object to modify.
971 * @param[in] serviceMap Service map for CPU object.
972 */
973inline void patchAppliedOperatingConfig(
974 const std::shared_ptr<bmcweb::AsyncResp>& resp,
975 const std::string& processorId, const std::string& appliedConfigUri,
Shantappa Teekappanavar5df6eda2022-01-18 12:29:28 -0600976 const std::string& cpuObjectPath,
977 const dbus::utility::MapperServiceMap& serviceMap)
Jonathan Doman3cde86f2020-12-02 14:50:45 -0800978{
979 // Check that the property even exists by checking for the interface
980 const std::string* controlService = nullptr;
981 for (const auto& [serviceName, interfaceList] : serviceMap)
982 {
983 if (std::find(interfaceList.begin(), interfaceList.end(),
984 "xyz.openbmc_project.Control.Processor."
985 "CurrentOperatingConfig") != interfaceList.end())
986 {
987 controlService = &serviceName;
988 break;
989 }
990 }
991
992 if (controlService == nullptr)
993 {
994 messages::internalError(resp->res);
995 return;
996 }
997
998 // Check that the config URI is a child of the cpu URI being patched.
999 std::string expectedPrefix("/redfish/v1/Systems/system/Processors/");
1000 expectedPrefix += processorId;
1001 expectedPrefix += "/OperatingConfigs/";
Ed Tanous11ba3972022-07-11 09:50:41 -07001002 if (!appliedConfigUri.starts_with(expectedPrefix) ||
Jonathan Doman3cde86f2020-12-02 14:50:45 -08001003 expectedPrefix.size() == appliedConfigUri.size())
1004 {
1005 messages::propertyValueIncorrect(
1006 resp->res, "AppliedOperatingConfig/@odata.id", appliedConfigUri);
1007 return;
1008 }
1009
1010 // Generate the D-Bus path of the OperatingConfig object, by assuming it's a
1011 // direct child of the CPU object.
1012 // Strip the expectedPrefix from the config URI to get the "filename", and
1013 // append to the CPU's path.
1014 std::string configBaseName = appliedConfigUri.substr(expectedPrefix.size());
1015 sdbusplus::message::object_path configPath(cpuObjectPath);
1016 configPath /= configBaseName;
1017
1018 BMCWEB_LOG_INFO << "Setting config to " << configPath.str;
1019
1020 // Set the property, with handler to check error responses
1021 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001022 [resp, appliedConfigUri](const boost::system::error_code& ec,
Patrick Williams59d494e2022-07-22 19:26:55 -05001023 const sdbusplus::message_t& msg) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001024 handleAppliedConfigResponse(resp, appliedConfigUri, ec, msg);
Jonathan Doman3cde86f2020-12-02 14:50:45 -08001025 },
1026 *controlService, cpuObjectPath, "org.freedesktop.DBus.Properties",
1027 "Set", "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig",
Ed Tanous168e20c2021-12-13 14:39:53 -08001028 "AppliedConfig", dbus::utility::DbusVariantType(std::move(configPath)));
Jonathan Doman3cde86f2020-12-02 14:50:45 -08001029}
1030
Nikhil Namjoshi71a24ca2022-11-11 01:52:32 +00001031inline void handleProcessorHead(crow::App& app, const crow::Request& req,
1032 const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1033 const std::string& /* systemName */,
1034 const std::string& /* processorId */)
1035{
1036 if (!redfish::setUpRedfishRoute(app, req, aResp))
1037 {
1038 return;
1039 }
1040 aResp->res.addHeader(
1041 boost::beast::http::field::link,
1042 "</redfish/v1/JsonSchemas/Processor/Processor.json>; rel=describedby");
1043}
1044
1045inline void handleProcessorCollectionHead(
1046 crow::App& app, const crow::Request& req,
1047 const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1048 const std::string& /* systemName */)
1049{
1050 if (!redfish::setUpRedfishRoute(app, req, aResp))
1051 {
1052 return;
1053 }
1054 aResp->res.addHeader(
1055 boost::beast::http::field::link,
1056 "</redfish/v1/JsonSchemas/ProcessorCollection/ProcessorCollection.json>; rel=describedby");
1057}
1058
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001059inline void requestRoutesOperatingConfigCollection(App& app)
Jonathan Domandba0c292020-12-02 15:34:13 -08001060{
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 Tanous39662a32023-02-06 15:09:46 -08001075 asyncResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
1076 "redfish", "v1", "Systems", "system", "Processors", cpuName,
1077 "OperatingConfigs");
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,
Willy Tuae9031f2022-09-27 05:48:07 +00001115 crow::utility::urlFromPieces("redfish", "v1", "Systems",
1116 "system", "Processors",
1117 cpuName, "OperatingConfigs"),
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 Tanous39662a32023-02-06 15:09:46 -08001166 json["@odata.id"] = crow::utility::urlFromPieces(
1167 "redfish", "v1", "Systems", "system", "Processors", cpuName,
1168 "OperatingConfigs", 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";
Willy Tueddfc432022-09-26 16:46:38 +00001264 asyncResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
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