blob: 34aa42fbf4f360f89f281ed2eb3dc9ee1b3346fe [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"
Chris Caindfbf7de2023-04-13 16:01:04 -050022#include "generated/enums/processor.hpp"
Gunnar Millsac6a4442020-10-14 14:55:29 -050023#include "health.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080024#include "query.hpp"
25#include "registries/privilege_registry.hpp"
26#include "utils/collection.hpp"
27#include "utils/dbus_utils.hpp"
28#include "utils/json_utils.hpp"
Gunnar Millsac6a4442020-10-14 14:55:29 -050029
30#include <boost/container/flat_map.hpp>
George Liue99073f2022-12-09 11:06:16 +080031#include <boost/system/error_code.hpp>
Ed Tanousef4c65b2023-04-24 15:28:50 -070032#include <boost/url/format.hpp>
Jonathan Doman1e1e5982021-06-11 09:36:17 -070033#include <sdbusplus/asio/property.hpp>
Jonathan Domandba0c292020-12-02 15:34:13 -080034#include <sdbusplus/message/native_types.hpp>
Krzysztof Grobelny351053f2022-07-28 15:44:22 +020035#include <sdbusplus/unpack_properties.hpp>
Jonathan Domandba0c292020-12-02 15:34:13 -080036#include <sdbusplus/utility/dedup_variant.hpp>
Gunnar Millsac6a4442020-10-14 14:55:29 -050037
George Liu7a1dbc42022-12-07 16:03:22 +080038#include <array>
Michael Shenb9d679d2023-02-13 02:29:04 +000039#include <limits>
Ed Tanous3544d2a2023-08-06 18:12:20 -070040#include <ranges>
Ed Tanous3c569212024-03-06 14:46:18 -080041#include <string>
George Liu7a1dbc42022-12-07 16:03:22 +080042#include <string_view>
43
Gunnar Millsac6a4442020-10-14 14:55:29 -050044namespace redfish
45{
46
Jonathan Domanc9514482021-02-24 09:20:51 -080047// Interfaces which imply a D-Bus object represents a Processor
George Liu7a1dbc42022-12-07 16:03:22 +080048constexpr std::array<std::string_view, 2> processorInterfaces = {
Jonathan Domanc9514482021-02-24 09:20:51 -080049 "xyz.openbmc_project.Inventory.Item.Cpu",
50 "xyz.openbmc_project.Inventory.Item.Accelerator"};
Jonathan Doman2bab9832020-12-02 15:27:40 -080051
Sharad Yadav71b82f22021-05-10 15:11:39 +053052/**
53 * @brief Fill out uuid info of a processor by
54 * requesting data from the given D-Bus object.
55 *
Ed Tanousac106bf2023-06-07 09:24:59 -070056 * @param[in,out] asyncResp Async HTTP response.
Sharad Yadav71b82f22021-05-10 15:11:39 +053057 * @param[in] service D-Bus service to query.
58 * @param[in] objPath D-Bus object to query.
59 */
Ed Tanousac106bf2023-06-07 09:24:59 -070060inline void getProcessorUUID(std::shared_ptr<bmcweb::AsyncResp> asyncResp,
Sharad Yadav71b82f22021-05-10 15:11:39 +053061 const std::string& service,
62 const std::string& objPath)
63{
Ed Tanous62598e32023-07-17 17:06:25 -070064 BMCWEB_LOG_DEBUG("Get Processor UUID");
Jonathan Doman1e1e5982021-06-11 09:36:17 -070065 sdbusplus::asio::getProperty<std::string>(
66 *crow::connections::systemBus, service, objPath,
67 "xyz.openbmc_project.Common.UUID", "UUID",
Ed Tanousac106bf2023-06-07 09:24:59 -070068 [objPath, asyncResp{std::move(asyncResp)}](
69 const boost::system::error_code& ec, const std::string& property) {
Ed Tanous002d39b2022-05-31 08:59:27 -070070 if (ec)
71 {
Ed Tanous62598e32023-07-17 17:06:25 -070072 BMCWEB_LOG_DEBUG("DBUS response error");
Ed Tanousac106bf2023-06-07 09:24:59 -070073 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -070074 return;
75 }
Ed Tanousac106bf2023-06-07 09:24:59 -070076 asyncResp->res.jsonValue["UUID"] = property;
Patrick Williams5a39f772023-10-20 11:20:21 -050077 });
Sharad Yadav71b82f22021-05-10 15:11:39 +053078}
79
Ed Tanous711ac7a2021-12-20 09:34:41 -080080inline void getCpuDataByInterface(
Ed Tanousac106bf2023-06-07 09:24:59 -070081 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Michael Shen80f79a42023-08-24 13:41:53 +000082 const dbus::utility::DBusInterfacesMap& cpuInterfacesProperties)
Gunnar Millsac6a4442020-10-14 14:55:29 -050083{
Ed Tanous62598e32023-07-17 17:06:25 -070084 BMCWEB_LOG_DEBUG("Get CPU resources by interface.");
Gunnar Millsac6a4442020-10-14 14:55:29 -050085
Chicago Duana1649ec2021-03-30 16:54:58 +080086 // Set the default value of state
Ed Tanousac106bf2023-06-07 09:24:59 -070087 asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
88 asyncResp->res.jsonValue["Status"]["Health"] = "OK";
Gunnar Millsac6a4442020-10-14 14:55:29 -050089
90 for (const auto& interface : cpuInterfacesProperties)
91 {
92 for (const auto& property : interface.second)
93 {
Chicago Duana1649ec2021-03-30 16:54:58 +080094 if (property.first == "Present")
Gunnar Millsac6a4442020-10-14 14:55:29 -050095 {
Chicago Duana1649ec2021-03-30 16:54:58 +080096 const bool* cpuPresent = std::get_if<bool>(&property.second);
97 if (cpuPresent == nullptr)
Gunnar Millsac6a4442020-10-14 14:55:29 -050098 {
99 // Important property not in desired type
Ed Tanousac106bf2023-06-07 09:24:59 -0700100 messages::internalError(asyncResp->res);
Gunnar Millsac6a4442020-10-14 14:55:29 -0500101 return;
102 }
Ed Tanouse05aec52022-01-25 10:28:56 -0800103 if (!*cpuPresent)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500104 {
Chicago Duana1649ec2021-03-30 16:54:58 +0800105 // Slot is not populated
Ed Tanousac106bf2023-06-07 09:24:59 -0700106 asyncResp->res.jsonValue["Status"]["State"] = "Absent";
Chicago Duana1649ec2021-03-30 16:54:58 +0800107 }
108 }
109 else if (property.first == "Functional")
110 {
111 const bool* cpuFunctional = std::get_if<bool>(&property.second);
112 if (cpuFunctional == nullptr)
113 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700114 messages::internalError(asyncResp->res);
Gunnar Millsac6a4442020-10-14 14:55:29 -0500115 return;
116 }
Ed Tanouse05aec52022-01-25 10:28:56 -0800117 if (!*cpuFunctional)
Chicago Duana1649ec2021-03-30 16:54:58 +0800118 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700119 asyncResp->res.jsonValue["Status"]["Health"] = "Critical";
Chicago Duana1649ec2021-03-30 16:54:58 +0800120 }
121 }
122 else if (property.first == "CoreCount")
123 {
124 const uint16_t* coresCount =
125 std::get_if<uint16_t>(&property.second);
126 if (coresCount == nullptr)
127 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700128 messages::internalError(asyncResp->res);
Chicago Duana1649ec2021-03-30 16:54:58 +0800129 return;
130 }
Ed Tanousac106bf2023-06-07 09:24:59 -0700131 asyncResp->res.jsonValue["TotalCores"] = *coresCount;
Gunnar Millsac6a4442020-10-14 14:55:29 -0500132 }
Jonathan Domandc3fa662020-10-26 23:10:24 -0700133 else if (property.first == "MaxSpeedInMhz")
134 {
135 const uint32_t* value = std::get_if<uint32_t>(&property.second);
136 if (value != nullptr)
137 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700138 asyncResp->res.jsonValue["MaxSpeedMHz"] = *value;
Jonathan Domandc3fa662020-10-26 23:10:24 -0700139 }
140 }
Gunnar Millsac6a4442020-10-14 14:55:29 -0500141 else if (property.first == "Socket")
142 {
143 const std::string* value =
144 std::get_if<std::string>(&property.second);
145 if (value != nullptr)
146 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700147 asyncResp->res.jsonValue["Socket"] = *value;
Gunnar Millsac6a4442020-10-14 14:55:29 -0500148 }
149 }
150 else if (property.first == "ThreadCount")
151 {
Jonathan Domandc3fa662020-10-26 23:10:24 -0700152 const uint16_t* value = std::get_if<uint16_t>(&property.second);
Gunnar Millsac6a4442020-10-14 14:55:29 -0500153 if (value != nullptr)
154 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700155 asyncResp->res.jsonValue["TotalThreads"] = *value;
Gunnar Millsac6a4442020-10-14 14:55:29 -0500156 }
157 }
Brandon Kim1930fbd2021-09-14 17:52:51 -0700158 else if (property.first == "EffectiveFamily")
Gunnar Millsac6a4442020-10-14 14:55:29 -0500159 {
Brandon Kim1930fbd2021-09-14 17:52:51 -0700160 const uint16_t* value = std::get_if<uint16_t>(&property.second);
Brad Bishop6169de22022-09-14 13:08:32 -0400161 if (value != nullptr && *value != 2)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500162 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700163 asyncResp->res.jsonValue["ProcessorId"]["EffectiveFamily"] =
Ed Tanous866e4862022-02-17 11:40:25 -0800164 "0x" + intToHexString(*value, 4);
Gunnar Millsac6a4442020-10-14 14:55:29 -0500165 }
166 }
Brandon Kim1930fbd2021-09-14 17:52:51 -0700167 else if (property.first == "EffectiveModel")
168 {
169 const uint16_t* value = std::get_if<uint16_t>(&property.second);
170 if (value == nullptr)
171 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700172 messages::internalError(asyncResp->res);
Brandon Kim1930fbd2021-09-14 17:52:51 -0700173 return;
174 }
Brad Bishop6169de22022-09-14 13:08:32 -0400175 if (*value != 0)
176 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700177 asyncResp->res.jsonValue["ProcessorId"]["EffectiveModel"] =
Brad Bishop6169de22022-09-14 13:08:32 -0400178 "0x" + intToHexString(*value, 4);
179 }
Brandon Kim1930fbd2021-09-14 17:52:51 -0700180 }
Gunnar Millsac6a4442020-10-14 14:55:29 -0500181 else if (property.first == "Id")
182 {
183 const uint64_t* value = std::get_if<uint64_t>(&property.second);
184 if (value != nullptr && *value != 0)
185 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700186 asyncResp->res
Gunnar Millsac6a4442020-10-14 14:55:29 -0500187 .jsonValue["ProcessorId"]["IdentificationRegisters"] =
Ed Tanous866e4862022-02-17 11:40:25 -0800188 "0x" + intToHexString(*value, 16);
Gunnar Millsac6a4442020-10-14 14:55:29 -0500189 }
190 }
Brandon Kim1930fbd2021-09-14 17:52:51 -0700191 else if (property.first == "Microcode")
192 {
193 const uint32_t* value = std::get_if<uint32_t>(&property.second);
194 if (value == nullptr)
195 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700196 messages::internalError(asyncResp->res);
Brandon Kim1930fbd2021-09-14 17:52:51 -0700197 return;
198 }
Brad Bishop6169de22022-09-14 13:08:32 -0400199 if (*value != 0)
200 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700201 asyncResp->res.jsonValue["ProcessorId"]["MicrocodeInfo"] =
Brad Bishop6169de22022-09-14 13:08:32 -0400202 "0x" + intToHexString(*value, 8);
203 }
Brandon Kim1930fbd2021-09-14 17:52:51 -0700204 }
205 else if (property.first == "Step")
206 {
207 const uint16_t* value = std::get_if<uint16_t>(&property.second);
208 if (value == nullptr)
209 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700210 messages::internalError(asyncResp->res);
Brandon Kim1930fbd2021-09-14 17:52:51 -0700211 return;
212 }
Michael Shenb9d679d2023-02-13 02:29:04 +0000213 if (*value != std::numeric_limits<uint16_t>::max())
Brad Bishop6169de22022-09-14 13:08:32 -0400214 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700215 asyncResp->res.jsonValue["ProcessorId"]["Step"] =
Brad Bishop6169de22022-09-14 13:08:32 -0400216 "0x" + intToHexString(*value, 4);
217 }
Brandon Kim1930fbd2021-09-14 17:52:51 -0700218 }
Gunnar Millsac6a4442020-10-14 14:55:29 -0500219 }
220 }
Gunnar Millsac6a4442020-10-14 14:55:29 -0500221}
222
Ed Tanousac106bf2023-06-07 09:24:59 -0700223inline void getCpuDataByService(std::shared_ptr<bmcweb::AsyncResp> asyncResp,
Gunnar Millsac6a4442020-10-14 14:55:29 -0500224 const std::string& cpuId,
225 const std::string& service,
226 const std::string& objPath)
227{
Ed Tanous62598e32023-07-17 17:06:25 -0700228 BMCWEB_LOG_DEBUG("Get available system cpu resources by service.");
Gunnar Millsac6a4442020-10-14 14:55:29 -0500229
George Liu5eb468d2023-06-20 17:03:24 +0800230 sdbusplus::message::object_path path("/xyz/openbmc_project/inventory");
231 dbus::utility::getManagedObjects(
232 service, path,
Ed Tanousac106bf2023-06-07 09:24:59 -0700233 [cpuId, service, objPath, asyncResp{std::move(asyncResp)}](
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800234 const boost::system::error_code& ec,
Gunnar Millsac6a4442020-10-14 14:55:29 -0500235 const dbus::utility::ManagedObjectType& dbusData) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700236 if (ec)
237 {
Ed Tanous62598e32023-07-17 17:06:25 -0700238 BMCWEB_LOG_DEBUG("DBUS response error");
Ed Tanousac106bf2023-06-07 09:24:59 -0700239 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -0700240 return;
241 }
Ed Tanousac106bf2023-06-07 09:24:59 -0700242 asyncResp->res.jsonValue["Id"] = cpuId;
243 asyncResp->res.jsonValue["Name"] = "Processor";
244 asyncResp->res.jsonValue["ProcessorType"] = "CPU";
Gunnar Millsac6a4442020-10-14 14:55:29 -0500245
Ed Tanous002d39b2022-05-31 08:59:27 -0700246 bool slotPresent = false;
247 std::string corePath = objPath + "/core";
248 size_t totalCores = 0;
249 for (const auto& object : dbusData)
250 {
251 if (object.first.str == objPath)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500252 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700253 getCpuDataByInterface(asyncResp, object.second);
Ed Tanous002d39b2022-05-31 08:59:27 -0700254 }
Ed Tanous11ba3972022-07-11 09:50:41 -0700255 else if (object.first.str.starts_with(corePath))
Ed Tanous002d39b2022-05-31 08:59:27 -0700256 {
257 for (const auto& interface : object.second)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500258 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700259 if (interface.first == "xyz.openbmc_project.Inventory.Item")
Gunnar Millsac6a4442020-10-14 14:55:29 -0500260 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700261 for (const auto& property : interface.second)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500262 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700263 if (property.first == "Present")
Gunnar Millsac6a4442020-10-14 14:55:29 -0500264 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700265 const bool* present =
266 std::get_if<bool>(&property.second);
267 if (present != nullptr)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500268 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700269 if (*present)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500270 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700271 slotPresent = true;
272 totalCores++;
Gunnar Millsac6a4442020-10-14 14:55:29 -0500273 }
274 }
275 }
276 }
277 }
278 }
279 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700280 }
281 // In getCpuDataByInterface(), state and health are set
282 // based on the present and functional status. If core
283 // count is zero, then it has a higher precedence.
284 if (slotPresent)
285 {
286 if (totalCores == 0)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500287 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700288 // Slot is not populated, set status end return
Ed Tanousac106bf2023-06-07 09:24:59 -0700289 asyncResp->res.jsonValue["Status"]["State"] = "Absent";
290 asyncResp->res.jsonValue["Status"]["Health"] = "OK";
Gunnar Millsac6a4442020-10-14 14:55:29 -0500291 }
Ed Tanousac106bf2023-06-07 09:24:59 -0700292 asyncResp->res.jsonValue["TotalCores"] = totalCores;
Ed Tanous002d39b2022-05-31 08:59:27 -0700293 }
294 return;
Patrick Williams5a39f772023-10-20 11:20:21 -0500295 });
Gunnar Millsac6a4442020-10-14 14:55:29 -0500296}
297
Chris Caindfbf7de2023-04-13 16:01:04 -0500298/**
299 * @brief Translates throttle cause DBUS property to redfish.
300 *
301 * @param[in] dbusSource The throttle cause from DBUS
302 *
303 * @return Returns as a string, the throttle cause in Redfish terms. If
304 * translation cannot be done, returns "Unknown" throttle reason.
305 */
306inline processor::ThrottleCause
307 dbusToRfThrottleCause(const std::string& dbusSource)
308{
309 if (dbusSource ==
310 "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.ClockLimit")
311 {
312 return processor::ThrottleCause::ClockLimit;
313 }
314 if (dbusSource ==
315 "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.ManagementDetectedFault")
316 {
317 return processor::ThrottleCause::ManagementDetectedFault;
318 }
319 if (dbusSource ==
320 "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.PowerLimit")
321 {
322 return processor::ThrottleCause::PowerLimit;
323 }
324 if (dbusSource ==
325 "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.ThermalLimit")
326 {
327 return processor::ThrottleCause::ThermalLimit;
328 }
329 if (dbusSource ==
330 "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.Unknown")
331 {
332 return processor::ThrottleCause::Unknown;
333 }
334 return processor::ThrottleCause::Invalid;
335}
336
337inline void
Ed Tanousac106bf2023-06-07 09:24:59 -0700338 readThrottleProperties(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Chris Caindfbf7de2023-04-13 16:01:04 -0500339 const boost::system::error_code& ec,
340 const dbus::utility::DBusPropertiesMap& properties)
341{
342 if (ec)
343 {
Ed Tanous62598e32023-07-17 17:06:25 -0700344 BMCWEB_LOG_ERROR("Processor Throttle getAllProperties error {}", ec);
Ed Tanousac106bf2023-06-07 09:24:59 -0700345 messages::internalError(asyncResp->res);
Chris Caindfbf7de2023-04-13 16:01:04 -0500346 return;
347 }
348
349 const bool* status = nullptr;
350 const std::vector<std::string>* causes = nullptr;
351
352 if (!sdbusplus::unpackPropertiesNoThrow(dbus_utils::UnpackErrorPrinter(),
353 properties, "Throttled", status,
354 "ThrottleCauses", causes))
355 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700356 messages::internalError(asyncResp->res);
Chris Caindfbf7de2023-04-13 16:01:04 -0500357 return;
358 }
359
Ed Tanousac106bf2023-06-07 09:24:59 -0700360 asyncResp->res.jsonValue["Throttled"] = *status;
Chris Caindfbf7de2023-04-13 16:01:04 -0500361 nlohmann::json::array_t rCauses;
362 for (const std::string& cause : *causes)
363 {
364 processor::ThrottleCause rfCause = dbusToRfThrottleCause(cause);
365 if (rfCause == processor::ThrottleCause::Invalid)
366 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700367 messages::internalError(asyncResp->res);
Chris Caindfbf7de2023-04-13 16:01:04 -0500368 return;
369 }
370
371 rCauses.emplace_back(rfCause);
372 }
Ed Tanousac106bf2023-06-07 09:24:59 -0700373 asyncResp->res.jsonValue["ThrottleCauses"] = std::move(rCauses);
Chris Caindfbf7de2023-04-13 16:01:04 -0500374}
375
376inline void
Ed Tanousac106bf2023-06-07 09:24:59 -0700377 getThrottleProperties(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Chris Caindfbf7de2023-04-13 16:01:04 -0500378 const std::string& service,
379 const std::string& objectPath)
380{
Ed Tanous62598e32023-07-17 17:06:25 -0700381 BMCWEB_LOG_DEBUG("Get processor throttle resources");
Chris Caindfbf7de2023-04-13 16:01:04 -0500382
383 sdbusplus::asio::getAllProperties(
384 *crow::connections::systemBus, service, objectPath,
385 "xyz.openbmc_project.Control.Power.Throttle",
Ed Tanousac106bf2023-06-07 09:24:59 -0700386 [asyncResp](const boost::system::error_code& ec,
387 const dbus::utility::DBusPropertiesMap& properties) {
388 readThrottleProperties(asyncResp, ec, properties);
Patrick Williams5a39f772023-10-20 11:20:21 -0500389 });
Chris Caindfbf7de2023-04-13 16:01:04 -0500390}
391
Ed Tanousac106bf2023-06-07 09:24:59 -0700392inline void getCpuAssetData(std::shared_ptr<bmcweb::AsyncResp> asyncResp,
Gunnar Millsac6a4442020-10-14 14:55:29 -0500393 const std::string& service,
394 const std::string& objPath)
395{
Ed Tanous62598e32023-07-17 17:06:25 -0700396 BMCWEB_LOG_DEBUG("Get Cpu Asset Data");
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200397 sdbusplus::asio::getAllProperties(
398 *crow::connections::systemBus, service, objPath,
399 "xyz.openbmc_project.Inventory.Decorator.Asset",
Ed Tanousac106bf2023-06-07 09:24:59 -0700400 [objPath, asyncResp{std::move(asyncResp)}](
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800401 const boost::system::error_code& ec,
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200402 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700403 if (ec)
404 {
Ed Tanous62598e32023-07-17 17:06:25 -0700405 BMCWEB_LOG_DEBUG("DBUS response error");
Ed Tanousac106bf2023-06-07 09:24:59 -0700406 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -0700407 return;
408 }
409
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200410 const std::string* serialNumber = nullptr;
411 const std::string* model = nullptr;
412 const std::string* manufacturer = nullptr;
413 const std::string* partNumber = nullptr;
414 const std::string* sparePartNumber = nullptr;
415
416 const bool success = sdbusplus::unpackPropertiesNoThrow(
417 dbus_utils::UnpackErrorPrinter(), properties, "SerialNumber",
418 serialNumber, "Model", model, "Manufacturer", manufacturer,
419 "PartNumber", partNumber, "SparePartNumber", sparePartNumber);
420
421 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -0700422 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700423 messages::internalError(asyncResp->res);
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200424 return;
425 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700426
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200427 if (serialNumber != nullptr && !serialNumber->empty())
428 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700429 asyncResp->res.jsonValue["SerialNumber"] = *serialNumber;
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200430 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700431
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200432 if ((model != nullptr) && !model->empty())
433 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700434 asyncResp->res.jsonValue["Model"] = *model;
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200435 }
436
437 if (manufacturer != nullptr)
438 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700439 asyncResp->res.jsonValue["Manufacturer"] = *manufacturer;
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200440
441 // Otherwise would be unexpected.
442 if (manufacturer->find("Intel") != std::string::npos)
Ed Tanous002d39b2022-05-31 08:59:27 -0700443 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700444 asyncResp->res.jsonValue["ProcessorArchitecture"] = "x86";
445 asyncResp->res.jsonValue["InstructionSet"] = "x86-64";
Ed Tanous002d39b2022-05-31 08:59:27 -0700446 }
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200447 else if (manufacturer->find("IBM") != std::string::npos)
Ed Tanous002d39b2022-05-31 08:59:27 -0700448 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700449 asyncResp->res.jsonValue["ProcessorArchitecture"] = "Power";
450 asyncResp->res.jsonValue["InstructionSet"] = "PowerISA";
Ed Tanous002d39b2022-05-31 08:59:27 -0700451 }
452 }
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200453
454 if (partNumber != nullptr)
455 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700456 asyncResp->res.jsonValue["PartNumber"] = *partNumber;
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200457 }
458
Brad Bishop6169de22022-09-14 13:08:32 -0400459 if (sparePartNumber != nullptr && !sparePartNumber->empty())
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200460 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700461 asyncResp->res.jsonValue["SparePartNumber"] = *sparePartNumber;
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200462 }
Patrick Williams5a39f772023-10-20 11:20:21 -0500463 });
Gunnar Millsac6a4442020-10-14 14:55:29 -0500464}
465
Ed Tanousac106bf2023-06-07 09:24:59 -0700466inline void getCpuRevisionData(std::shared_ptr<bmcweb::AsyncResp> asyncResp,
Gunnar Millsac6a4442020-10-14 14:55:29 -0500467 const std::string& service,
468 const std::string& objPath)
469{
Ed Tanous62598e32023-07-17 17:06:25 -0700470 BMCWEB_LOG_DEBUG("Get Cpu Revision Data");
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200471 sdbusplus::asio::getAllProperties(
472 *crow::connections::systemBus, service, objPath,
473 "xyz.openbmc_project.Inventory.Decorator.Revision",
Ed Tanousac106bf2023-06-07 09:24:59 -0700474 [objPath, asyncResp{std::move(asyncResp)}](
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800475 const boost::system::error_code& ec,
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200476 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700477 if (ec)
478 {
Ed Tanous62598e32023-07-17 17:06:25 -0700479 BMCWEB_LOG_DEBUG("DBUS response error");
Ed Tanousac106bf2023-06-07 09:24:59 -0700480 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -0700481 return;
482 }
Gunnar Millsac6a4442020-10-14 14:55:29 -0500483
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200484 const std::string* version = nullptr;
485
486 const bool success = sdbusplus::unpackPropertiesNoThrow(
487 dbus_utils::UnpackErrorPrinter(), properties, "Version", version);
488
489 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -0700490 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700491 messages::internalError(asyncResp->res);
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200492 return;
Ed Tanous002d39b2022-05-31 08:59:27 -0700493 }
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200494
495 if (version != nullptr)
496 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700497 asyncResp->res.jsonValue["Version"] = *version;
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200498 }
Patrick Williams5a39f772023-10-20 11:20:21 -0500499 });
Gunnar Millsac6a4442020-10-14 14:55:29 -0500500}
501
zhanghch058d1b46d2021-04-01 11:18:24 +0800502inline void getAcceleratorDataByService(
Ed Tanousac106bf2023-06-07 09:24:59 -0700503 std::shared_ptr<bmcweb::AsyncResp> asyncResp, const std::string& acclrtrId,
zhanghch058d1b46d2021-04-01 11:18:24 +0800504 const std::string& service, const std::string& objPath)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500505{
Ed Tanous62598e32023-07-17 17:06:25 -0700506 BMCWEB_LOG_DEBUG("Get available system Accelerator resources by service.");
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200507 sdbusplus::asio::getAllProperties(
508 *crow::connections::systemBus, service, objPath, "",
Ed Tanousac106bf2023-06-07 09:24:59 -0700509 [acclrtrId, asyncResp{std::move(asyncResp)}](
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800510 const boost::system::error_code& ec,
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200511 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700512 if (ec)
513 {
Ed Tanous62598e32023-07-17 17:06:25 -0700514 BMCWEB_LOG_DEBUG("DBUS response error");
Ed Tanousac106bf2023-06-07 09:24:59 -0700515 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -0700516 return;
517 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700518
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200519 const bool* functional = nullptr;
520 const bool* present = nullptr;
521
522 const bool success = sdbusplus::unpackPropertiesNoThrow(
523 dbus_utils::UnpackErrorPrinter(), properties, "Functional",
524 functional, "Present", present);
525
526 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -0700527 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700528 messages::internalError(asyncResp->res);
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200529 return;
Ed Tanous002d39b2022-05-31 08:59:27 -0700530 }
Gunnar Millsac6a4442020-10-14 14:55:29 -0500531
Ed Tanous002d39b2022-05-31 08:59:27 -0700532 std::string state = "Enabled";
533 std::string health = "OK";
Gunnar Millsac6a4442020-10-14 14:55:29 -0500534
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200535 if (present != nullptr && !*present)
Ed Tanous002d39b2022-05-31 08:59:27 -0700536 {
537 state = "Absent";
538 }
539
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200540 if (functional != nullptr && !*functional)
Ed Tanous002d39b2022-05-31 08:59:27 -0700541 {
542 if (state == "Enabled")
Gunnar Millsac6a4442020-10-14 14:55:29 -0500543 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700544 health = "Critical";
Gunnar Millsac6a4442020-10-14 14:55:29 -0500545 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700546 }
Gunnar Millsac6a4442020-10-14 14:55:29 -0500547
Ed Tanousac106bf2023-06-07 09:24:59 -0700548 asyncResp->res.jsonValue["Id"] = acclrtrId;
549 asyncResp->res.jsonValue["Name"] = "Processor";
550 asyncResp->res.jsonValue["Status"]["State"] = state;
551 asyncResp->res.jsonValue["Status"]["Health"] = health;
552 asyncResp->res.jsonValue["ProcessorType"] = "Accelerator";
Patrick Williams5a39f772023-10-20 11:20:21 -0500553 });
Gunnar Millsac6a4442020-10-14 14:55:29 -0500554}
555
Jonathan Domandba0c292020-12-02 15:34:13 -0800556// OperatingConfig D-Bus Types
557using TurboProfileProperty = std::vector<std::tuple<uint32_t, size_t>>;
558using BaseSpeedPrioritySettingsProperty =
559 std::vector<std::tuple<uint32_t, std::vector<uint32_t>>>;
560// uint32_t and size_t may or may not be the same type, requiring a dedup'd
561// variant
Jonathan Domandba0c292020-12-02 15:34:13 -0800562
563/**
564 * Fill out the HighSpeedCoreIDs in a Processor resource from the given
565 * OperatingConfig D-Bus property.
566 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700567 * @param[in,out] asyncResp Async HTTP response.
Jonathan Domandba0c292020-12-02 15:34:13 -0800568 * @param[in] baseSpeedSettings Full list of base speed priority groups,
569 * to use to determine the list of high
570 * speed cores.
571 */
572inline void highSpeedCoreIdsHandler(
Ed Tanousac106bf2023-06-07 09:24:59 -0700573 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Jonathan Domandba0c292020-12-02 15:34:13 -0800574 const BaseSpeedPrioritySettingsProperty& baseSpeedSettings)
575{
576 // The D-Bus property does not indicate which bucket is the "high
577 // priority" group, so let's discern that by looking for the one with
578 // highest base frequency.
579 auto highPriorityGroup = baseSpeedSettings.cend();
580 uint32_t highestBaseSpeed = 0;
581 for (auto it = baseSpeedSettings.cbegin(); it != baseSpeedSettings.cend();
582 ++it)
583 {
584 const uint32_t baseFreq = std::get<uint32_t>(*it);
585 if (baseFreq > highestBaseSpeed)
586 {
587 highestBaseSpeed = baseFreq;
588 highPriorityGroup = it;
589 }
590 }
591
Ed Tanousac106bf2023-06-07 09:24:59 -0700592 nlohmann::json& jsonCoreIds = asyncResp->res.jsonValue["HighSpeedCoreIDs"];
Jonathan Domandba0c292020-12-02 15:34:13 -0800593 jsonCoreIds = nlohmann::json::array();
594
595 // There may not be any entries in the D-Bus property, so only populate
596 // if there was actually something there.
597 if (highPriorityGroup != baseSpeedSettings.cend())
598 {
599 jsonCoreIds = std::get<std::vector<uint32_t>>(*highPriorityGroup);
600 }
601}
602
603/**
604 * Fill out OperatingConfig related items in a Processor resource by requesting
605 * data from the given D-Bus object.
606 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700607 * @param[in,out] asyncResp Async HTTP response.
Jonathan Domandba0c292020-12-02 15:34:13 -0800608 * @param[in] cpuId CPU D-Bus name.
609 * @param[in] service D-Bus service to query.
610 * @param[in] objPath D-Bus object to query.
611 */
Ed Tanousac106bf2023-06-07 09:24:59 -0700612inline void
613 getCpuConfigData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
614 const std::string& cpuId, const std::string& service,
615 const std::string& objPath)
Jonathan Domandba0c292020-12-02 15:34:13 -0800616{
Ed Tanous62598e32023-07-17 17:06:25 -0700617 BMCWEB_LOG_INFO("Getting CPU operating configs for {}", cpuId);
Jonathan Domandba0c292020-12-02 15:34:13 -0800618
619 // First, GetAll CurrentOperatingConfig properties on the object
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200620 sdbusplus::asio::getAllProperties(
621 *crow::connections::systemBus, service, objPath,
622 "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig",
Ed Tanousac106bf2023-06-07 09:24:59 -0700623 [asyncResp, cpuId,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800624 service](const boost::system::error_code& ec,
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200625 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700626 if (ec)
627 {
Ed Tanous62598e32023-07-17 17:06:25 -0700628 BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec, ec.message());
Ed Tanousac106bf2023-06-07 09:24:59 -0700629 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -0700630 return;
631 }
Jonathan Domandba0c292020-12-02 15:34:13 -0800632
Ed Tanousac106bf2023-06-07 09:24:59 -0700633 nlohmann::json& json = asyncResp->res.jsonValue;
Jonathan Domandba0c292020-12-02 15:34:13 -0800634
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200635 const sdbusplus::message::object_path* appliedConfig = nullptr;
636 const bool* baseSpeedPriorityEnabled = nullptr;
637
638 const bool success = sdbusplus::unpackPropertiesNoThrow(
639 dbus_utils::UnpackErrorPrinter(), properties, "AppliedConfig",
640 appliedConfig, "BaseSpeedPriorityEnabled",
641 baseSpeedPriorityEnabled);
642
643 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -0700644 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700645 messages::internalError(asyncResp->res);
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200646 return;
Ed Tanous002d39b2022-05-31 08:59:27 -0700647 }
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200648
649 if (appliedConfig != nullptr)
650 {
651 const std::string& dbusPath = appliedConfig->str;
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200652 nlohmann::json::object_t operatingConfig;
Ed Tanousef4c65b2023-04-24 15:28:50 -0700653 operatingConfig["@odata.id"] = boost::urls::format(
654 "/redfish/v1/Systems/system/Processors/{}/OperatingConfigs",
655 cpuId);
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200656 json["OperatingConfigs"] = std::move(operatingConfig);
657
658 // Reuse the D-Bus config object name for the Redfish
659 // URI
660 size_t baseNamePos = dbusPath.rfind('/');
661 if (baseNamePos == std::string::npos ||
662 baseNamePos == (dbusPath.size() - 1))
663 {
664 // If the AppliedConfig was somehow not a valid path,
665 // skip adding any more properties, since everything
666 // else is tied to this applied config.
Ed Tanousac106bf2023-06-07 09:24:59 -0700667 messages::internalError(asyncResp->res);
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200668 return;
669 }
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200670 nlohmann::json::object_t appliedOperatingConfig;
Ed Tanousef4c65b2023-04-24 15:28:50 -0700671 appliedOperatingConfig["@odata.id"] = boost::urls::format(
672 "/redfish/v1/Systems/system/Processors/{}/OperatingConfigs/{}",
673 cpuId, dbusPath.substr(baseNamePos + 1));
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200674 json["AppliedOperatingConfig"] = std::move(appliedOperatingConfig);
675
676 // Once we found the current applied config, queue another
677 // request to read the base freq core ids out of that
678 // config.
679 sdbusplus::asio::getProperty<BaseSpeedPrioritySettingsProperty>(
680 *crow::connections::systemBus, service, dbusPath,
681 "xyz.openbmc_project.Inventory.Item.Cpu."
682 "OperatingConfig",
683 "BaseSpeedPrioritySettings",
Ed Tanousac106bf2023-06-07 09:24:59 -0700684 [asyncResp](
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800685 const boost::system::error_code& ec2,
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200686 const BaseSpeedPrioritySettingsProperty& baseSpeedList) {
687 if (ec2)
688 {
Ed Tanous62598e32023-07-17 17:06:25 -0700689 BMCWEB_LOG_WARNING("D-Bus Property Get error: {}", ec2);
Ed Tanousac106bf2023-06-07 09:24:59 -0700690 messages::internalError(asyncResp->res);
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200691 return;
692 }
693
Ed Tanousac106bf2023-06-07 09:24:59 -0700694 highSpeedCoreIdsHandler(asyncResp, baseSpeedList);
Patrick Williams5a39f772023-10-20 11:20:21 -0500695 });
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200696 }
697
698 if (baseSpeedPriorityEnabled != nullptr)
699 {
700 json["BaseSpeedPriorityState"] =
701 *baseSpeedPriorityEnabled ? "Enabled" : "Disabled";
702 }
Patrick Williams5a39f772023-10-20 11:20:21 -0500703 });
Jonathan Domandba0c292020-12-02 15:34:13 -0800704}
705
SunnySrivastava1984cba4f442021-01-07 12:48:16 -0600706/**
707 * @brief Fill out location info of a processor by
708 * requesting data from the given D-Bus object.
709 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700710 * @param[in,out] asyncResp Async HTTP response.
SunnySrivastava1984cba4f442021-01-07 12:48:16 -0600711 * @param[in] service D-Bus service to query.
712 * @param[in] objPath D-Bus object to query.
713 */
Ed Tanousac106bf2023-06-07 09:24:59 -0700714inline void getCpuLocationCode(std::shared_ptr<bmcweb::AsyncResp> asyncResp,
SunnySrivastava1984cba4f442021-01-07 12:48:16 -0600715 const std::string& service,
716 const std::string& objPath)
717{
Ed Tanous62598e32023-07-17 17:06:25 -0700718 BMCWEB_LOG_DEBUG("Get Cpu Location Data");
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700719 sdbusplus::asio::getProperty<std::string>(
720 *crow::connections::systemBus, service, objPath,
721 "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode",
Ed Tanousac106bf2023-06-07 09:24:59 -0700722 [objPath, asyncResp{std::move(asyncResp)}](
723 const boost::system::error_code& ec, const std::string& property) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700724 if (ec)
725 {
Ed Tanous62598e32023-07-17 17:06:25 -0700726 BMCWEB_LOG_DEBUG("DBUS response error");
Ed Tanousac106bf2023-06-07 09:24:59 -0700727 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -0700728 return;
729 }
SunnySrivastava1984cba4f442021-01-07 12:48:16 -0600730
Ed Tanousac106bf2023-06-07 09:24:59 -0700731 asyncResp->res.jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
Ed Tanous002d39b2022-05-31 08:59:27 -0700732 property;
Patrick Williams5a39f772023-10-20 11:20:21 -0500733 });
SunnySrivastava1984cba4f442021-01-07 12:48:16 -0600734}
735
Jonathan Domanc9514482021-02-24 09:20:51 -0800736/**
Jonathan Doman49e429c2021-03-03 13:11:44 -0800737 * Populate the unique identifier in a Processor resource by requesting data
738 * from the given D-Bus object.
739 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700740 * @param[in,out] asyncResp Async HTTP response.
Jonathan Doman49e429c2021-03-03 13:11:44 -0800741 * @param[in] service D-Bus service to query.
742 * @param[in] objPath D-Bus object to query.
743 */
Ed Tanousac106bf2023-06-07 09:24:59 -0700744inline void getCpuUniqueId(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Jonathan Doman49e429c2021-03-03 13:11:44 -0800745 const std::string& service,
746 const std::string& objectPath)
747{
Ed Tanous62598e32023-07-17 17:06:25 -0700748 BMCWEB_LOG_DEBUG("Get CPU UniqueIdentifier");
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700749 sdbusplus::asio::getProperty<std::string>(
750 *crow::connections::systemBus, service, objectPath,
751 "xyz.openbmc_project.Inventory.Decorator.UniqueIdentifier",
752 "UniqueIdentifier",
Ed Tanousac106bf2023-06-07 09:24:59 -0700753 [asyncResp](const boost::system::error_code& ec,
754 const std::string& id) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700755 if (ec)
756 {
Ed Tanous62598e32023-07-17 17:06:25 -0700757 BMCWEB_LOG_ERROR("Failed to read cpu unique id: {}", ec);
Ed Tanousac106bf2023-06-07 09:24:59 -0700758 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -0700759 return;
760 }
Ed Tanousac106bf2023-06-07 09:24:59 -0700761 asyncResp->res
762 .jsonValue["ProcessorId"]["ProtectedIdentificationNumber"] = id;
Patrick Williams5a39f772023-10-20 11:20:21 -0500763 });
Jonathan Doman49e429c2021-03-03 13:11:44 -0800764}
765
766/**
Jonathan Domanc9514482021-02-24 09:20:51 -0800767 * Find the D-Bus object representing the requested Processor, and call the
768 * handler with the results. If matching object is not found, add 404 error to
769 * response and don't call the handler.
770 *
771 * @param[in,out] resp Async HTTP response.
772 * @param[in] processorId Redfish Processor Id.
773 * @param[in] handler Callback to continue processing request upon
774 * successfully finding object.
775 */
776template <typename Handler>
zhanghch058d1b46d2021-04-01 11:18:24 +0800777inline void getProcessorObject(const std::shared_ptr<bmcweb::AsyncResp>& resp,
Jonathan Domanc9514482021-02-24 09:20:51 -0800778 const std::string& processorId,
779 Handler&& handler)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500780{
Ed Tanous62598e32023-07-17 17:06:25 -0700781 BMCWEB_LOG_DEBUG("Get available system processor resources.");
Gunnar Millsac6a4442020-10-14 14:55:29 -0500782
Jonathan Domanc9514482021-02-24 09:20:51 -0800783 // GetSubTree on all interfaces which provide info about a Processor
Chris Caindfbf7de2023-04-13 16:01:04 -0500784 constexpr std::array<std::string_view, 9> interfaces = {
George Liue99073f2022-12-09 11:06:16 +0800785 "xyz.openbmc_project.Common.UUID",
786 "xyz.openbmc_project.Inventory.Decorator.Asset",
787 "xyz.openbmc_project.Inventory.Decorator.Revision",
788 "xyz.openbmc_project.Inventory.Item.Cpu",
789 "xyz.openbmc_project.Inventory.Decorator.LocationCode",
790 "xyz.openbmc_project.Inventory.Item.Accelerator",
791 "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig",
Chris Caindfbf7de2023-04-13 16:01:04 -0500792 "xyz.openbmc_project.Inventory.Decorator.UniqueIdentifier",
793 "xyz.openbmc_project.Control.Power.Throttle"};
George Liue99073f2022-12-09 11:06:16 +0800794 dbus::utility::getSubTree(
795 "/xyz/openbmc_project/inventory", 0, interfaces,
Jonathan Domanc9514482021-02-24 09:20:51 -0800796 [resp, processorId, handler = std::forward<Handler>(handler)](
George Liue99073f2022-12-09 11:06:16 +0800797 const boost::system::error_code& ec,
798 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700799 if (ec)
800 {
Ed Tanous62598e32023-07-17 17:06:25 -0700801 BMCWEB_LOG_DEBUG("DBUS response error: {}", ec);
Ed Tanous002d39b2022-05-31 08:59:27 -0700802 messages::internalError(resp->res);
803 return;
804 }
805 for (const auto& [objectPath, serviceMap] : subtree)
806 {
807 // Ignore any objects which don't end with our desired cpu name
Ed Tanous11ba3972022-07-11 09:50:41 -0700808 if (!objectPath.ends_with(processorId))
Gunnar Millsac6a4442020-10-14 14:55:29 -0500809 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700810 continue;
Gunnar Millsac6a4442020-10-14 14:55:29 -0500811 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700812
813 bool found = false;
814 // Filter out objects that don't have the CPU-specific
815 // interfaces to make sure we can return 404 on non-CPUs
816 // (e.g. /redfish/../Processors/dimm0)
817 for (const auto& [serviceName, interfaceList] : serviceMap)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500818 {
Ed Tanous3544d2a2023-08-06 18:12:20 -0700819 if (std::ranges::find_first_of(interfaceList,
820 processorInterfaces) !=
821 std::end(interfaceList))
Gunnar Millsac6a4442020-10-14 14:55:29 -0500822 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700823 found = true;
824 break;
Jonathan Doman2bab9832020-12-02 15:27:40 -0800825 }
Gunnar Millsac6a4442020-10-14 14:55:29 -0500826 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700827
828 if (!found)
829 {
830 continue;
831 }
832
833 // Process the first object which does match our cpu name and
834 // required interfaces, and potentially ignore any other
835 // matching objects. Assume all interfaces we want to process
836 // must be on the same object path.
837
Ed Tanous8a592812022-06-04 09:06:59 -0700838 handler(objectPath, serviceMap);
Ed Tanous002d39b2022-05-31 08:59:27 -0700839 return;
840 }
841 messages::resourceNotFound(resp->res, "Processor", processorId);
Patrick Williams5a39f772023-10-20 11:20:21 -0500842 });
Gunnar Millsac6a4442020-10-14 14:55:29 -0500843}
844
Ed Tanousac106bf2023-06-07 09:24:59 -0700845inline void
846 getProcessorData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
847 const std::string& processorId,
848 const std::string& objectPath,
849 const dbus::utility::MapperServiceMap& serviceMap)
Jonathan Domanc9514482021-02-24 09:20:51 -0800850{
851 for (const auto& [serviceName, interfaceList] : serviceMap)
852 {
853 for (const auto& interface : interfaceList)
854 {
855 if (interface == "xyz.openbmc_project.Inventory.Decorator.Asset")
856 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700857 getCpuAssetData(asyncResp, serviceName, objectPath);
Jonathan Domanc9514482021-02-24 09:20:51 -0800858 }
George Liu0fda0f12021-11-16 10:06:17 +0800859 else if (interface ==
860 "xyz.openbmc_project.Inventory.Decorator.Revision")
Jonathan Domanc9514482021-02-24 09:20:51 -0800861 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700862 getCpuRevisionData(asyncResp, serviceName, objectPath);
Jonathan Domanc9514482021-02-24 09:20:51 -0800863 }
864 else if (interface == "xyz.openbmc_project.Inventory.Item.Cpu")
865 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700866 getCpuDataByService(asyncResp, processorId, serviceName,
Jonathan Domanc9514482021-02-24 09:20:51 -0800867 objectPath);
868 }
George Liu0fda0f12021-11-16 10:06:17 +0800869 else if (interface ==
870 "xyz.openbmc_project.Inventory.Item.Accelerator")
Jonathan Domanc9514482021-02-24 09:20:51 -0800871 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700872 getAcceleratorDataByService(asyncResp, processorId, serviceName,
Jonathan Domanc9514482021-02-24 09:20:51 -0800873 objectPath);
874 }
George Liu0fda0f12021-11-16 10:06:17 +0800875 else if (
876 interface ==
877 "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig")
Jonathan Domanc9514482021-02-24 09:20:51 -0800878 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700879 getCpuConfigData(asyncResp, processorId, serviceName,
880 objectPath);
Jonathan Domanc9514482021-02-24 09:20:51 -0800881 }
George Liu0fda0f12021-11-16 10:06:17 +0800882 else if (interface ==
883 "xyz.openbmc_project.Inventory.Decorator.LocationCode")
Jonathan Domanc9514482021-02-24 09:20:51 -0800884 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700885 getCpuLocationCode(asyncResp, serviceName, objectPath);
Jonathan Domanc9514482021-02-24 09:20:51 -0800886 }
Sharad Yadav71b82f22021-05-10 15:11:39 +0530887 else if (interface == "xyz.openbmc_project.Common.UUID")
888 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700889 getProcessorUUID(asyncResp, serviceName, objectPath);
Sharad Yadav71b82f22021-05-10 15:11:39 +0530890 }
George Liu0fda0f12021-11-16 10:06:17 +0800891 else if (interface ==
892 "xyz.openbmc_project.Inventory.Decorator.UniqueIdentifier")
Jonathan Doman49e429c2021-03-03 13:11:44 -0800893 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700894 getCpuUniqueId(asyncResp, serviceName, objectPath);
Jonathan Doman49e429c2021-03-03 13:11:44 -0800895 }
Chris Caindfbf7de2023-04-13 16:01:04 -0500896 else if (interface == "xyz.openbmc_project.Control.Power.Throttle")
897 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700898 getThrottleProperties(asyncResp, serviceName, objectPath);
Chris Caindfbf7de2023-04-13 16:01:04 -0500899 }
Jonathan Domanc9514482021-02-24 09:20:51 -0800900 }
901 }
902}
903
Jonathan Domandba0c292020-12-02 15:34:13 -0800904/**
905 * Request all the properties for the given D-Bus object and fill out the
906 * related entries in the Redfish OperatingConfig response.
907 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700908 * @param[in,out] asyncResp Async HTTP response.
Jonathan Domandba0c292020-12-02 15:34:13 -0800909 * @param[in] service D-Bus service name to query.
910 * @param[in] objPath D-Bus object to query.
911 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800912inline void
Ed Tanousac106bf2023-06-07 09:24:59 -0700913 getOperatingConfigData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
zhanghch058d1b46d2021-04-01 11:18:24 +0800914 const std::string& service,
915 const std::string& objPath)
Jonathan Domandba0c292020-12-02 15:34:13 -0800916{
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200917 sdbusplus::asio::getAllProperties(
918 *crow::connections::systemBus, service, objPath,
919 "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig",
Ed Tanousac106bf2023-06-07 09:24:59 -0700920 [asyncResp](const boost::system::error_code& ec,
921 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700922 if (ec)
923 {
Ed Tanous62598e32023-07-17 17:06:25 -0700924 BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec, ec.message());
Ed Tanousac106bf2023-06-07 09:24:59 -0700925 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -0700926 return;
927 }
928
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200929 const size_t* availableCoreCount = nullptr;
930 const uint32_t* baseSpeed = nullptr;
931 const uint32_t* maxJunctionTemperature = nullptr;
932 const uint32_t* maxSpeed = nullptr;
933 const uint32_t* powerLimit = nullptr;
934 const TurboProfileProperty* turboProfile = nullptr;
935 const BaseSpeedPrioritySettingsProperty* baseSpeedPrioritySettings =
936 nullptr;
937
938 const bool success = sdbusplus::unpackPropertiesNoThrow(
939 dbus_utils::UnpackErrorPrinter(), properties, "AvailableCoreCount",
940 availableCoreCount, "BaseSpeed", baseSpeed,
941 "MaxJunctionTemperature", maxJunctionTemperature, "MaxSpeed",
942 maxSpeed, "PowerLimit", powerLimit, "TurboProfile", turboProfile,
943 "BaseSpeedPrioritySettings", baseSpeedPrioritySettings);
944
945 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -0700946 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700947 messages::internalError(asyncResp->res);
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200948 return;
949 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700950
Ed Tanousac106bf2023-06-07 09:24:59 -0700951 nlohmann::json& json = asyncResp->res.jsonValue;
Ed Tanous002d39b2022-05-31 08:59:27 -0700952
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200953 if (availableCoreCount != nullptr)
954 {
955 json["TotalAvailableCoreCount"] = *availableCoreCount;
956 }
957
958 if (baseSpeed != nullptr)
959 {
960 json["BaseSpeedMHz"] = *baseSpeed;
961 }
962
963 if (maxJunctionTemperature != nullptr)
964 {
965 json["MaxJunctionTemperatureCelsius"] = *maxJunctionTemperature;
966 }
967
968 if (maxSpeed != nullptr)
969 {
970 json["MaxSpeedMHz"] = *maxSpeed;
971 }
972
973 if (powerLimit != nullptr)
974 {
975 json["TDPWatts"] = *powerLimit;
976 }
977
978 if (turboProfile != nullptr)
979 {
980 nlohmann::json& turboArray = json["TurboProfile"];
981 turboArray = nlohmann::json::array();
982 for (const auto& [turboSpeed, coreCount] : *turboProfile)
983 {
984 nlohmann::json::object_t turbo;
985 turbo["ActiveCoreCount"] = coreCount;
986 turbo["MaxSpeedMHz"] = turboSpeed;
Patrick Williamsb2ba3072023-05-12 10:27:39 -0500987 turboArray.emplace_back(std::move(turbo));
Ed Tanous002d39b2022-05-31 08:59:27 -0700988 }
989 }
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200990
991 if (baseSpeedPrioritySettings != nullptr)
992 {
993 nlohmann::json& baseSpeedArray = json["BaseSpeedPrioritySettings"];
994 baseSpeedArray = nlohmann::json::array();
995 for (const auto& [baseSpeedMhz, coreList] :
996 *baseSpeedPrioritySettings)
997 {
998 nlohmann::json::object_t speed;
999 speed["CoreCount"] = coreList.size();
1000 speed["CoreIDs"] = coreList;
1001 speed["BaseSpeedMHz"] = baseSpeedMhz;
Patrick Williamsb2ba3072023-05-12 10:27:39 -05001002 baseSpeedArray.emplace_back(std::move(speed));
Krzysztof Grobelny351053f2022-07-28 15:44:22 +02001003 }
1004 }
Patrick Williams5a39f772023-10-20 11:20:21 -05001005 });
Jonathan Domandba0c292020-12-02 15:34:13 -08001006}
1007
Jonathan Doman3cde86f2020-12-02 14:50:45 -08001008/**
1009 * Handle the D-Bus response from attempting to set the CPU's AppliedConfig
1010 * property. Main task is to translate error messages into Redfish errors.
1011 *
1012 * @param[in,out] resp HTTP response.
1013 * @param[in] setPropVal Value which we attempted to set.
1014 * @param[in] ec D-Bus response error code.
1015 * @param[in] msg D-Bus response message.
1016 */
1017inline void
1018 handleAppliedConfigResponse(const std::shared_ptr<bmcweb::AsyncResp>& resp,
1019 const std::string& setPropVal,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001020 const boost::system::error_code& ec,
Patrick Williams59d494e2022-07-22 19:26:55 -05001021 const sdbusplus::message_t& msg)
Jonathan Doman3cde86f2020-12-02 14:50:45 -08001022{
1023 if (!ec)
1024 {
Ed Tanous62598e32023-07-17 17:06:25 -07001025 BMCWEB_LOG_DEBUG("Set Property succeeded");
Jonathan Doman3cde86f2020-12-02 14:50:45 -08001026 return;
1027 }
1028
Ed Tanous62598e32023-07-17 17:06:25 -07001029 BMCWEB_LOG_DEBUG("Set Property failed: {}", ec);
Jonathan Doman3cde86f2020-12-02 14:50:45 -08001030
1031 const sd_bus_error* dbusError = msg.get_error();
1032 if (dbusError == nullptr)
1033 {
1034 messages::internalError(resp->res);
1035 return;
1036 }
1037
1038 // The asio error code doesn't know about our custom errors, so we have to
1039 // parse the error string. Some of these D-Bus -> Redfish translations are a
1040 // stretch, but it's good to try to communicate something vaguely useful.
1041 if (strcmp(dbusError->name,
1042 "xyz.openbmc_project.Common.Error.InvalidArgument") == 0)
1043 {
1044 // Service did not like the object_path we tried to set.
1045 messages::propertyValueIncorrect(
1046 resp->res, "AppliedOperatingConfig/@odata.id", setPropVal);
1047 }
1048 else if (strcmp(dbusError->name,
1049 "xyz.openbmc_project.Common.Error.NotAllowed") == 0)
1050 {
1051 // Service indicates we can never change the config for this processor.
1052 messages::propertyNotWritable(resp->res, "AppliedOperatingConfig");
1053 }
1054 else if (strcmp(dbusError->name,
1055 "xyz.openbmc_project.Common.Error.Unavailable") == 0)
1056 {
1057 // Service indicates the config cannot be changed right now, but maybe
1058 // in a different system state.
1059 messages::resourceInStandby(resp->res);
1060 }
Jonathan Doman3cde86f2020-12-02 14:50:45 -08001061 else
1062 {
1063 messages::internalError(resp->res);
1064 }
1065}
1066
1067/**
1068 * Handle the PATCH operation of the AppliedOperatingConfig property. Do basic
1069 * validation of the input data, and then set the D-Bus property.
1070 *
1071 * @param[in,out] resp Async HTTP response.
1072 * @param[in] processorId Processor's Id.
1073 * @param[in] appliedConfigUri New property value to apply.
1074 * @param[in] cpuObjectPath Path of CPU object to modify.
1075 * @param[in] serviceMap Service map for CPU object.
1076 */
1077inline void patchAppliedOperatingConfig(
1078 const std::shared_ptr<bmcweb::AsyncResp>& resp,
1079 const std::string& processorId, const std::string& appliedConfigUri,
Shantappa Teekappanavar5df6eda2022-01-18 12:29:28 -06001080 const std::string& cpuObjectPath,
1081 const dbus::utility::MapperServiceMap& serviceMap)
Jonathan Doman3cde86f2020-12-02 14:50:45 -08001082{
1083 // Check that the property even exists by checking for the interface
1084 const std::string* controlService = nullptr;
1085 for (const auto& [serviceName, interfaceList] : serviceMap)
1086 {
Ed Tanous3544d2a2023-08-06 18:12:20 -07001087 if (std::ranges::find(interfaceList,
1088 "xyz.openbmc_project.Control.Processor."
1089 "CurrentOperatingConfig") != interfaceList.end())
Jonathan Doman3cde86f2020-12-02 14:50:45 -08001090 {
1091 controlService = &serviceName;
1092 break;
1093 }
1094 }
1095
1096 if (controlService == nullptr)
1097 {
1098 messages::internalError(resp->res);
1099 return;
1100 }
1101
1102 // Check that the config URI is a child of the cpu URI being patched.
1103 std::string expectedPrefix("/redfish/v1/Systems/system/Processors/");
1104 expectedPrefix += processorId;
1105 expectedPrefix += "/OperatingConfigs/";
Ed Tanous11ba3972022-07-11 09:50:41 -07001106 if (!appliedConfigUri.starts_with(expectedPrefix) ||
Jonathan Doman3cde86f2020-12-02 14:50:45 -08001107 expectedPrefix.size() == appliedConfigUri.size())
1108 {
1109 messages::propertyValueIncorrect(
1110 resp->res, "AppliedOperatingConfig/@odata.id", appliedConfigUri);
1111 return;
1112 }
1113
1114 // Generate the D-Bus path of the OperatingConfig object, by assuming it's a
1115 // direct child of the CPU object.
1116 // Strip the expectedPrefix from the config URI to get the "filename", and
1117 // append to the CPU's path.
1118 std::string configBaseName = appliedConfigUri.substr(expectedPrefix.size());
1119 sdbusplus::message::object_path configPath(cpuObjectPath);
1120 configPath /= configBaseName;
1121
Ed Tanous62598e32023-07-17 17:06:25 -07001122 BMCWEB_LOG_INFO("Setting config to {}", configPath.str);
Jonathan Doman3cde86f2020-12-02 14:50:45 -08001123
1124 // Set the property, with handler to check error responses
George Liu9ae226f2023-06-21 17:56:46 +08001125 sdbusplus::asio::setProperty(
1126 *crow::connections::systemBus, *controlService, cpuObjectPath,
1127 "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig",
1128 "AppliedConfig", configPath,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001129 [resp, appliedConfigUri](const boost::system::error_code& ec,
Patrick Williams59d494e2022-07-22 19:26:55 -05001130 const sdbusplus::message_t& msg) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001131 handleAppliedConfigResponse(resp, appliedConfigUri, ec, msg);
Patrick Williams5a39f772023-10-20 11:20:21 -05001132 });
Jonathan Doman3cde86f2020-12-02 14:50:45 -08001133}
1134
Ed Tanousac106bf2023-06-07 09:24:59 -07001135inline void
1136 handleProcessorHead(crow::App& app, const crow::Request& req,
1137 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1138 const std::string& /* systemName */,
1139 const std::string& /* processorId */)
Nikhil Namjoshi71a24ca2022-11-11 01:52:32 +00001140{
Ed Tanousac106bf2023-06-07 09:24:59 -07001141 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Nikhil Namjoshi71a24ca2022-11-11 01:52:32 +00001142 {
1143 return;
1144 }
Ed Tanousac106bf2023-06-07 09:24:59 -07001145 asyncResp->res.addHeader(
Nikhil Namjoshi71a24ca2022-11-11 01:52:32 +00001146 boost::beast::http::field::link,
1147 "</redfish/v1/JsonSchemas/Processor/Processor.json>; rel=describedby");
1148}
1149
1150inline void handleProcessorCollectionHead(
1151 crow::App& app, const crow::Request& req,
Ed Tanousac106bf2023-06-07 09:24:59 -07001152 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Nikhil Namjoshi71a24ca2022-11-11 01:52:32 +00001153 const std::string& /* systemName */)
1154{
Ed Tanousac106bf2023-06-07 09:24:59 -07001155 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Nikhil Namjoshi71a24ca2022-11-11 01:52:32 +00001156 {
1157 return;
1158 }
Ed Tanousac106bf2023-06-07 09:24:59 -07001159 asyncResp->res.addHeader(
Nikhil Namjoshi71a24ca2022-11-11 01:52:32 +00001160 boost::beast::http::field::link,
1161 "</redfish/v1/JsonSchemas/ProcessorCollection/ProcessorCollection.json>; rel=describedby");
1162}
1163
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001164inline void requestRoutesOperatingConfigCollection(App& app)
Jonathan Domandba0c292020-12-02 15:34:13 -08001165{
Ed Tanous7f3e84a2022-12-28 16:22:54 -08001166 BMCWEB_ROUTE(app,
1167 "/redfish/v1/Systems/<str>/Processors/<str>/OperatingConfigs/")
Ed Tanoused398212021-06-09 17:05:54 -07001168 .privileges(redfish::privileges::getOperatingConfigCollection)
Ed Tanous002d39b2022-05-31 08:59:27 -07001169 .methods(boost::beast::http::verb::get)(
1170 [&app](const crow::Request& req,
1171 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous7f3e84a2022-12-28 16:22:54 -08001172 const std::string& systemName, const std::string& cpuName) {
Carson Labrado3ba00072022-06-06 19:40:56 +00001173 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07001174 {
1175 return;
1176 }
Ed Tanous7f3e84a2022-12-28 16:22:54 -08001177
1178 if constexpr (bmcwebEnableMultiHost)
1179 {
1180 // Option currently returns no systems. TBD
1181 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1182 systemName);
1183 return;
1184 }
1185
1186 if (systemName != "system")
1187 {
1188 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1189 systemName);
1190 return;
1191 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001192 asyncResp->res.jsonValue["@odata.type"] =
1193 "#OperatingConfigCollection.OperatingConfigCollection";
Ed Tanousef4c65b2023-04-24 15:28:50 -07001194 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
1195 "/redfish/v1/Systems/system/Processors/{}/OperatingConfigs",
1196 cpuName);
Ed Tanous002d39b2022-05-31 08:59:27 -07001197 asyncResp->res.jsonValue["Name"] = "Operating Config Collection";
1198
1199 // First find the matching CPU object so we know how to
1200 // constrain our search for related Config objects.
George Liu7a1dbc42022-12-07 16:03:22 +08001201 const std::array<std::string_view, 1> interfaces = {
1202 "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig"};
1203 dbus::utility::getSubTreePaths(
1204 "/xyz/openbmc_project/inventory", 0, interfaces,
Ed Tanous002d39b2022-05-31 08:59:27 -07001205 [asyncResp, cpuName](
George Liu7a1dbc42022-12-07 16:03:22 +08001206 const boost::system::error_code& ec,
Ed Tanous002d39b2022-05-31 08:59:27 -07001207 const dbus::utility::MapperGetSubTreePathsResponse& objects) {
1208 if (ec)
Ed Tanous45ca1b82022-03-25 13:07:27 -07001209 {
Ed Tanous62598e32023-07-17 17:06:25 -07001210 BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec, ec.message());
Ed Tanous002d39b2022-05-31 08:59:27 -07001211 messages::internalError(asyncResp->res);
Ed Tanous45ca1b82022-03-25 13:07:27 -07001212 return;
1213 }
Jonathan Domandba0c292020-12-02 15:34:13 -08001214
Ed Tanous002d39b2022-05-31 08:59:27 -07001215 for (const std::string& object : objects)
1216 {
Ed Tanous11ba3972022-07-11 09:50:41 -07001217 if (!object.ends_with(cpuName))
Ed Tanous002d39b2022-05-31 08:59:27 -07001218 {
1219 continue;
1220 }
George Liu0fda0f12021-11-16 10:06:17 +08001221
Ed Tanous002d39b2022-05-31 08:59:27 -07001222 // Not expected that there will be multiple matching
1223 // CPU objects, but if there are just use the first
1224 // one.
Jonathan Domandba0c292020-12-02 15:34:13 -08001225
Ed Tanous002d39b2022-05-31 08:59:27 -07001226 // Use the common search routine to construct the
1227 // Collection of all Config objects under this CPU.
Patrick Williams5a39f772023-10-20 11:20:21 -05001228 constexpr std::array<std::string_view, 1> interface{
1229 "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig"};
Ed Tanous002d39b2022-05-31 08:59:27 -07001230 collection_util::getCollectionMembers(
1231 asyncResp,
Ed Tanousef4c65b2023-04-24 15:28:50 -07001232 boost::urls::format(
1233 "/redfish/v1/Systems/system/Processors/{}/OperatingConfigs",
1234 cpuName),
Lakshmi Yadlapati36b5f1e2023-09-26 23:53:28 -05001235 interface, object);
Ed Tanous002d39b2022-05-31 08:59:27 -07001236 return;
1237 }
George Liu0fda0f12021-11-16 10:06:17 +08001238 });
Patrick Williams5a39f772023-10-20 11:20:21 -05001239 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001240}
1241
1242inline void requestRoutesOperatingConfig(App& app)
1243{
1244 BMCWEB_ROUTE(
1245 app,
Ed Tanous7f3e84a2022-12-28 16:22:54 -08001246 "/redfish/v1/Systems/<str>/Processors/<str>/OperatingConfigs/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001247 .privileges(redfish::privileges::getOperatingConfig)
Ed Tanous002d39b2022-05-31 08:59:27 -07001248 .methods(boost::beast::http::verb::get)(
1249 [&app](const crow::Request& req,
1250 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous7f3e84a2022-12-28 16:22:54 -08001251 const std::string& systemName, const std::string& cpuName,
1252 const std::string& configName) {
Carson Labrado3ba00072022-06-06 19:40:56 +00001253 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07001254 {
1255 return;
1256 }
Ed Tanous7f3e84a2022-12-28 16:22:54 -08001257 if constexpr (bmcwebEnableMultiHost)
1258 {
1259 // Option currently returns no systems. TBD
1260 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1261 systemName);
1262 return;
1263 }
1264
1265 if (systemName != "system")
1266 {
1267 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1268 systemName);
1269 return;
1270 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001271 // Ask for all objects implementing OperatingConfig so we can search
1272 // for one with a matching name
George Liue99073f2022-12-09 11:06:16 +08001273 constexpr std::array<std::string_view, 1> interfaces = {
1274 "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig"};
1275 dbus::utility::getSubTree(
1276 "/xyz/openbmc_project/inventory", 0, interfaces,
Ed Tanous39662a32023-02-06 15:09:46 -08001277 [asyncResp, cpuName, configName](
George Liue99073f2022-12-09 11:06:16 +08001278 const boost::system::error_code& ec,
Ed Tanous002d39b2022-05-31 08:59:27 -07001279 const dbus::utility::MapperGetSubTreeResponse& subtree) {
1280 if (ec)
Ed Tanous45ca1b82022-03-25 13:07:27 -07001281 {
Ed Tanous62598e32023-07-17 17:06:25 -07001282 BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec, ec.message());
Ed Tanous002d39b2022-05-31 08:59:27 -07001283 messages::internalError(asyncResp->res);
Ed Tanous45ca1b82022-03-25 13:07:27 -07001284 return;
1285 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001286 const std::string expectedEnding = cpuName + '/' + configName;
1287 for (const auto& [objectPath, serviceMap] : subtree)
1288 {
1289 // Ignore any configs without matching cpuX/configY
Ed Tanous11ba3972022-07-11 09:50:41 -07001290 if (!objectPath.ends_with(expectedEnding) || serviceMap.empty())
Ed Tanous002d39b2022-05-31 08:59:27 -07001291 {
1292 continue;
1293 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001294
Ed Tanous002d39b2022-05-31 08:59:27 -07001295 nlohmann::json& json = asyncResp->res.jsonValue;
1296 json["@odata.type"] = "#OperatingConfig.v1_0_0.OperatingConfig";
Ed Tanousef4c65b2023-04-24 15:28:50 -07001297 json["@odata.id"] = boost::urls::format(
1298 "/redfish/v1/Systems/system/Processors/{}/OperatingConfigs/{}",
1299 cpuName, configName);
Ed Tanous002d39b2022-05-31 08:59:27 -07001300 json["Name"] = "Processor Profile";
1301 json["Id"] = configName;
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001302
Ed Tanous002d39b2022-05-31 08:59:27 -07001303 // Just use the first implementation of the object - not
1304 // expected that there would be multiple matching
1305 // services
1306 getOperatingConfigData(asyncResp, serviceMap.begin()->first,
1307 objectPath);
1308 return;
1309 }
1310 messages::resourceNotFound(asyncResp->res, "OperatingConfig",
1311 configName);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001312 });
Patrick Williams5a39f772023-10-20 11:20:21 -05001313 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001314}
Jonathan Domandba0c292020-12-02 15:34:13 -08001315
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001316inline void requestRoutesProcessorCollection(App& app)
Gunnar Millsac6a4442020-10-14 14:55:29 -05001317{
Gunnar Millsac6a4442020-10-14 14:55:29 -05001318 /**
1319 * Functions triggers appropriate requests on DBus
1320 */
Ed Tanous22d268c2022-05-19 09:39:07 -07001321 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/")
Nikhil Namjoshi71a24ca2022-11-11 01:52:32 +00001322 .privileges(redfish::privileges::headProcessorCollection)
1323 .methods(boost::beast::http::verb::head)(
1324 std::bind_front(handleProcessorCollectionHead, std::ref(app)));
1325
1326 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/")
Ed Tanoused398212021-06-09 17:05:54 -07001327 .privileges(redfish::privileges::getProcessorCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001328 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07001329 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07001330 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1331 const std::string& systemName) {
Carson Labrado3ba00072022-06-06 19:40:56 +00001332 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07001333 {
1334 return;
1335 }
Ed Tanous7f3e84a2022-12-28 16:22:54 -08001336 if constexpr (bmcwebEnableMultiHost)
1337 {
1338 // Option currently returns no systems. TBD
1339 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1340 systemName);
1341 return;
1342 }
1343
Ed Tanous22d268c2022-05-19 09:39:07 -07001344 if (systemName != "system")
1345 {
1346 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1347 systemName);
1348 return;
1349 }
1350
Nikhil Namjoshi71a24ca2022-11-11 01:52:32 +00001351 asyncResp->res.addHeader(
1352 boost::beast::http::field::link,
1353 "</redfish/v1/JsonSchemas/ProcessorCollection/ProcessorCollection.json>; rel=describedby");
1354
Ed Tanous002d39b2022-05-31 08:59:27 -07001355 asyncResp->res.jsonValue["@odata.type"] =
1356 "#ProcessorCollection.ProcessorCollection";
1357 asyncResp->res.jsonValue["Name"] = "Processor Collection";
Gunnar Millsac6a4442020-10-14 14:55:29 -05001358
Ed Tanous002d39b2022-05-31 08:59:27 -07001359 asyncResp->res.jsonValue["@odata.id"] =
1360 "/redfish/v1/Systems/system/Processors";
Gunnar Millsac6a4442020-10-14 14:55:29 -05001361
Ed Tanous002d39b2022-05-31 08:59:27 -07001362 collection_util::getCollectionMembers(
Willy Tuae9031f2022-09-27 05:48:07 +00001363 asyncResp,
1364 boost::urls::url("/redfish/v1/Systems/system/Processors"),
Lakshmi Yadlapati36b5f1e2023-09-26 23:53:28 -05001365 processorInterfaces, "/xyz/openbmc_project/inventory");
Patrick Williams5a39f772023-10-20 11:20:21 -05001366 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001367}
Gunnar Millsac6a4442020-10-14 14:55:29 -05001368
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001369inline void requestRoutesProcessor(App& app)
Gunnar Millsac6a4442020-10-14 14:55:29 -05001370{
Gunnar Millsac6a4442020-10-14 14:55:29 -05001371 /**
1372 * Functions triggers appropriate requests on DBus
1373 */
Gunnar Millsac6a4442020-10-14 14:55:29 -05001374
Ed Tanous22d268c2022-05-19 09:39:07 -07001375 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/<str>/")
Nikhil Namjoshi71a24ca2022-11-11 01:52:32 +00001376 .privileges(redfish::privileges::headProcessor)
1377 .methods(boost::beast::http::verb::head)(
1378 std::bind_front(handleProcessorHead, std::ref(app)));
1379
1380 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001381 .privileges(redfish::privileges::getProcessor)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001382 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07001383 [&app](const crow::Request& req,
1384 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous22d268c2022-05-19 09:39:07 -07001385 const std::string& systemName,
Ed Tanous45ca1b82022-03-25 13:07:27 -07001386 const std::string& processorId) {
Carson Labrado3ba00072022-06-06 19:40:56 +00001387 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07001388 {
1389 return;
1390 }
Ed Tanous7f3e84a2022-12-28 16:22:54 -08001391 if constexpr (bmcwebEnableMultiHost)
1392 {
1393 // Option currently returns no systems. TBD
1394 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1395 systemName);
1396 return;
1397 }
Ed Tanous22d268c2022-05-19 09:39:07 -07001398 if (systemName != "system")
1399 {
1400 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1401 systemName);
1402 return;
1403 }
1404
Nikhil Namjoshi71a24ca2022-11-11 01:52:32 +00001405 asyncResp->res.addHeader(
1406 boost::beast::http::field::link,
1407 "</redfish/v1/JsonSchemas/Processor/Processor.json>; rel=describedby");
Ed Tanous002d39b2022-05-31 08:59:27 -07001408 asyncResp->res.jsonValue["@odata.type"] =
Chris Caindfbf7de2023-04-13 16:01:04 -05001409 "#Processor.v1_18_0.Processor";
Ed Tanousef4c65b2023-04-24 15:28:50 -07001410 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
1411 "/redfish/v1/Systems/system/Processors/{}", processorId);
Jonathan Doman3cde86f2020-12-02 14:50:45 -08001412
Ed Tanous8a592812022-06-04 09:06:59 -07001413 getProcessorObject(
1414 asyncResp, processorId,
1415 std::bind_front(getProcessorData, asyncResp, processorId));
Patrick Williams5a39f772023-10-20 11:20:21 -05001416 });
Jonathan Doman3cde86f2020-12-02 14:50:45 -08001417
Ed Tanous22d268c2022-05-19 09:39:07 -07001418 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001419 .privileges(redfish::privileges::patchProcessor)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001420 .methods(boost::beast::http::verb::patch)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07001421 [&app](const crow::Request& req,
1422 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous22d268c2022-05-19 09:39:07 -07001423 const std::string& systemName,
Ed Tanous45ca1b82022-03-25 13:07:27 -07001424 const std::string& processorId) {
Carson Labrado3ba00072022-06-06 19:40:56 +00001425 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07001426 {
1427 return;
1428 }
Ed Tanous7f3e84a2022-12-28 16:22:54 -08001429 if constexpr (bmcwebEnableMultiHost)
1430 {
1431 // Option currently returns no systems. TBD
1432 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1433 systemName);
1434 return;
1435 }
Ed Tanous22d268c2022-05-19 09:39:07 -07001436 if (systemName != "system")
1437 {
1438 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1439 systemName);
1440 return;
1441 }
1442
Ed Tanous3c569212024-03-06 14:46:18 -08001443 std::optional<std::string> appliedConfigUri;
Ed Tanous002d39b2022-05-31 08:59:27 -07001444 if (!json_util::readJsonPatch(req, asyncResp->res,
Ed Tanous3c569212024-03-06 14:46:18 -08001445 "AppliedOperatingConfig/@odata.id",
1446 appliedConfigUri))
Ed Tanous002d39b2022-05-31 08:59:27 -07001447 {
1448 return;
1449 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001450
Ed Tanous3c569212024-03-06 14:46:18 -08001451 if (appliedConfigUri)
Ed Tanous002d39b2022-05-31 08:59:27 -07001452 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001453 // Check for 404 and find matching D-Bus object, then run
1454 // property patch handlers if that all succeeds.
Ed Tanous8a592812022-06-04 09:06:59 -07001455 getProcessorObject(asyncResp, processorId,
1456 std::bind_front(patchAppliedOperatingConfig,
1457 asyncResp, processorId,
Ed Tanous3c569212024-03-06 14:46:18 -08001458 *appliedConfigUri));
Ed Tanous002d39b2022-05-31 08:59:27 -07001459 }
Patrick Williams5a39f772023-10-20 11:20:21 -05001460 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001461}
Gunnar Millsac6a4442020-10-14 14:55:29 -05001462
1463} // namespace redfish