blob: ff17ebdcc3d59b8f417d720e3b169d6c79b38a3d [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"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080023#include "query.hpp"
24#include "registries/privilege_registry.hpp"
25#include "utils/collection.hpp"
26#include "utils/dbus_utils.hpp"
27#include "utils/json_utils.hpp"
Gunnar Millsac6a4442020-10-14 14:55:29 -050028
29#include <boost/container/flat_map.hpp>
George Liue99073f2022-12-09 11:06:16 +080030#include <boost/system/error_code.hpp>
Ed Tanousef4c65b2023-04-24 15:28:50 -070031#include <boost/url/format.hpp>
Jonathan Doman1e1e5982021-06-11 09:36:17 -070032#include <sdbusplus/asio/property.hpp>
Jonathan Domandba0c292020-12-02 15:34:13 -080033#include <sdbusplus/message/native_types.hpp>
Krzysztof Grobelny351053f2022-07-28 15:44:22 +020034#include <sdbusplus/unpack_properties.hpp>
Jonathan Domandba0c292020-12-02 15:34:13 -080035#include <sdbusplus/utility/dedup_variant.hpp>
Gunnar Millsac6a4442020-10-14 14:55:29 -050036
George Liu7a1dbc42022-12-07 16:03:22 +080037#include <array>
Michael Shenb9d679d2023-02-13 02:29:04 +000038#include <limits>
Ed Tanous3544d2a2023-08-06 18:12:20 -070039#include <ranges>
Ed Tanous3c569212024-03-06 14:46:18 -080040#include <string>
George Liu7a1dbc42022-12-07 16:03:22 +080041#include <string_view>
42
Gunnar Millsac6a4442020-10-14 14:55:29 -050043namespace redfish
44{
45
Jonathan Domanc9514482021-02-24 09:20:51 -080046// Interfaces which imply a D-Bus object represents a Processor
George Liu7a1dbc42022-12-07 16:03:22 +080047constexpr std::array<std::string_view, 2> processorInterfaces = {
Jonathan Domanc9514482021-02-24 09:20:51 -080048 "xyz.openbmc_project.Inventory.Item.Cpu",
49 "xyz.openbmc_project.Inventory.Item.Accelerator"};
Jonathan Doman2bab9832020-12-02 15:27:40 -080050
Sharad Yadav71b82f22021-05-10 15:11:39 +053051/**
52 * @brief Fill out uuid info of a processor by
53 * requesting data from the given D-Bus object.
54 *
Ed Tanousac106bf2023-06-07 09:24:59 -070055 * @param[in,out] asyncResp Async HTTP response.
Sharad Yadav71b82f22021-05-10 15:11:39 +053056 * @param[in] service D-Bus service to query.
57 * @param[in] objPath D-Bus object to query.
58 */
Ed Tanousac106bf2023-06-07 09:24:59 -070059inline void getProcessorUUID(std::shared_ptr<bmcweb::AsyncResp> asyncResp,
Sharad Yadav71b82f22021-05-10 15:11:39 +053060 const std::string& service,
61 const std::string& objPath)
62{
Ed Tanous62598e32023-07-17 17:06:25 -070063 BMCWEB_LOG_DEBUG("Get Processor UUID");
Jonathan Doman1e1e5982021-06-11 09:36:17 -070064 sdbusplus::asio::getProperty<std::string>(
65 *crow::connections::systemBus, service, objPath,
66 "xyz.openbmc_project.Common.UUID", "UUID",
Ed Tanousac106bf2023-06-07 09:24:59 -070067 [objPath, asyncResp{std::move(asyncResp)}](
68 const boost::system::error_code& ec, const std::string& property) {
Ed Tanous002d39b2022-05-31 08:59:27 -070069 if (ec)
70 {
Ed Tanous62598e32023-07-17 17:06:25 -070071 BMCWEB_LOG_DEBUG("DBUS response error");
Ed Tanousac106bf2023-06-07 09:24:59 -070072 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -070073 return;
74 }
Ed Tanousac106bf2023-06-07 09:24:59 -070075 asyncResp->res.jsonValue["UUID"] = property;
Patrick Williams5a39f772023-10-20 11:20:21 -050076 });
Sharad Yadav71b82f22021-05-10 15:11:39 +053077}
78
Ed Tanous711ac7a2021-12-20 09:34:41 -080079inline void getCpuDataByInterface(
Ed Tanousac106bf2023-06-07 09:24:59 -070080 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Michael Shen80f79a42023-08-24 13:41:53 +000081 const dbus::utility::DBusInterfacesMap& cpuInterfacesProperties)
Gunnar Millsac6a4442020-10-14 14:55:29 -050082{
Ed Tanous62598e32023-07-17 17:06:25 -070083 BMCWEB_LOG_DEBUG("Get CPU resources by interface.");
Gunnar Millsac6a4442020-10-14 14:55:29 -050084
Chicago Duana1649ec2021-03-30 16:54:58 +080085 // Set the default value of state
Ed Tanousac106bf2023-06-07 09:24:59 -070086 asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
87 asyncResp->res.jsonValue["Status"]["Health"] = "OK";
Gunnar Millsac6a4442020-10-14 14:55:29 -050088
89 for (const auto& interface : cpuInterfacesProperties)
90 {
91 for (const auto& property : interface.second)
92 {
Chicago Duana1649ec2021-03-30 16:54:58 +080093 if (property.first == "Present")
Gunnar Millsac6a4442020-10-14 14:55:29 -050094 {
Chicago Duana1649ec2021-03-30 16:54:58 +080095 const bool* cpuPresent = std::get_if<bool>(&property.second);
96 if (cpuPresent == nullptr)
Gunnar Millsac6a4442020-10-14 14:55:29 -050097 {
98 // Important property not in desired type
Ed Tanousac106bf2023-06-07 09:24:59 -070099 messages::internalError(asyncResp->res);
Gunnar Millsac6a4442020-10-14 14:55:29 -0500100 return;
101 }
Ed Tanouse05aec52022-01-25 10:28:56 -0800102 if (!*cpuPresent)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500103 {
Chicago Duana1649ec2021-03-30 16:54:58 +0800104 // Slot is not populated
Ed Tanousac106bf2023-06-07 09:24:59 -0700105 asyncResp->res.jsonValue["Status"]["State"] = "Absent";
Chicago Duana1649ec2021-03-30 16:54:58 +0800106 }
107 }
108 else if (property.first == "Functional")
109 {
110 const bool* cpuFunctional = std::get_if<bool>(&property.second);
111 if (cpuFunctional == nullptr)
112 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700113 messages::internalError(asyncResp->res);
Gunnar Millsac6a4442020-10-14 14:55:29 -0500114 return;
115 }
Ed Tanouse05aec52022-01-25 10:28:56 -0800116 if (!*cpuFunctional)
Chicago Duana1649ec2021-03-30 16:54:58 +0800117 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700118 asyncResp->res.jsonValue["Status"]["Health"] = "Critical";
Chicago Duana1649ec2021-03-30 16:54:58 +0800119 }
120 }
121 else if (property.first == "CoreCount")
122 {
123 const uint16_t* coresCount =
124 std::get_if<uint16_t>(&property.second);
125 if (coresCount == nullptr)
126 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700127 messages::internalError(asyncResp->res);
Chicago Duana1649ec2021-03-30 16:54:58 +0800128 return;
129 }
Ed Tanousac106bf2023-06-07 09:24:59 -0700130 asyncResp->res.jsonValue["TotalCores"] = *coresCount;
Gunnar Millsac6a4442020-10-14 14:55:29 -0500131 }
Jonathan Domandc3fa662020-10-26 23:10:24 -0700132 else if (property.first == "MaxSpeedInMhz")
133 {
134 const uint32_t* value = std::get_if<uint32_t>(&property.second);
135 if (value != nullptr)
136 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700137 asyncResp->res.jsonValue["MaxSpeedMHz"] = *value;
Jonathan Domandc3fa662020-10-26 23:10:24 -0700138 }
139 }
Gunnar Millsac6a4442020-10-14 14:55:29 -0500140 else if (property.first == "Socket")
141 {
142 const std::string* value =
143 std::get_if<std::string>(&property.second);
144 if (value != nullptr)
145 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700146 asyncResp->res.jsonValue["Socket"] = *value;
Gunnar Millsac6a4442020-10-14 14:55:29 -0500147 }
148 }
149 else if (property.first == "ThreadCount")
150 {
Jonathan Domandc3fa662020-10-26 23:10:24 -0700151 const uint16_t* value = std::get_if<uint16_t>(&property.second);
Gunnar Millsac6a4442020-10-14 14:55:29 -0500152 if (value != nullptr)
153 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700154 asyncResp->res.jsonValue["TotalThreads"] = *value;
Gunnar Millsac6a4442020-10-14 14:55:29 -0500155 }
156 }
Brandon Kim1930fbd2021-09-14 17:52:51 -0700157 else if (property.first == "EffectiveFamily")
Gunnar Millsac6a4442020-10-14 14:55:29 -0500158 {
Brandon Kim1930fbd2021-09-14 17:52:51 -0700159 const uint16_t* value = std::get_if<uint16_t>(&property.second);
Brad Bishop6169de22022-09-14 13:08:32 -0400160 if (value != nullptr && *value != 2)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500161 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700162 asyncResp->res.jsonValue["ProcessorId"]["EffectiveFamily"] =
Ed Tanous866e4862022-02-17 11:40:25 -0800163 "0x" + intToHexString(*value, 4);
Gunnar Millsac6a4442020-10-14 14:55:29 -0500164 }
165 }
Brandon Kim1930fbd2021-09-14 17:52:51 -0700166 else if (property.first == "EffectiveModel")
167 {
168 const uint16_t* value = std::get_if<uint16_t>(&property.second);
169 if (value == nullptr)
170 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700171 messages::internalError(asyncResp->res);
Brandon Kim1930fbd2021-09-14 17:52:51 -0700172 return;
173 }
Brad Bishop6169de22022-09-14 13:08:32 -0400174 if (*value != 0)
175 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700176 asyncResp->res.jsonValue["ProcessorId"]["EffectiveModel"] =
Brad Bishop6169de22022-09-14 13:08:32 -0400177 "0x" + intToHexString(*value, 4);
178 }
Brandon Kim1930fbd2021-09-14 17:52:51 -0700179 }
Gunnar Millsac6a4442020-10-14 14:55:29 -0500180 else if (property.first == "Id")
181 {
182 const uint64_t* value = std::get_if<uint64_t>(&property.second);
183 if (value != nullptr && *value != 0)
184 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700185 asyncResp->res
Gunnar Millsac6a4442020-10-14 14:55:29 -0500186 .jsonValue["ProcessorId"]["IdentificationRegisters"] =
Ed Tanous866e4862022-02-17 11:40:25 -0800187 "0x" + intToHexString(*value, 16);
Gunnar Millsac6a4442020-10-14 14:55:29 -0500188 }
189 }
Brandon Kim1930fbd2021-09-14 17:52:51 -0700190 else if (property.first == "Microcode")
191 {
192 const uint32_t* value = std::get_if<uint32_t>(&property.second);
193 if (value == nullptr)
194 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700195 messages::internalError(asyncResp->res);
Brandon Kim1930fbd2021-09-14 17:52:51 -0700196 return;
197 }
Brad Bishop6169de22022-09-14 13:08:32 -0400198 if (*value != 0)
199 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700200 asyncResp->res.jsonValue["ProcessorId"]["MicrocodeInfo"] =
Brad Bishop6169de22022-09-14 13:08:32 -0400201 "0x" + intToHexString(*value, 8);
202 }
Brandon Kim1930fbd2021-09-14 17:52:51 -0700203 }
204 else if (property.first == "Step")
205 {
206 const uint16_t* value = std::get_if<uint16_t>(&property.second);
207 if (value == nullptr)
208 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700209 messages::internalError(asyncResp->res);
Brandon Kim1930fbd2021-09-14 17:52:51 -0700210 return;
211 }
Michael Shenb9d679d2023-02-13 02:29:04 +0000212 if (*value != std::numeric_limits<uint16_t>::max())
Brad Bishop6169de22022-09-14 13:08:32 -0400213 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700214 asyncResp->res.jsonValue["ProcessorId"]["Step"] =
Brad Bishop6169de22022-09-14 13:08:32 -0400215 "0x" + intToHexString(*value, 4);
216 }
Brandon Kim1930fbd2021-09-14 17:52:51 -0700217 }
Gunnar Millsac6a4442020-10-14 14:55:29 -0500218 }
219 }
Gunnar Millsac6a4442020-10-14 14:55:29 -0500220}
221
Ed Tanousac106bf2023-06-07 09:24:59 -0700222inline void getCpuDataByService(std::shared_ptr<bmcweb::AsyncResp> asyncResp,
Gunnar Millsac6a4442020-10-14 14:55:29 -0500223 const std::string& cpuId,
224 const std::string& service,
225 const std::string& objPath)
226{
Ed Tanous62598e32023-07-17 17:06:25 -0700227 BMCWEB_LOG_DEBUG("Get available system cpu resources by service.");
Gunnar Millsac6a4442020-10-14 14:55:29 -0500228
George Liu5eb468d2023-06-20 17:03:24 +0800229 sdbusplus::message::object_path path("/xyz/openbmc_project/inventory");
230 dbus::utility::getManagedObjects(
231 service, path,
Ed Tanousac106bf2023-06-07 09:24:59 -0700232 [cpuId, service, objPath, asyncResp{std::move(asyncResp)}](
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800233 const boost::system::error_code& ec,
Gunnar Millsac6a4442020-10-14 14:55:29 -0500234 const dbus::utility::ManagedObjectType& dbusData) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700235 if (ec)
236 {
Ed Tanous62598e32023-07-17 17:06:25 -0700237 BMCWEB_LOG_DEBUG("DBUS response error");
Ed Tanousac106bf2023-06-07 09:24:59 -0700238 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -0700239 return;
240 }
Ed Tanousac106bf2023-06-07 09:24:59 -0700241 asyncResp->res.jsonValue["Id"] = cpuId;
242 asyncResp->res.jsonValue["Name"] = "Processor";
243 asyncResp->res.jsonValue["ProcessorType"] = "CPU";
Gunnar Millsac6a4442020-10-14 14:55:29 -0500244
Ed Tanous002d39b2022-05-31 08:59:27 -0700245 bool slotPresent = false;
246 std::string corePath = objPath + "/core";
247 size_t totalCores = 0;
248 for (const auto& object : dbusData)
249 {
250 if (object.first.str == objPath)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500251 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700252 getCpuDataByInterface(asyncResp, object.second);
Ed Tanous002d39b2022-05-31 08:59:27 -0700253 }
Ed Tanous11ba3972022-07-11 09:50:41 -0700254 else if (object.first.str.starts_with(corePath))
Ed Tanous002d39b2022-05-31 08:59:27 -0700255 {
256 for (const auto& interface : object.second)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500257 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700258 if (interface.first == "xyz.openbmc_project.Inventory.Item")
Gunnar Millsac6a4442020-10-14 14:55:29 -0500259 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700260 for (const auto& property : interface.second)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500261 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700262 if (property.first == "Present")
Gunnar Millsac6a4442020-10-14 14:55:29 -0500263 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700264 const bool* present =
265 std::get_if<bool>(&property.second);
266 if (present != nullptr)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500267 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700268 if (*present)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500269 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700270 slotPresent = true;
271 totalCores++;
Gunnar Millsac6a4442020-10-14 14:55:29 -0500272 }
273 }
274 }
275 }
276 }
277 }
278 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700279 }
280 // In getCpuDataByInterface(), state and health are set
281 // based on the present and functional status. If core
282 // count is zero, then it has a higher precedence.
283 if (slotPresent)
284 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700285 asyncResp->res.jsonValue["TotalCores"] = totalCores;
Ed Tanous002d39b2022-05-31 08:59:27 -0700286 }
287 return;
Patrick Williams5a39f772023-10-20 11:20:21 -0500288 });
Gunnar Millsac6a4442020-10-14 14:55:29 -0500289}
290
Chris Caindfbf7de2023-04-13 16:01:04 -0500291/**
292 * @brief Translates throttle cause DBUS property to redfish.
293 *
294 * @param[in] dbusSource The throttle cause from DBUS
295 *
296 * @return Returns as a string, the throttle cause in Redfish terms. If
297 * translation cannot be done, returns "Unknown" throttle reason.
298 */
299inline processor::ThrottleCause
300 dbusToRfThrottleCause(const std::string& dbusSource)
301{
302 if (dbusSource ==
303 "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.ClockLimit")
304 {
305 return processor::ThrottleCause::ClockLimit;
306 }
307 if (dbusSource ==
308 "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.ManagementDetectedFault")
309 {
310 return processor::ThrottleCause::ManagementDetectedFault;
311 }
312 if (dbusSource ==
313 "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.PowerLimit")
314 {
315 return processor::ThrottleCause::PowerLimit;
316 }
317 if (dbusSource ==
318 "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.ThermalLimit")
319 {
320 return processor::ThrottleCause::ThermalLimit;
321 }
322 if (dbusSource ==
323 "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.Unknown")
324 {
325 return processor::ThrottleCause::Unknown;
326 }
327 return processor::ThrottleCause::Invalid;
328}
329
330inline void
Ed Tanousac106bf2023-06-07 09:24:59 -0700331 readThrottleProperties(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Chris Caindfbf7de2023-04-13 16:01:04 -0500332 const boost::system::error_code& ec,
333 const dbus::utility::DBusPropertiesMap& properties)
334{
335 if (ec)
336 {
Ed Tanous62598e32023-07-17 17:06:25 -0700337 BMCWEB_LOG_ERROR("Processor Throttle getAllProperties error {}", ec);
Ed Tanousac106bf2023-06-07 09:24:59 -0700338 messages::internalError(asyncResp->res);
Chris Caindfbf7de2023-04-13 16:01:04 -0500339 return;
340 }
341
342 const bool* status = nullptr;
343 const std::vector<std::string>* causes = nullptr;
344
345 if (!sdbusplus::unpackPropertiesNoThrow(dbus_utils::UnpackErrorPrinter(),
346 properties, "Throttled", status,
347 "ThrottleCauses", causes))
348 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700349 messages::internalError(asyncResp->res);
Chris Caindfbf7de2023-04-13 16:01:04 -0500350 return;
351 }
352
Ed Tanousac106bf2023-06-07 09:24:59 -0700353 asyncResp->res.jsonValue["Throttled"] = *status;
Chris Caindfbf7de2023-04-13 16:01:04 -0500354 nlohmann::json::array_t rCauses;
355 for (const std::string& cause : *causes)
356 {
357 processor::ThrottleCause rfCause = dbusToRfThrottleCause(cause);
358 if (rfCause == processor::ThrottleCause::Invalid)
359 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700360 messages::internalError(asyncResp->res);
Chris Caindfbf7de2023-04-13 16:01:04 -0500361 return;
362 }
363
364 rCauses.emplace_back(rfCause);
365 }
Ed Tanousac106bf2023-06-07 09:24:59 -0700366 asyncResp->res.jsonValue["ThrottleCauses"] = std::move(rCauses);
Chris Caindfbf7de2023-04-13 16:01:04 -0500367}
368
369inline void
Ed Tanousac106bf2023-06-07 09:24:59 -0700370 getThrottleProperties(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Chris Caindfbf7de2023-04-13 16:01:04 -0500371 const std::string& service,
372 const std::string& objectPath)
373{
Ed Tanous62598e32023-07-17 17:06:25 -0700374 BMCWEB_LOG_DEBUG("Get processor throttle resources");
Chris Caindfbf7de2023-04-13 16:01:04 -0500375
376 sdbusplus::asio::getAllProperties(
377 *crow::connections::systemBus, service, objectPath,
378 "xyz.openbmc_project.Control.Power.Throttle",
Ed Tanousac106bf2023-06-07 09:24:59 -0700379 [asyncResp](const boost::system::error_code& ec,
380 const dbus::utility::DBusPropertiesMap& properties) {
381 readThrottleProperties(asyncResp, ec, properties);
Patrick Williams5a39f772023-10-20 11:20:21 -0500382 });
Chris Caindfbf7de2023-04-13 16:01:04 -0500383}
384
Ed Tanousac106bf2023-06-07 09:24:59 -0700385inline void getCpuAssetData(std::shared_ptr<bmcweb::AsyncResp> asyncResp,
Gunnar Millsac6a4442020-10-14 14:55:29 -0500386 const std::string& service,
387 const std::string& objPath)
388{
Ed Tanous62598e32023-07-17 17:06:25 -0700389 BMCWEB_LOG_DEBUG("Get Cpu Asset Data");
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200390 sdbusplus::asio::getAllProperties(
391 *crow::connections::systemBus, service, objPath,
392 "xyz.openbmc_project.Inventory.Decorator.Asset",
Ed Tanousac106bf2023-06-07 09:24:59 -0700393 [objPath, asyncResp{std::move(asyncResp)}](
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800394 const boost::system::error_code& ec,
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200395 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700396 if (ec)
397 {
Ed Tanous62598e32023-07-17 17:06:25 -0700398 BMCWEB_LOG_DEBUG("DBUS response error");
Ed Tanousac106bf2023-06-07 09:24:59 -0700399 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -0700400 return;
401 }
402
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200403 const std::string* serialNumber = nullptr;
404 const std::string* model = nullptr;
405 const std::string* manufacturer = nullptr;
406 const std::string* partNumber = nullptr;
407 const std::string* sparePartNumber = nullptr;
408
409 const bool success = sdbusplus::unpackPropertiesNoThrow(
410 dbus_utils::UnpackErrorPrinter(), properties, "SerialNumber",
411 serialNumber, "Model", model, "Manufacturer", manufacturer,
412 "PartNumber", partNumber, "SparePartNumber", sparePartNumber);
413
414 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -0700415 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700416 messages::internalError(asyncResp->res);
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200417 return;
418 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700419
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200420 if (serialNumber != nullptr && !serialNumber->empty())
421 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700422 asyncResp->res.jsonValue["SerialNumber"] = *serialNumber;
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200423 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700424
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200425 if ((model != nullptr) && !model->empty())
426 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700427 asyncResp->res.jsonValue["Model"] = *model;
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200428 }
429
430 if (manufacturer != nullptr)
431 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700432 asyncResp->res.jsonValue["Manufacturer"] = *manufacturer;
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200433
434 // Otherwise would be unexpected.
435 if (manufacturer->find("Intel") != std::string::npos)
Ed Tanous002d39b2022-05-31 08:59:27 -0700436 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700437 asyncResp->res.jsonValue["ProcessorArchitecture"] = "x86";
438 asyncResp->res.jsonValue["InstructionSet"] = "x86-64";
Ed Tanous002d39b2022-05-31 08:59:27 -0700439 }
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200440 else if (manufacturer->find("IBM") != std::string::npos)
Ed Tanous002d39b2022-05-31 08:59:27 -0700441 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700442 asyncResp->res.jsonValue["ProcessorArchitecture"] = "Power";
443 asyncResp->res.jsonValue["InstructionSet"] = "PowerISA";
Ed Tanous002d39b2022-05-31 08:59:27 -0700444 }
445 }
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200446
447 if (partNumber != nullptr)
448 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700449 asyncResp->res.jsonValue["PartNumber"] = *partNumber;
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200450 }
451
Brad Bishop6169de22022-09-14 13:08:32 -0400452 if (sparePartNumber != nullptr && !sparePartNumber->empty())
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200453 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700454 asyncResp->res.jsonValue["SparePartNumber"] = *sparePartNumber;
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200455 }
Patrick Williams5a39f772023-10-20 11:20:21 -0500456 });
Gunnar Millsac6a4442020-10-14 14:55:29 -0500457}
458
Ed Tanousac106bf2023-06-07 09:24:59 -0700459inline void getCpuRevisionData(std::shared_ptr<bmcweb::AsyncResp> asyncResp,
Gunnar Millsac6a4442020-10-14 14:55:29 -0500460 const std::string& service,
461 const std::string& objPath)
462{
Ed Tanous62598e32023-07-17 17:06:25 -0700463 BMCWEB_LOG_DEBUG("Get Cpu Revision Data");
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200464 sdbusplus::asio::getAllProperties(
465 *crow::connections::systemBus, service, objPath,
466 "xyz.openbmc_project.Inventory.Decorator.Revision",
Ed Tanousac106bf2023-06-07 09:24:59 -0700467 [objPath, asyncResp{std::move(asyncResp)}](
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800468 const boost::system::error_code& ec,
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200469 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700470 if (ec)
471 {
Ed Tanous62598e32023-07-17 17:06:25 -0700472 BMCWEB_LOG_DEBUG("DBUS response error");
Ed Tanousac106bf2023-06-07 09:24:59 -0700473 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -0700474 return;
475 }
Gunnar Millsac6a4442020-10-14 14:55:29 -0500476
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200477 const std::string* version = nullptr;
478
479 const bool success = sdbusplus::unpackPropertiesNoThrow(
480 dbus_utils::UnpackErrorPrinter(), properties, "Version", version);
481
482 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -0700483 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700484 messages::internalError(asyncResp->res);
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200485 return;
Ed Tanous002d39b2022-05-31 08:59:27 -0700486 }
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200487
488 if (version != nullptr)
489 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700490 asyncResp->res.jsonValue["Version"] = *version;
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200491 }
Patrick Williams5a39f772023-10-20 11:20:21 -0500492 });
Gunnar Millsac6a4442020-10-14 14:55:29 -0500493}
494
zhanghch058d1b46d2021-04-01 11:18:24 +0800495inline void getAcceleratorDataByService(
Ed Tanousac106bf2023-06-07 09:24:59 -0700496 std::shared_ptr<bmcweb::AsyncResp> asyncResp, const std::string& acclrtrId,
zhanghch058d1b46d2021-04-01 11:18:24 +0800497 const std::string& service, const std::string& objPath)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500498{
Ed Tanous62598e32023-07-17 17:06:25 -0700499 BMCWEB_LOG_DEBUG("Get available system Accelerator resources by service.");
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200500 sdbusplus::asio::getAllProperties(
501 *crow::connections::systemBus, service, objPath, "",
Ed Tanousac106bf2023-06-07 09:24:59 -0700502 [acclrtrId, asyncResp{std::move(asyncResp)}](
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800503 const boost::system::error_code& ec,
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200504 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700505 if (ec)
506 {
Ed Tanous62598e32023-07-17 17:06:25 -0700507 BMCWEB_LOG_DEBUG("DBUS response error");
Ed Tanousac106bf2023-06-07 09:24:59 -0700508 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -0700509 return;
510 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700511
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200512 const bool* functional = nullptr;
513 const bool* present = nullptr;
514
515 const bool success = sdbusplus::unpackPropertiesNoThrow(
516 dbus_utils::UnpackErrorPrinter(), properties, "Functional",
517 functional, "Present", present);
518
519 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -0700520 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700521 messages::internalError(asyncResp->res);
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200522 return;
Ed Tanous002d39b2022-05-31 08:59:27 -0700523 }
Gunnar Millsac6a4442020-10-14 14:55:29 -0500524
Ed Tanous002d39b2022-05-31 08:59:27 -0700525 std::string state = "Enabled";
526 std::string health = "OK";
Gunnar Millsac6a4442020-10-14 14:55:29 -0500527
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200528 if (present != nullptr && !*present)
Ed Tanous002d39b2022-05-31 08:59:27 -0700529 {
530 state = "Absent";
531 }
532
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200533 if (functional != nullptr && !*functional)
Ed Tanous002d39b2022-05-31 08:59:27 -0700534 {
535 if (state == "Enabled")
Gunnar Millsac6a4442020-10-14 14:55:29 -0500536 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700537 health = "Critical";
Gunnar Millsac6a4442020-10-14 14:55:29 -0500538 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700539 }
Gunnar Millsac6a4442020-10-14 14:55:29 -0500540
Ed Tanousac106bf2023-06-07 09:24:59 -0700541 asyncResp->res.jsonValue["Id"] = acclrtrId;
542 asyncResp->res.jsonValue["Name"] = "Processor";
543 asyncResp->res.jsonValue["Status"]["State"] = state;
544 asyncResp->res.jsonValue["Status"]["Health"] = health;
545 asyncResp->res.jsonValue["ProcessorType"] = "Accelerator";
Patrick Williams5a39f772023-10-20 11:20:21 -0500546 });
Gunnar Millsac6a4442020-10-14 14:55:29 -0500547}
548
Jonathan Domandba0c292020-12-02 15:34:13 -0800549// OperatingConfig D-Bus Types
550using TurboProfileProperty = std::vector<std::tuple<uint32_t, size_t>>;
551using BaseSpeedPrioritySettingsProperty =
552 std::vector<std::tuple<uint32_t, std::vector<uint32_t>>>;
553// uint32_t and size_t may or may not be the same type, requiring a dedup'd
554// variant
Jonathan Domandba0c292020-12-02 15:34:13 -0800555
556/**
557 * Fill out the HighSpeedCoreIDs in a Processor resource from the given
558 * OperatingConfig D-Bus property.
559 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700560 * @param[in,out] asyncResp Async HTTP response.
Jonathan Domandba0c292020-12-02 15:34:13 -0800561 * @param[in] baseSpeedSettings Full list of base speed priority groups,
562 * to use to determine the list of high
563 * speed cores.
564 */
565inline void highSpeedCoreIdsHandler(
Ed Tanousac106bf2023-06-07 09:24:59 -0700566 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Jonathan Domandba0c292020-12-02 15:34:13 -0800567 const BaseSpeedPrioritySettingsProperty& baseSpeedSettings)
568{
569 // The D-Bus property does not indicate which bucket is the "high
570 // priority" group, so let's discern that by looking for the one with
571 // highest base frequency.
572 auto highPriorityGroup = baseSpeedSettings.cend();
573 uint32_t highestBaseSpeed = 0;
574 for (auto it = baseSpeedSettings.cbegin(); it != baseSpeedSettings.cend();
575 ++it)
576 {
577 const uint32_t baseFreq = std::get<uint32_t>(*it);
578 if (baseFreq > highestBaseSpeed)
579 {
580 highestBaseSpeed = baseFreq;
581 highPriorityGroup = it;
582 }
583 }
584
Ed Tanousac106bf2023-06-07 09:24:59 -0700585 nlohmann::json& jsonCoreIds = asyncResp->res.jsonValue["HighSpeedCoreIDs"];
Jonathan Domandba0c292020-12-02 15:34:13 -0800586 jsonCoreIds = nlohmann::json::array();
587
588 // There may not be any entries in the D-Bus property, so only populate
589 // if there was actually something there.
590 if (highPriorityGroup != baseSpeedSettings.cend())
591 {
592 jsonCoreIds = std::get<std::vector<uint32_t>>(*highPriorityGroup);
593 }
594}
595
596/**
597 * Fill out OperatingConfig related items in a Processor resource by requesting
598 * data from the given D-Bus object.
599 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700600 * @param[in,out] asyncResp Async HTTP response.
Jonathan Domandba0c292020-12-02 15:34:13 -0800601 * @param[in] cpuId CPU D-Bus name.
602 * @param[in] service D-Bus service to query.
603 * @param[in] objPath D-Bus object to query.
604 */
Ed Tanousac106bf2023-06-07 09:24:59 -0700605inline void
606 getCpuConfigData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
607 const std::string& cpuId, const std::string& service,
608 const std::string& objPath)
Jonathan Domandba0c292020-12-02 15:34:13 -0800609{
Ed Tanous62598e32023-07-17 17:06:25 -0700610 BMCWEB_LOG_INFO("Getting CPU operating configs for {}", cpuId);
Jonathan Domandba0c292020-12-02 15:34:13 -0800611
612 // First, GetAll CurrentOperatingConfig properties on the object
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200613 sdbusplus::asio::getAllProperties(
614 *crow::connections::systemBus, service, objPath,
615 "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig",
Ed Tanousac106bf2023-06-07 09:24:59 -0700616 [asyncResp, cpuId,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800617 service](const boost::system::error_code& ec,
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200618 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700619 if (ec)
620 {
Ed Tanous62598e32023-07-17 17:06:25 -0700621 BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec, ec.message());
Ed Tanousac106bf2023-06-07 09:24:59 -0700622 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -0700623 return;
624 }
Jonathan Domandba0c292020-12-02 15:34:13 -0800625
Ed Tanousac106bf2023-06-07 09:24:59 -0700626 nlohmann::json& json = asyncResp->res.jsonValue;
Jonathan Domandba0c292020-12-02 15:34:13 -0800627
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200628 const sdbusplus::message::object_path* appliedConfig = nullptr;
629 const bool* baseSpeedPriorityEnabled = nullptr;
630
631 const bool success = sdbusplus::unpackPropertiesNoThrow(
632 dbus_utils::UnpackErrorPrinter(), properties, "AppliedConfig",
633 appliedConfig, "BaseSpeedPriorityEnabled",
634 baseSpeedPriorityEnabled);
635
636 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -0700637 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700638 messages::internalError(asyncResp->res);
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200639 return;
Ed Tanous002d39b2022-05-31 08:59:27 -0700640 }
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200641
642 if (appliedConfig != nullptr)
643 {
644 const std::string& dbusPath = appliedConfig->str;
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200645 nlohmann::json::object_t operatingConfig;
Ed Tanousef4c65b2023-04-24 15:28:50 -0700646 operatingConfig["@odata.id"] = boost::urls::format(
647 "/redfish/v1/Systems/system/Processors/{}/OperatingConfigs",
648 cpuId);
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200649 json["OperatingConfigs"] = std::move(operatingConfig);
650
651 // Reuse the D-Bus config object name for the Redfish
652 // URI
653 size_t baseNamePos = dbusPath.rfind('/');
654 if (baseNamePos == std::string::npos ||
655 baseNamePos == (dbusPath.size() - 1))
656 {
657 // If the AppliedConfig was somehow not a valid path,
658 // skip adding any more properties, since everything
659 // else is tied to this applied config.
Ed Tanousac106bf2023-06-07 09:24:59 -0700660 messages::internalError(asyncResp->res);
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200661 return;
662 }
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200663 nlohmann::json::object_t appliedOperatingConfig;
Ed Tanousef4c65b2023-04-24 15:28:50 -0700664 appliedOperatingConfig["@odata.id"] = boost::urls::format(
665 "/redfish/v1/Systems/system/Processors/{}/OperatingConfigs/{}",
666 cpuId, dbusPath.substr(baseNamePos + 1));
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200667 json["AppliedOperatingConfig"] = std::move(appliedOperatingConfig);
668
669 // Once we found the current applied config, queue another
670 // request to read the base freq core ids out of that
671 // config.
672 sdbusplus::asio::getProperty<BaseSpeedPrioritySettingsProperty>(
673 *crow::connections::systemBus, service, dbusPath,
674 "xyz.openbmc_project.Inventory.Item.Cpu."
675 "OperatingConfig",
676 "BaseSpeedPrioritySettings",
Ed Tanousac106bf2023-06-07 09:24:59 -0700677 [asyncResp](
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800678 const boost::system::error_code& ec2,
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200679 const BaseSpeedPrioritySettingsProperty& baseSpeedList) {
680 if (ec2)
681 {
Ed Tanous62598e32023-07-17 17:06:25 -0700682 BMCWEB_LOG_WARNING("D-Bus Property Get error: {}", ec2);
Ed Tanousac106bf2023-06-07 09:24:59 -0700683 messages::internalError(asyncResp->res);
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200684 return;
685 }
686
Ed Tanousac106bf2023-06-07 09:24:59 -0700687 highSpeedCoreIdsHandler(asyncResp, baseSpeedList);
Patrick Williams5a39f772023-10-20 11:20:21 -0500688 });
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200689 }
690
691 if (baseSpeedPriorityEnabled != nullptr)
692 {
693 json["BaseSpeedPriorityState"] =
694 *baseSpeedPriorityEnabled ? "Enabled" : "Disabled";
695 }
Patrick Williams5a39f772023-10-20 11:20:21 -0500696 });
Jonathan Domandba0c292020-12-02 15:34:13 -0800697}
698
SunnySrivastava1984cba4f442021-01-07 12:48:16 -0600699/**
700 * @brief Fill out location info of a processor by
701 * requesting data from the given D-Bus object.
702 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700703 * @param[in,out] asyncResp Async HTTP response.
SunnySrivastava1984cba4f442021-01-07 12:48:16 -0600704 * @param[in] service D-Bus service to query.
705 * @param[in] objPath D-Bus object to query.
706 */
Ed Tanousac106bf2023-06-07 09:24:59 -0700707inline void getCpuLocationCode(std::shared_ptr<bmcweb::AsyncResp> asyncResp,
SunnySrivastava1984cba4f442021-01-07 12:48:16 -0600708 const std::string& service,
709 const std::string& objPath)
710{
Ed Tanous62598e32023-07-17 17:06:25 -0700711 BMCWEB_LOG_DEBUG("Get Cpu Location Data");
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700712 sdbusplus::asio::getProperty<std::string>(
713 *crow::connections::systemBus, service, objPath,
714 "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode",
Ed Tanousac106bf2023-06-07 09:24:59 -0700715 [objPath, asyncResp{std::move(asyncResp)}](
716 const boost::system::error_code& ec, const std::string& property) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700717 if (ec)
718 {
Ed Tanous62598e32023-07-17 17:06:25 -0700719 BMCWEB_LOG_DEBUG("DBUS response error");
Ed Tanousac106bf2023-06-07 09:24:59 -0700720 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -0700721 return;
722 }
SunnySrivastava1984cba4f442021-01-07 12:48:16 -0600723
Ed Tanousac106bf2023-06-07 09:24:59 -0700724 asyncResp->res.jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
Ed Tanous002d39b2022-05-31 08:59:27 -0700725 property;
Patrick Williams5a39f772023-10-20 11:20:21 -0500726 });
SunnySrivastava1984cba4f442021-01-07 12:48:16 -0600727}
728
Jonathan Domanc9514482021-02-24 09:20:51 -0800729/**
Jonathan Doman49e429c2021-03-03 13:11:44 -0800730 * Populate the unique identifier in a Processor resource by requesting data
731 * from the given D-Bus object.
732 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700733 * @param[in,out] asyncResp Async HTTP response.
Jonathan Doman49e429c2021-03-03 13:11:44 -0800734 * @param[in] service D-Bus service to query.
735 * @param[in] objPath D-Bus object to query.
736 */
Ed Tanousac106bf2023-06-07 09:24:59 -0700737inline void getCpuUniqueId(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Jonathan Doman49e429c2021-03-03 13:11:44 -0800738 const std::string& service,
739 const std::string& objectPath)
740{
Ed Tanous62598e32023-07-17 17:06:25 -0700741 BMCWEB_LOG_DEBUG("Get CPU UniqueIdentifier");
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700742 sdbusplus::asio::getProperty<std::string>(
743 *crow::connections::systemBus, service, objectPath,
744 "xyz.openbmc_project.Inventory.Decorator.UniqueIdentifier",
745 "UniqueIdentifier",
Ed Tanousac106bf2023-06-07 09:24:59 -0700746 [asyncResp](const boost::system::error_code& ec,
747 const std::string& id) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700748 if (ec)
749 {
Ed Tanous62598e32023-07-17 17:06:25 -0700750 BMCWEB_LOG_ERROR("Failed to read cpu unique id: {}", ec);
Ed Tanousac106bf2023-06-07 09:24:59 -0700751 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -0700752 return;
753 }
Ed Tanousac106bf2023-06-07 09:24:59 -0700754 asyncResp->res
755 .jsonValue["ProcessorId"]["ProtectedIdentificationNumber"] = id;
Patrick Williams5a39f772023-10-20 11:20:21 -0500756 });
Jonathan Doman49e429c2021-03-03 13:11:44 -0800757}
758
759/**
Jonathan Domanc9514482021-02-24 09:20:51 -0800760 * Find the D-Bus object representing the requested Processor, and call the
761 * handler with the results. If matching object is not found, add 404 error to
762 * response and don't call the handler.
763 *
764 * @param[in,out] resp Async HTTP response.
765 * @param[in] processorId Redfish Processor Id.
766 * @param[in] handler Callback to continue processing request upon
767 * successfully finding object.
768 */
769template <typename Handler>
zhanghch058d1b46d2021-04-01 11:18:24 +0800770inline void getProcessorObject(const std::shared_ptr<bmcweb::AsyncResp>& resp,
Jonathan Domanc9514482021-02-24 09:20:51 -0800771 const std::string& processorId,
772 Handler&& handler)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500773{
Ed Tanous62598e32023-07-17 17:06:25 -0700774 BMCWEB_LOG_DEBUG("Get available system processor resources.");
Gunnar Millsac6a4442020-10-14 14:55:29 -0500775
Jonathan Domanc9514482021-02-24 09:20:51 -0800776 // GetSubTree on all interfaces which provide info about a Processor
Chris Caindfbf7de2023-04-13 16:01:04 -0500777 constexpr std::array<std::string_view, 9> interfaces = {
George Liue99073f2022-12-09 11:06:16 +0800778 "xyz.openbmc_project.Common.UUID",
779 "xyz.openbmc_project.Inventory.Decorator.Asset",
780 "xyz.openbmc_project.Inventory.Decorator.Revision",
781 "xyz.openbmc_project.Inventory.Item.Cpu",
782 "xyz.openbmc_project.Inventory.Decorator.LocationCode",
783 "xyz.openbmc_project.Inventory.Item.Accelerator",
784 "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig",
Chris Caindfbf7de2023-04-13 16:01:04 -0500785 "xyz.openbmc_project.Inventory.Decorator.UniqueIdentifier",
786 "xyz.openbmc_project.Control.Power.Throttle"};
George Liue99073f2022-12-09 11:06:16 +0800787 dbus::utility::getSubTree(
788 "/xyz/openbmc_project/inventory", 0, interfaces,
Jonathan Domanc9514482021-02-24 09:20:51 -0800789 [resp, processorId, handler = std::forward<Handler>(handler)](
George Liue99073f2022-12-09 11:06:16 +0800790 const boost::system::error_code& ec,
791 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700792 if (ec)
793 {
Ed Tanous62598e32023-07-17 17:06:25 -0700794 BMCWEB_LOG_DEBUG("DBUS response error: {}", ec);
Ed Tanous002d39b2022-05-31 08:59:27 -0700795 messages::internalError(resp->res);
796 return;
797 }
798 for (const auto& [objectPath, serviceMap] : subtree)
799 {
800 // Ignore any objects which don't end with our desired cpu name
Ed Tanous11ba3972022-07-11 09:50:41 -0700801 if (!objectPath.ends_with(processorId))
Gunnar Millsac6a4442020-10-14 14:55:29 -0500802 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700803 continue;
Gunnar Millsac6a4442020-10-14 14:55:29 -0500804 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700805
806 bool found = false;
807 // Filter out objects that don't have the CPU-specific
808 // interfaces to make sure we can return 404 on non-CPUs
809 // (e.g. /redfish/../Processors/dimm0)
810 for (const auto& [serviceName, interfaceList] : serviceMap)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500811 {
Ed Tanous3544d2a2023-08-06 18:12:20 -0700812 if (std::ranges::find_first_of(interfaceList,
813 processorInterfaces) !=
814 std::end(interfaceList))
Gunnar Millsac6a4442020-10-14 14:55:29 -0500815 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700816 found = true;
817 break;
Jonathan Doman2bab9832020-12-02 15:27:40 -0800818 }
Gunnar Millsac6a4442020-10-14 14:55:29 -0500819 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700820
821 if (!found)
822 {
823 continue;
824 }
825
826 // Process the first object which does match our cpu name and
827 // required interfaces, and potentially ignore any other
828 // matching objects. Assume all interfaces we want to process
829 // must be on the same object path.
830
Ed Tanous8a592812022-06-04 09:06:59 -0700831 handler(objectPath, serviceMap);
Ed Tanous002d39b2022-05-31 08:59:27 -0700832 return;
833 }
834 messages::resourceNotFound(resp->res, "Processor", processorId);
Patrick Williams5a39f772023-10-20 11:20:21 -0500835 });
Gunnar Millsac6a4442020-10-14 14:55:29 -0500836}
837
Ed Tanousac106bf2023-06-07 09:24:59 -0700838inline void
839 getProcessorData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
840 const std::string& processorId,
841 const std::string& objectPath,
842 const dbus::utility::MapperServiceMap& serviceMap)
Jonathan Domanc9514482021-02-24 09:20:51 -0800843{
844 for (const auto& [serviceName, interfaceList] : serviceMap)
845 {
846 for (const auto& interface : interfaceList)
847 {
848 if (interface == "xyz.openbmc_project.Inventory.Decorator.Asset")
849 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700850 getCpuAssetData(asyncResp, serviceName, objectPath);
Jonathan Domanc9514482021-02-24 09:20:51 -0800851 }
George Liu0fda0f12021-11-16 10:06:17 +0800852 else if (interface ==
853 "xyz.openbmc_project.Inventory.Decorator.Revision")
Jonathan Domanc9514482021-02-24 09:20:51 -0800854 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700855 getCpuRevisionData(asyncResp, serviceName, objectPath);
Jonathan Domanc9514482021-02-24 09:20:51 -0800856 }
857 else if (interface == "xyz.openbmc_project.Inventory.Item.Cpu")
858 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700859 getCpuDataByService(asyncResp, processorId, serviceName,
Jonathan Domanc9514482021-02-24 09:20:51 -0800860 objectPath);
861 }
George Liu0fda0f12021-11-16 10:06:17 +0800862 else if (interface ==
863 "xyz.openbmc_project.Inventory.Item.Accelerator")
Jonathan Domanc9514482021-02-24 09:20:51 -0800864 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700865 getAcceleratorDataByService(asyncResp, processorId, serviceName,
Jonathan Domanc9514482021-02-24 09:20:51 -0800866 objectPath);
867 }
George Liu0fda0f12021-11-16 10:06:17 +0800868 else if (
869 interface ==
870 "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig")
Jonathan Domanc9514482021-02-24 09:20:51 -0800871 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700872 getCpuConfigData(asyncResp, processorId, serviceName,
873 objectPath);
Jonathan Domanc9514482021-02-24 09:20:51 -0800874 }
George Liu0fda0f12021-11-16 10:06:17 +0800875 else if (interface ==
876 "xyz.openbmc_project.Inventory.Decorator.LocationCode")
Jonathan Domanc9514482021-02-24 09:20:51 -0800877 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700878 getCpuLocationCode(asyncResp, serviceName, objectPath);
Jonathan Domanc9514482021-02-24 09:20:51 -0800879 }
Sharad Yadav71b82f22021-05-10 15:11:39 +0530880 else if (interface == "xyz.openbmc_project.Common.UUID")
881 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700882 getProcessorUUID(asyncResp, serviceName, objectPath);
Sharad Yadav71b82f22021-05-10 15:11:39 +0530883 }
George Liu0fda0f12021-11-16 10:06:17 +0800884 else if (interface ==
885 "xyz.openbmc_project.Inventory.Decorator.UniqueIdentifier")
Jonathan Doman49e429c2021-03-03 13:11:44 -0800886 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700887 getCpuUniqueId(asyncResp, serviceName, objectPath);
Jonathan Doman49e429c2021-03-03 13:11:44 -0800888 }
Chris Caindfbf7de2023-04-13 16:01:04 -0500889 else if (interface == "xyz.openbmc_project.Control.Power.Throttle")
890 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700891 getThrottleProperties(asyncResp, serviceName, objectPath);
Chris Caindfbf7de2023-04-13 16:01:04 -0500892 }
Jonathan Domanc9514482021-02-24 09:20:51 -0800893 }
894 }
895}
896
Jonathan Domandba0c292020-12-02 15:34:13 -0800897/**
898 * Request all the properties for the given D-Bus object and fill out the
899 * related entries in the Redfish OperatingConfig response.
900 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700901 * @param[in,out] asyncResp Async HTTP response.
Jonathan Domandba0c292020-12-02 15:34:13 -0800902 * @param[in] service D-Bus service name to query.
903 * @param[in] objPath D-Bus object to query.
904 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800905inline void
Ed Tanousac106bf2023-06-07 09:24:59 -0700906 getOperatingConfigData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
zhanghch058d1b46d2021-04-01 11:18:24 +0800907 const std::string& service,
908 const std::string& objPath)
Jonathan Domandba0c292020-12-02 15:34:13 -0800909{
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200910 sdbusplus::asio::getAllProperties(
911 *crow::connections::systemBus, service, objPath,
912 "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig",
Ed Tanousac106bf2023-06-07 09:24:59 -0700913 [asyncResp](const boost::system::error_code& ec,
914 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700915 if (ec)
916 {
Ed Tanous62598e32023-07-17 17:06:25 -0700917 BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec, ec.message());
Ed Tanousac106bf2023-06-07 09:24:59 -0700918 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -0700919 return;
920 }
921
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200922 const size_t* availableCoreCount = nullptr;
923 const uint32_t* baseSpeed = nullptr;
924 const uint32_t* maxJunctionTemperature = nullptr;
925 const uint32_t* maxSpeed = nullptr;
926 const uint32_t* powerLimit = nullptr;
927 const TurboProfileProperty* turboProfile = nullptr;
928 const BaseSpeedPrioritySettingsProperty* baseSpeedPrioritySettings =
929 nullptr;
930
931 const bool success = sdbusplus::unpackPropertiesNoThrow(
932 dbus_utils::UnpackErrorPrinter(), properties, "AvailableCoreCount",
933 availableCoreCount, "BaseSpeed", baseSpeed,
934 "MaxJunctionTemperature", maxJunctionTemperature, "MaxSpeed",
935 maxSpeed, "PowerLimit", powerLimit, "TurboProfile", turboProfile,
936 "BaseSpeedPrioritySettings", baseSpeedPrioritySettings);
937
938 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -0700939 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700940 messages::internalError(asyncResp->res);
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200941 return;
942 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700943
Ed Tanousac106bf2023-06-07 09:24:59 -0700944 nlohmann::json& json = asyncResp->res.jsonValue;
Ed Tanous002d39b2022-05-31 08:59:27 -0700945
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200946 if (availableCoreCount != nullptr)
947 {
948 json["TotalAvailableCoreCount"] = *availableCoreCount;
949 }
950
951 if (baseSpeed != nullptr)
952 {
953 json["BaseSpeedMHz"] = *baseSpeed;
954 }
955
956 if (maxJunctionTemperature != nullptr)
957 {
958 json["MaxJunctionTemperatureCelsius"] = *maxJunctionTemperature;
959 }
960
961 if (maxSpeed != nullptr)
962 {
963 json["MaxSpeedMHz"] = *maxSpeed;
964 }
965
966 if (powerLimit != nullptr)
967 {
968 json["TDPWatts"] = *powerLimit;
969 }
970
971 if (turboProfile != nullptr)
972 {
973 nlohmann::json& turboArray = json["TurboProfile"];
974 turboArray = nlohmann::json::array();
975 for (const auto& [turboSpeed, coreCount] : *turboProfile)
976 {
977 nlohmann::json::object_t turbo;
978 turbo["ActiveCoreCount"] = coreCount;
979 turbo["MaxSpeedMHz"] = turboSpeed;
Patrick Williamsb2ba3072023-05-12 10:27:39 -0500980 turboArray.emplace_back(std::move(turbo));
Ed Tanous002d39b2022-05-31 08:59:27 -0700981 }
982 }
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200983
984 if (baseSpeedPrioritySettings != nullptr)
985 {
986 nlohmann::json& baseSpeedArray = json["BaseSpeedPrioritySettings"];
987 baseSpeedArray = nlohmann::json::array();
988 for (const auto& [baseSpeedMhz, coreList] :
989 *baseSpeedPrioritySettings)
990 {
991 nlohmann::json::object_t speed;
992 speed["CoreCount"] = coreList.size();
993 speed["CoreIDs"] = coreList;
994 speed["BaseSpeedMHz"] = baseSpeedMhz;
Patrick Williamsb2ba3072023-05-12 10:27:39 -0500995 baseSpeedArray.emplace_back(std::move(speed));
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200996 }
997 }
Patrick Williams5a39f772023-10-20 11:20:21 -0500998 });
Jonathan Domandba0c292020-12-02 15:34:13 -0800999}
1000
Jonathan Doman3cde86f2020-12-02 14:50:45 -08001001/**
Jonathan Doman3cde86f2020-12-02 14:50:45 -08001002 * Handle the PATCH operation of the AppliedOperatingConfig property. Do basic
1003 * validation of the input data, and then set the D-Bus property.
1004 *
1005 * @param[in,out] resp Async HTTP response.
1006 * @param[in] processorId Processor's Id.
1007 * @param[in] appliedConfigUri New property value to apply.
1008 * @param[in] cpuObjectPath Path of CPU object to modify.
1009 * @param[in] serviceMap Service map for CPU object.
1010 */
1011inline void patchAppliedOperatingConfig(
1012 const std::shared_ptr<bmcweb::AsyncResp>& resp,
1013 const std::string& processorId, const std::string& appliedConfigUri,
Shantappa Teekappanavar5df6eda2022-01-18 12:29:28 -06001014 const std::string& cpuObjectPath,
1015 const dbus::utility::MapperServiceMap& serviceMap)
Jonathan Doman3cde86f2020-12-02 14:50:45 -08001016{
1017 // Check that the property even exists by checking for the interface
1018 const std::string* controlService = nullptr;
1019 for (const auto& [serviceName, interfaceList] : serviceMap)
1020 {
Ed Tanous3544d2a2023-08-06 18:12:20 -07001021 if (std::ranges::find(interfaceList,
1022 "xyz.openbmc_project.Control.Processor."
1023 "CurrentOperatingConfig") != interfaceList.end())
Jonathan Doman3cde86f2020-12-02 14:50:45 -08001024 {
1025 controlService = &serviceName;
1026 break;
1027 }
1028 }
1029
1030 if (controlService == nullptr)
1031 {
1032 messages::internalError(resp->res);
1033 return;
1034 }
1035
1036 // Check that the config URI is a child of the cpu URI being patched.
1037 std::string expectedPrefix("/redfish/v1/Systems/system/Processors/");
1038 expectedPrefix += processorId;
1039 expectedPrefix += "/OperatingConfigs/";
Ed Tanous11ba3972022-07-11 09:50:41 -07001040 if (!appliedConfigUri.starts_with(expectedPrefix) ||
Jonathan Doman3cde86f2020-12-02 14:50:45 -08001041 expectedPrefix.size() == appliedConfigUri.size())
1042 {
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001043 messages::propertyValueIncorrect(resp->res, "AppliedOperatingConfig",
1044 appliedConfigUri);
Jonathan Doman3cde86f2020-12-02 14:50:45 -08001045 return;
1046 }
1047
1048 // Generate the D-Bus path of the OperatingConfig object, by assuming it's a
1049 // direct child of the CPU object.
1050 // Strip the expectedPrefix from the config URI to get the "filename", and
1051 // append to the CPU's path.
1052 std::string configBaseName = appliedConfigUri.substr(expectedPrefix.size());
1053 sdbusplus::message::object_path configPath(cpuObjectPath);
1054 configPath /= configBaseName;
1055
Ed Tanous62598e32023-07-17 17:06:25 -07001056 BMCWEB_LOG_INFO("Setting config to {}", configPath.str);
Jonathan Doman3cde86f2020-12-02 14:50:45 -08001057
1058 // Set the property, with handler to check error responses
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001059 setDbusProperty(
1060 resp, *controlService, cpuObjectPath,
George Liu9ae226f2023-06-21 17:56:46 +08001061 "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001062 "AppliedConfig", "AppliedOperatingConfig", configPath);
Jonathan Doman3cde86f2020-12-02 14:50:45 -08001063}
1064
Ed Tanousac106bf2023-06-07 09:24:59 -07001065inline void
1066 handleProcessorHead(crow::App& app, const crow::Request& req,
1067 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1068 const std::string& /* systemName */,
1069 const std::string& /* processorId */)
Nikhil Namjoshi71a24ca2022-11-11 01:52:32 +00001070{
Ed Tanousac106bf2023-06-07 09:24:59 -07001071 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Nikhil Namjoshi71a24ca2022-11-11 01:52:32 +00001072 {
1073 return;
1074 }
Ed Tanousac106bf2023-06-07 09:24:59 -07001075 asyncResp->res.addHeader(
Nikhil Namjoshi71a24ca2022-11-11 01:52:32 +00001076 boost::beast::http::field::link,
1077 "</redfish/v1/JsonSchemas/Processor/Processor.json>; rel=describedby");
1078}
1079
1080inline void handleProcessorCollectionHead(
1081 crow::App& app, const crow::Request& req,
Ed Tanousac106bf2023-06-07 09:24:59 -07001082 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Nikhil Namjoshi71a24ca2022-11-11 01:52:32 +00001083 const std::string& /* systemName */)
1084{
Ed Tanousac106bf2023-06-07 09:24:59 -07001085 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Nikhil Namjoshi71a24ca2022-11-11 01:52:32 +00001086 {
1087 return;
1088 }
Ed Tanousac106bf2023-06-07 09:24:59 -07001089 asyncResp->res.addHeader(
Nikhil Namjoshi71a24ca2022-11-11 01:52:32 +00001090 boost::beast::http::field::link,
1091 "</redfish/v1/JsonSchemas/ProcessorCollection/ProcessorCollection.json>; rel=describedby");
1092}
1093
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001094inline void requestRoutesOperatingConfigCollection(App& app)
Jonathan Domandba0c292020-12-02 15:34:13 -08001095{
Ed Tanous7f3e84a2022-12-28 16:22:54 -08001096 BMCWEB_ROUTE(app,
1097 "/redfish/v1/Systems/<str>/Processors/<str>/OperatingConfigs/")
Ed Tanoused398212021-06-09 17:05:54 -07001098 .privileges(redfish::privileges::getOperatingConfigCollection)
Ed Tanous002d39b2022-05-31 08:59:27 -07001099 .methods(boost::beast::http::verb::get)(
1100 [&app](const crow::Request& req,
1101 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous7f3e84a2022-12-28 16:22:54 -08001102 const std::string& systemName, const std::string& cpuName) {
Carson Labrado3ba00072022-06-06 19:40:56 +00001103 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07001104 {
1105 return;
1106 }
Ed Tanous7f3e84a2022-12-28 16:22:54 -08001107
1108 if constexpr (bmcwebEnableMultiHost)
1109 {
1110 // Option currently returns no systems. TBD
1111 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1112 systemName);
1113 return;
1114 }
1115
1116 if (systemName != "system")
1117 {
1118 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1119 systemName);
1120 return;
1121 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001122 asyncResp->res.jsonValue["@odata.type"] =
1123 "#OperatingConfigCollection.OperatingConfigCollection";
Ed Tanousef4c65b2023-04-24 15:28:50 -07001124 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
1125 "/redfish/v1/Systems/system/Processors/{}/OperatingConfigs",
1126 cpuName);
Ed Tanous002d39b2022-05-31 08:59:27 -07001127 asyncResp->res.jsonValue["Name"] = "Operating Config Collection";
1128
1129 // First find the matching CPU object so we know how to
1130 // constrain our search for related Config objects.
George Liu7a1dbc42022-12-07 16:03:22 +08001131 const std::array<std::string_view, 1> interfaces = {
1132 "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig"};
1133 dbus::utility::getSubTreePaths(
1134 "/xyz/openbmc_project/inventory", 0, interfaces,
Ed Tanous002d39b2022-05-31 08:59:27 -07001135 [asyncResp, cpuName](
George Liu7a1dbc42022-12-07 16:03:22 +08001136 const boost::system::error_code& ec,
Ed Tanous002d39b2022-05-31 08:59:27 -07001137 const dbus::utility::MapperGetSubTreePathsResponse& objects) {
1138 if (ec)
Ed Tanous45ca1b82022-03-25 13:07:27 -07001139 {
Ed Tanous62598e32023-07-17 17:06:25 -07001140 BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec, ec.message());
Ed Tanous002d39b2022-05-31 08:59:27 -07001141 messages::internalError(asyncResp->res);
Ed Tanous45ca1b82022-03-25 13:07:27 -07001142 return;
1143 }
Jonathan Domandba0c292020-12-02 15:34:13 -08001144
Ed Tanous002d39b2022-05-31 08:59:27 -07001145 for (const std::string& object : objects)
1146 {
Ed Tanous11ba3972022-07-11 09:50:41 -07001147 if (!object.ends_with(cpuName))
Ed Tanous002d39b2022-05-31 08:59:27 -07001148 {
1149 continue;
1150 }
George Liu0fda0f12021-11-16 10:06:17 +08001151
Ed Tanous002d39b2022-05-31 08:59:27 -07001152 // Not expected that there will be multiple matching
1153 // CPU objects, but if there are just use the first
1154 // one.
Jonathan Domandba0c292020-12-02 15:34:13 -08001155
Ed Tanous002d39b2022-05-31 08:59:27 -07001156 // Use the common search routine to construct the
1157 // Collection of all Config objects under this CPU.
Patrick Williams5a39f772023-10-20 11:20:21 -05001158 constexpr std::array<std::string_view, 1> interface{
1159 "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig"};
Ed Tanous002d39b2022-05-31 08:59:27 -07001160 collection_util::getCollectionMembers(
1161 asyncResp,
Ed Tanousef4c65b2023-04-24 15:28:50 -07001162 boost::urls::format(
1163 "/redfish/v1/Systems/system/Processors/{}/OperatingConfigs",
1164 cpuName),
Lakshmi Yadlapati36b5f1e2023-09-26 23:53:28 -05001165 interface, object);
Ed Tanous002d39b2022-05-31 08:59:27 -07001166 return;
1167 }
George Liu0fda0f12021-11-16 10:06:17 +08001168 });
Patrick Williams5a39f772023-10-20 11:20:21 -05001169 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001170}
1171
1172inline void requestRoutesOperatingConfig(App& app)
1173{
1174 BMCWEB_ROUTE(
1175 app,
Ed Tanous7f3e84a2022-12-28 16:22:54 -08001176 "/redfish/v1/Systems/<str>/Processors/<str>/OperatingConfigs/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001177 .privileges(redfish::privileges::getOperatingConfig)
Ed Tanous002d39b2022-05-31 08:59:27 -07001178 .methods(boost::beast::http::verb::get)(
1179 [&app](const crow::Request& req,
1180 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous7f3e84a2022-12-28 16:22:54 -08001181 const std::string& systemName, const std::string& cpuName,
1182 const std::string& configName) {
Carson Labrado3ba00072022-06-06 19:40:56 +00001183 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07001184 {
1185 return;
1186 }
Ed Tanous7f3e84a2022-12-28 16:22:54 -08001187 if constexpr (bmcwebEnableMultiHost)
1188 {
1189 // Option currently returns no systems. TBD
1190 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1191 systemName);
1192 return;
1193 }
1194
1195 if (systemName != "system")
1196 {
1197 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1198 systemName);
1199 return;
1200 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001201 // Ask for all objects implementing OperatingConfig so we can search
1202 // for one with a matching name
George Liue99073f2022-12-09 11:06:16 +08001203 constexpr std::array<std::string_view, 1> interfaces = {
1204 "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig"};
1205 dbus::utility::getSubTree(
1206 "/xyz/openbmc_project/inventory", 0, interfaces,
Ed Tanous39662a32023-02-06 15:09:46 -08001207 [asyncResp, cpuName, configName](
George Liue99073f2022-12-09 11:06:16 +08001208 const boost::system::error_code& ec,
Ed Tanous002d39b2022-05-31 08:59:27 -07001209 const dbus::utility::MapperGetSubTreeResponse& subtree) {
1210 if (ec)
Ed Tanous45ca1b82022-03-25 13:07:27 -07001211 {
Ed Tanous62598e32023-07-17 17:06:25 -07001212 BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec, ec.message());
Ed Tanous002d39b2022-05-31 08:59:27 -07001213 messages::internalError(asyncResp->res);
Ed Tanous45ca1b82022-03-25 13:07:27 -07001214 return;
1215 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001216 const std::string expectedEnding = cpuName + '/' + configName;
1217 for (const auto& [objectPath, serviceMap] : subtree)
1218 {
1219 // Ignore any configs without matching cpuX/configY
Ed Tanous11ba3972022-07-11 09:50:41 -07001220 if (!objectPath.ends_with(expectedEnding) || serviceMap.empty())
Ed Tanous002d39b2022-05-31 08:59:27 -07001221 {
1222 continue;
1223 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001224
Ed Tanous002d39b2022-05-31 08:59:27 -07001225 nlohmann::json& json = asyncResp->res.jsonValue;
1226 json["@odata.type"] = "#OperatingConfig.v1_0_0.OperatingConfig";
Ed Tanousef4c65b2023-04-24 15:28:50 -07001227 json["@odata.id"] = boost::urls::format(
1228 "/redfish/v1/Systems/system/Processors/{}/OperatingConfigs/{}",
1229 cpuName, configName);
Ed Tanous002d39b2022-05-31 08:59:27 -07001230 json["Name"] = "Processor Profile";
1231 json["Id"] = configName;
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001232
Ed Tanous002d39b2022-05-31 08:59:27 -07001233 // Just use the first implementation of the object - not
1234 // expected that there would be multiple matching
1235 // services
1236 getOperatingConfigData(asyncResp, serviceMap.begin()->first,
1237 objectPath);
1238 return;
1239 }
1240 messages::resourceNotFound(asyncResp->res, "OperatingConfig",
1241 configName);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001242 });
Patrick Williams5a39f772023-10-20 11:20:21 -05001243 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001244}
Jonathan Domandba0c292020-12-02 15:34:13 -08001245
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001246inline void requestRoutesProcessorCollection(App& app)
Gunnar Millsac6a4442020-10-14 14:55:29 -05001247{
Gunnar Millsac6a4442020-10-14 14:55:29 -05001248 /**
1249 * Functions triggers appropriate requests on DBus
1250 */
Ed Tanous22d268c2022-05-19 09:39:07 -07001251 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/")
Nikhil Namjoshi71a24ca2022-11-11 01:52:32 +00001252 .privileges(redfish::privileges::headProcessorCollection)
1253 .methods(boost::beast::http::verb::head)(
1254 std::bind_front(handleProcessorCollectionHead, std::ref(app)));
1255
1256 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/")
Ed Tanoused398212021-06-09 17:05:54 -07001257 .privileges(redfish::privileges::getProcessorCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001258 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07001259 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07001260 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1261 const std::string& systemName) {
Carson Labrado3ba00072022-06-06 19:40:56 +00001262 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07001263 {
1264 return;
1265 }
Ed Tanous7f3e84a2022-12-28 16:22:54 -08001266 if constexpr (bmcwebEnableMultiHost)
1267 {
1268 // Option currently returns no systems. TBD
1269 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1270 systemName);
1271 return;
1272 }
1273
Ed Tanous22d268c2022-05-19 09:39:07 -07001274 if (systemName != "system")
1275 {
1276 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1277 systemName);
1278 return;
1279 }
1280
Nikhil Namjoshi71a24ca2022-11-11 01:52:32 +00001281 asyncResp->res.addHeader(
1282 boost::beast::http::field::link,
1283 "</redfish/v1/JsonSchemas/ProcessorCollection/ProcessorCollection.json>; rel=describedby");
1284
Ed Tanous002d39b2022-05-31 08:59:27 -07001285 asyncResp->res.jsonValue["@odata.type"] =
1286 "#ProcessorCollection.ProcessorCollection";
1287 asyncResp->res.jsonValue["Name"] = "Processor Collection";
Gunnar Millsac6a4442020-10-14 14:55:29 -05001288
Ed Tanous002d39b2022-05-31 08:59:27 -07001289 asyncResp->res.jsonValue["@odata.id"] =
1290 "/redfish/v1/Systems/system/Processors";
Gunnar Millsac6a4442020-10-14 14:55:29 -05001291
Ed Tanous002d39b2022-05-31 08:59:27 -07001292 collection_util::getCollectionMembers(
Willy Tuae9031f2022-09-27 05:48:07 +00001293 asyncResp,
1294 boost::urls::url("/redfish/v1/Systems/system/Processors"),
Lakshmi Yadlapati36b5f1e2023-09-26 23:53:28 -05001295 processorInterfaces, "/xyz/openbmc_project/inventory");
Patrick Williams5a39f772023-10-20 11:20:21 -05001296 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001297}
Gunnar Millsac6a4442020-10-14 14:55:29 -05001298
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001299inline void requestRoutesProcessor(App& app)
Gunnar Millsac6a4442020-10-14 14:55:29 -05001300{
Gunnar Millsac6a4442020-10-14 14:55:29 -05001301 /**
1302 * Functions triggers appropriate requests on DBus
1303 */
Gunnar Millsac6a4442020-10-14 14:55:29 -05001304
Ed Tanous22d268c2022-05-19 09:39:07 -07001305 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/<str>/")
Nikhil Namjoshi71a24ca2022-11-11 01:52:32 +00001306 .privileges(redfish::privileges::headProcessor)
1307 .methods(boost::beast::http::verb::head)(
1308 std::bind_front(handleProcessorHead, std::ref(app)));
1309
1310 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001311 .privileges(redfish::privileges::getProcessor)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001312 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07001313 [&app](const crow::Request& req,
1314 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous22d268c2022-05-19 09:39:07 -07001315 const std::string& systemName,
Ed Tanous45ca1b82022-03-25 13:07:27 -07001316 const std::string& processorId) {
Carson Labrado3ba00072022-06-06 19:40:56 +00001317 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07001318 {
1319 return;
1320 }
Ed Tanous7f3e84a2022-12-28 16:22:54 -08001321 if constexpr (bmcwebEnableMultiHost)
1322 {
1323 // Option currently returns no systems. TBD
1324 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1325 systemName);
1326 return;
1327 }
Ed Tanous22d268c2022-05-19 09:39:07 -07001328 if (systemName != "system")
1329 {
1330 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1331 systemName);
1332 return;
1333 }
1334
Nikhil Namjoshi71a24ca2022-11-11 01:52:32 +00001335 asyncResp->res.addHeader(
1336 boost::beast::http::field::link,
1337 "</redfish/v1/JsonSchemas/Processor/Processor.json>; rel=describedby");
Ed Tanous002d39b2022-05-31 08:59:27 -07001338 asyncResp->res.jsonValue["@odata.type"] =
Chris Caindfbf7de2023-04-13 16:01:04 -05001339 "#Processor.v1_18_0.Processor";
Ed Tanousef4c65b2023-04-24 15:28:50 -07001340 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
1341 "/redfish/v1/Systems/system/Processors/{}", processorId);
Jonathan Doman3cde86f2020-12-02 14:50:45 -08001342
Ed Tanous8a592812022-06-04 09:06:59 -07001343 getProcessorObject(
1344 asyncResp, processorId,
1345 std::bind_front(getProcessorData, asyncResp, processorId));
Patrick Williams5a39f772023-10-20 11:20:21 -05001346 });
Jonathan Doman3cde86f2020-12-02 14:50:45 -08001347
Ed Tanous22d268c2022-05-19 09:39:07 -07001348 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001349 .privileges(redfish::privileges::patchProcessor)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001350 .methods(boost::beast::http::verb::patch)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07001351 [&app](const crow::Request& req,
1352 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous22d268c2022-05-19 09:39:07 -07001353 const std::string& systemName,
Ed Tanous45ca1b82022-03-25 13:07:27 -07001354 const std::string& processorId) {
Carson Labrado3ba00072022-06-06 19:40:56 +00001355 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07001356 {
1357 return;
1358 }
Ed Tanous7f3e84a2022-12-28 16:22:54 -08001359 if constexpr (bmcwebEnableMultiHost)
1360 {
1361 // Option currently returns no systems. TBD
1362 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1363 systemName);
1364 return;
1365 }
Ed Tanous22d268c2022-05-19 09:39:07 -07001366 if (systemName != "system")
1367 {
1368 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1369 systemName);
1370 return;
1371 }
1372
Ed Tanous3c569212024-03-06 14:46:18 -08001373 std::optional<std::string> appliedConfigUri;
Ed Tanous002d39b2022-05-31 08:59:27 -07001374 if (!json_util::readJsonPatch(req, asyncResp->res,
Ed Tanous3c569212024-03-06 14:46:18 -08001375 "AppliedOperatingConfig/@odata.id",
1376 appliedConfigUri))
Ed Tanous002d39b2022-05-31 08:59:27 -07001377 {
1378 return;
1379 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001380
Ed Tanous3c569212024-03-06 14:46:18 -08001381 if (appliedConfigUri)
Ed Tanous002d39b2022-05-31 08:59:27 -07001382 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001383 // Check for 404 and find matching D-Bus object, then run
1384 // property patch handlers if that all succeeds.
Ed Tanous8a592812022-06-04 09:06:59 -07001385 getProcessorObject(asyncResp, processorId,
1386 std::bind_front(patchAppliedOperatingConfig,
1387 asyncResp, processorId,
Ed Tanous3c569212024-03-06 14:46:18 -08001388 *appliedConfigUri));
Ed Tanous002d39b2022-05-31 08:59:27 -07001389 }
Patrick Williams5a39f772023-10-20 11:20:21 -05001390 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001391}
Gunnar Millsac6a4442020-10-14 14:55:29 -05001392
1393} // namespace redfish