blob: 7fe858f50292c85710cd2d7fb3732e5c1bedea38 [file] [log] [blame]
Ed Tanous40e9b922024-09-10 13:50:16 -07001// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright OpenBMC Authors
3// SPDX-FileCopyrightText: Copyright 2018 Intel Corporation
Gunnar Millsac6a4442020-10-14 14:55:29 -05004#pragma once
5
Ed Tanousd7857202025-01-28 15:32:26 -08006#include "bmcweb_config.h"
7
Ed Tanous3ccb3ad2023-01-13 17:40:03 -08008#include "app.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -08009#include "async_resp.hpp"
George Liu7a1dbc42022-12-07 16:03:22 +080010#include "dbus_utility.hpp"
Jonathan Doman1e1e5982021-06-11 09:36:17 -070011#include "error_messages.hpp"
Chris Caindfbf7de2023-04-13 16:01:04 -050012#include "generated/enums/processor.hpp"
Ed Tanous539d8c62024-06-19 14:38:27 -070013#include "generated/enums/resource.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -080014#include "http_request.hpp"
George Liu98eafce2020-10-03 16:46:04 +080015#include "led.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -080016#include "logging.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080017#include "query.hpp"
18#include "registries/privilege_registry.hpp"
19#include "utils/collection.hpp"
20#include "utils/dbus_utils.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -080021#include "utils/hex_utils.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080022#include "utils/json_utils.hpp"
Gunnar Millsac6a4442020-10-14 14:55:29 -050023
Ed Tanousd7857202025-01-28 15:32:26 -080024#include <boost/beast/http/field.hpp>
25#include <boost/beast/http/verb.hpp>
George Liue99073f2022-12-09 11:06:16 +080026#include <boost/system/error_code.hpp>
Ed Tanousef4c65b2023-04-24 15:28:50 -070027#include <boost/url/format.hpp>
Jonathan Domandba0c292020-12-02 15:34:13 -080028#include <sdbusplus/message/native_types.hpp>
Krzysztof Grobelny351053f2022-07-28 15:44:22 +020029#include <sdbusplus/unpack_properties.hpp>
Gunnar Millsac6a4442020-10-14 14:55:29 -050030
Ed Tanousd7857202025-01-28 15:32:26 -080031#include <algorithm>
George Liu7a1dbc42022-12-07 16:03:22 +080032#include <array>
Ed Tanousd7857202025-01-28 15:32:26 -080033#include <cstddef>
34#include <cstdint>
35#include <format>
36#include <functional>
Michael Shenb9d679d2023-02-13 02:29:04 +000037#include <limits>
Ed Tanousd7857202025-01-28 15:32:26 -080038#include <memory>
39#include <optional>
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>
Ed Tanousd7857202025-01-28 15:32:26 -080043#include <tuple>
44#include <utility>
45#include <variant>
46#include <vector>
George Liu7a1dbc42022-12-07 16:03:22 +080047
Gunnar Millsac6a4442020-10-14 14:55:29 -050048namespace redfish
49{
50
Jonathan Domanc9514482021-02-24 09:20:51 -080051// Interfaces which imply a D-Bus object represents a Processor
George Liu7a1dbc42022-12-07 16:03:22 +080052constexpr std::array<std::string_view, 2> processorInterfaces = {
Jonathan Domanc9514482021-02-24 09:20:51 -080053 "xyz.openbmc_project.Inventory.Item.Cpu",
54 "xyz.openbmc_project.Inventory.Item.Accelerator"};
Jonathan Doman2bab9832020-12-02 15:27:40 -080055
Sharad Yadav71b82f22021-05-10 15:11:39 +053056/**
57 * @brief Fill out uuid info of a processor by
58 * requesting data from the given D-Bus object.
59 *
Ed Tanousac106bf2023-06-07 09:24:59 -070060 * @param[in,out] asyncResp Async HTTP response.
Sharad Yadav71b82f22021-05-10 15:11:39 +053061 * @param[in] service D-Bus service to query.
62 * @param[in] objPath D-Bus object to query.
63 */
Ed Tanousac106bf2023-06-07 09:24:59 -070064inline void getProcessorUUID(std::shared_ptr<bmcweb::AsyncResp> asyncResp,
Sharad Yadav71b82f22021-05-10 15:11:39 +053065 const std::string& service,
66 const std::string& objPath)
67{
Ed Tanous62598e32023-07-17 17:06:25 -070068 BMCWEB_LOG_DEBUG("Get Processor UUID");
Ed Tanousdeae6a72024-11-11 21:58:57 -080069 dbus::utility::getProperty<std::string>(
70 service, objPath, "xyz.openbmc_project.Common.UUID", "UUID",
Ed Tanousac106bf2023-06-07 09:24:59 -070071 [objPath, asyncResp{std::move(asyncResp)}](
72 const boost::system::error_code& ec, const std::string& property) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -040073 if (ec)
74 {
75 BMCWEB_LOG_DEBUG("DBUS response error");
76 messages::internalError(asyncResp->res);
77 return;
78 }
79 asyncResp->res.jsonValue["UUID"] = property;
80 });
Sharad Yadav71b82f22021-05-10 15:11:39 +053081}
82
Ed Tanous711ac7a2021-12-20 09:34:41 -080083inline void getCpuDataByInterface(
Ed Tanousac106bf2023-06-07 09:24:59 -070084 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Michael Shen80f79a42023-08-24 13:41:53 +000085 const dbus::utility::DBusInterfacesMap& cpuInterfacesProperties)
Gunnar Millsac6a4442020-10-14 14:55:29 -050086{
Ed Tanous62598e32023-07-17 17:06:25 -070087 BMCWEB_LOG_DEBUG("Get CPU resources by interface.");
Gunnar Millsac6a4442020-10-14 14:55:29 -050088
Chicago Duana1649ec2021-03-30 16:54:58 +080089 // Set the default value of state
Ed Tanous539d8c62024-06-19 14:38:27 -070090 asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled;
91 asyncResp->res.jsonValue["Status"]["Health"] = resource::Health::OK;
Gunnar Millsac6a4442020-10-14 14:55:29 -050092
93 for (const auto& interface : cpuInterfacesProperties)
94 {
95 for (const auto& property : interface.second)
96 {
Chicago Duana1649ec2021-03-30 16:54:58 +080097 if (property.first == "Present")
Gunnar Millsac6a4442020-10-14 14:55:29 -050098 {
Chicago Duana1649ec2021-03-30 16:54:58 +080099 const bool* cpuPresent = std::get_if<bool>(&property.second);
100 if (cpuPresent == nullptr)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500101 {
102 // Important property not in desired type
Ed Tanousac106bf2023-06-07 09:24:59 -0700103 messages::internalError(asyncResp->res);
Gunnar Millsac6a4442020-10-14 14:55:29 -0500104 return;
105 }
Ed Tanouse05aec52022-01-25 10:28:56 -0800106 if (!*cpuPresent)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500107 {
Chicago Duana1649ec2021-03-30 16:54:58 +0800108 // Slot is not populated
Ed Tanous539d8c62024-06-19 14:38:27 -0700109 asyncResp->res.jsonValue["Status"]["State"] =
110 resource::State::Absent;
Chicago Duana1649ec2021-03-30 16:54:58 +0800111 }
112 }
113 else if (property.first == "Functional")
114 {
115 const bool* cpuFunctional = std::get_if<bool>(&property.second);
116 if (cpuFunctional == nullptr)
117 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700118 messages::internalError(asyncResp->res);
Gunnar Millsac6a4442020-10-14 14:55:29 -0500119 return;
120 }
Ed Tanouse05aec52022-01-25 10:28:56 -0800121 if (!*cpuFunctional)
Chicago Duana1649ec2021-03-30 16:54:58 +0800122 {
Ed Tanous539d8c62024-06-19 14:38:27 -0700123 asyncResp->res.jsonValue["Status"]["Health"] =
124 resource::Health::Critical;
Chicago Duana1649ec2021-03-30 16:54:58 +0800125 }
126 }
127 else if (property.first == "CoreCount")
128 {
129 const uint16_t* coresCount =
130 std::get_if<uint16_t>(&property.second);
131 if (coresCount == nullptr)
132 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700133 messages::internalError(asyncResp->res);
Chicago Duana1649ec2021-03-30 16:54:58 +0800134 return;
135 }
Ed Tanousac106bf2023-06-07 09:24:59 -0700136 asyncResp->res.jsonValue["TotalCores"] = *coresCount;
Gunnar Millsac6a4442020-10-14 14:55:29 -0500137 }
Jonathan Domandc3fa662020-10-26 23:10:24 -0700138 else if (property.first == "MaxSpeedInMhz")
139 {
140 const uint32_t* value = std::get_if<uint32_t>(&property.second);
141 if (value != nullptr)
142 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700143 asyncResp->res.jsonValue["MaxSpeedMHz"] = *value;
Jonathan Domandc3fa662020-10-26 23:10:24 -0700144 }
145 }
Gunnar Millsac6a4442020-10-14 14:55:29 -0500146 else if (property.first == "Socket")
147 {
148 const std::string* value =
149 std::get_if<std::string>(&property.second);
150 if (value != nullptr)
151 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700152 asyncResp->res.jsonValue["Socket"] = *value;
Gunnar Millsac6a4442020-10-14 14:55:29 -0500153 }
154 }
155 else if (property.first == "ThreadCount")
156 {
Jonathan Domandc3fa662020-10-26 23:10:24 -0700157 const uint16_t* value = std::get_if<uint16_t>(&property.second);
Gunnar Millsac6a4442020-10-14 14:55:29 -0500158 if (value != nullptr)
159 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700160 asyncResp->res.jsonValue["TotalThreads"] = *value;
Gunnar Millsac6a4442020-10-14 14:55:29 -0500161 }
162 }
Brandon Kim1930fbd2021-09-14 17:52:51 -0700163 else if (property.first == "EffectiveFamily")
Gunnar Millsac6a4442020-10-14 14:55:29 -0500164 {
Brandon Kim1930fbd2021-09-14 17:52:51 -0700165 const uint16_t* value = std::get_if<uint16_t>(&property.second);
Brad Bishop6169de22022-09-14 13:08:32 -0400166 if (value != nullptr && *value != 2)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500167 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700168 asyncResp->res.jsonValue["ProcessorId"]["EffectiveFamily"] =
Ed Tanous866e4862022-02-17 11:40:25 -0800169 "0x" + intToHexString(*value, 4);
Gunnar Millsac6a4442020-10-14 14:55:29 -0500170 }
171 }
Brandon Kim1930fbd2021-09-14 17:52:51 -0700172 else if (property.first == "EffectiveModel")
173 {
174 const uint16_t* value = std::get_if<uint16_t>(&property.second);
175 if (value == nullptr)
176 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700177 messages::internalError(asyncResp->res);
Brandon Kim1930fbd2021-09-14 17:52:51 -0700178 return;
179 }
Brad Bishop6169de22022-09-14 13:08:32 -0400180 if (*value != 0)
181 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700182 asyncResp->res.jsonValue["ProcessorId"]["EffectiveModel"] =
Brad Bishop6169de22022-09-14 13:08:32 -0400183 "0x" + intToHexString(*value, 4);
184 }
Brandon Kim1930fbd2021-09-14 17:52:51 -0700185 }
Gunnar Millsac6a4442020-10-14 14:55:29 -0500186 else if (property.first == "Id")
187 {
188 const uint64_t* value = std::get_if<uint64_t>(&property.second);
189 if (value != nullptr && *value != 0)
190 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700191 asyncResp->res
Gunnar Millsac6a4442020-10-14 14:55:29 -0500192 .jsonValue["ProcessorId"]["IdentificationRegisters"] =
Ed Tanous866e4862022-02-17 11:40:25 -0800193 "0x" + intToHexString(*value, 16);
Gunnar Millsac6a4442020-10-14 14:55:29 -0500194 }
195 }
Brandon Kim1930fbd2021-09-14 17:52:51 -0700196 else if (property.first == "Microcode")
197 {
198 const uint32_t* value = std::get_if<uint32_t>(&property.second);
199 if (value == nullptr)
200 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700201 messages::internalError(asyncResp->res);
Brandon Kim1930fbd2021-09-14 17:52:51 -0700202 return;
203 }
Brad Bishop6169de22022-09-14 13:08:32 -0400204 if (*value != 0)
205 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700206 asyncResp->res.jsonValue["ProcessorId"]["MicrocodeInfo"] =
Brad Bishop6169de22022-09-14 13:08:32 -0400207 "0x" + intToHexString(*value, 8);
208 }
Brandon Kim1930fbd2021-09-14 17:52:51 -0700209 }
210 else if (property.first == "Step")
211 {
212 const uint16_t* value = std::get_if<uint16_t>(&property.second);
213 if (value == nullptr)
214 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700215 messages::internalError(asyncResp->res);
Brandon Kim1930fbd2021-09-14 17:52:51 -0700216 return;
217 }
Michael Shenb9d679d2023-02-13 02:29:04 +0000218 if (*value != std::numeric_limits<uint16_t>::max())
Brad Bishop6169de22022-09-14 13:08:32 -0400219 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700220 asyncResp->res.jsonValue["ProcessorId"]["Step"] =
Brad Bishop6169de22022-09-14 13:08:32 -0400221 "0x" + intToHexString(*value, 4);
222 }
Brandon Kim1930fbd2021-09-14 17:52:51 -0700223 }
Gunnar Millsac6a4442020-10-14 14:55:29 -0500224 }
225 }
Gunnar Millsac6a4442020-10-14 14:55:29 -0500226}
227
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400228inline void getCpuDataByService(
229 std::shared_ptr<bmcweb::AsyncResp> asyncResp, const std::string& cpuId,
230 const std::string& service, const std::string& objPath)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500231{
Ed Tanous62598e32023-07-17 17:06:25 -0700232 BMCWEB_LOG_DEBUG("Get available system cpu resources by service.");
Gunnar Millsac6a4442020-10-14 14:55:29 -0500233
George Liu5eb468d2023-06-20 17:03:24 +0800234 sdbusplus::message::object_path path("/xyz/openbmc_project/inventory");
235 dbus::utility::getManagedObjects(
236 service, path,
Ed Tanousac106bf2023-06-07 09:24:59 -0700237 [cpuId, service, objPath, asyncResp{std::move(asyncResp)}](
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800238 const boost::system::error_code& ec,
Gunnar Millsac6a4442020-10-14 14:55:29 -0500239 const dbus::utility::ManagedObjectType& dbusData) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400240 if (ec)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500241 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400242 BMCWEB_LOG_DEBUG("DBUS response error");
243 messages::internalError(asyncResp->res);
244 return;
Ed Tanous002d39b2022-05-31 08:59:27 -0700245 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400246 asyncResp->res.jsonValue["Id"] = cpuId;
247 asyncResp->res.jsonValue["Name"] = "Processor";
248 asyncResp->res.jsonValue["ProcessorType"] =
249 processor::ProcessorType::CPU;
250
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400251 for (const auto& object : dbusData)
Ed Tanous002d39b2022-05-31 08:59:27 -0700252 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400253 if (object.first.str == objPath)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500254 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400255 getCpuDataByInterface(asyncResp, object.second);
256 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400257 }
258 return;
259 });
Gunnar Millsac6a4442020-10-14 14:55:29 -0500260}
261
Chris Caindfbf7de2023-04-13 16:01:04 -0500262/**
263 * @brief Translates throttle cause DBUS property to redfish.
264 *
265 * @param[in] dbusSource The throttle cause from DBUS
266 *
267 * @return Returns as a string, the throttle cause in Redfish terms. If
268 * translation cannot be done, returns "Unknown" throttle reason.
269 */
Patrick Williams504af5a2025-02-03 14:29:03 -0500270inline processor::ThrottleCause dbusToRfThrottleCause(
271 const std::string& dbusSource)
Chris Caindfbf7de2023-04-13 16:01:04 -0500272{
273 if (dbusSource ==
274 "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.ClockLimit")
275 {
276 return processor::ThrottleCause::ClockLimit;
277 }
278 if (dbusSource ==
279 "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.ManagementDetectedFault")
280 {
281 return processor::ThrottleCause::ManagementDetectedFault;
282 }
283 if (dbusSource ==
284 "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.PowerLimit")
285 {
286 return processor::ThrottleCause::PowerLimit;
287 }
288 if (dbusSource ==
289 "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.ThermalLimit")
290 {
291 return processor::ThrottleCause::ThermalLimit;
292 }
293 if (dbusSource ==
294 "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.Unknown")
295 {
296 return processor::ThrottleCause::Unknown;
297 }
298 return processor::ThrottleCause::Invalid;
299}
300
Patrick Williams504af5a2025-02-03 14:29:03 -0500301inline void readThrottleProperties(
302 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
303 const boost::system::error_code& ec,
304 const dbus::utility::DBusPropertiesMap& properties)
Chris Caindfbf7de2023-04-13 16:01:04 -0500305{
306 if (ec)
307 {
Ed Tanous62598e32023-07-17 17:06:25 -0700308 BMCWEB_LOG_ERROR("Processor Throttle getAllProperties error {}", ec);
Ed Tanousac106bf2023-06-07 09:24:59 -0700309 messages::internalError(asyncResp->res);
Chris Caindfbf7de2023-04-13 16:01:04 -0500310 return;
311 }
312
313 const bool* status = nullptr;
314 const std::vector<std::string>* causes = nullptr;
315
316 if (!sdbusplus::unpackPropertiesNoThrow(dbus_utils::UnpackErrorPrinter(),
317 properties, "Throttled", status,
318 "ThrottleCauses", causes))
319 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700320 messages::internalError(asyncResp->res);
Chris Caindfbf7de2023-04-13 16:01:04 -0500321 return;
322 }
323
Ed Tanousac106bf2023-06-07 09:24:59 -0700324 asyncResp->res.jsonValue["Throttled"] = *status;
Chris Caindfbf7de2023-04-13 16:01:04 -0500325 nlohmann::json::array_t rCauses;
326 for (const std::string& cause : *causes)
327 {
328 processor::ThrottleCause rfCause = dbusToRfThrottleCause(cause);
329 if (rfCause == processor::ThrottleCause::Invalid)
330 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700331 messages::internalError(asyncResp->res);
Chris Caindfbf7de2023-04-13 16:01:04 -0500332 return;
333 }
334
335 rCauses.emplace_back(rfCause);
336 }
Ed Tanousac106bf2023-06-07 09:24:59 -0700337 asyncResp->res.jsonValue["ThrottleCauses"] = std::move(rCauses);
Chris Caindfbf7de2023-04-13 16:01:04 -0500338}
339
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400340inline void getThrottleProperties(
341 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
342 const std::string& service, const std::string& objectPath)
Chris Caindfbf7de2023-04-13 16:01:04 -0500343{
Ed Tanous62598e32023-07-17 17:06:25 -0700344 BMCWEB_LOG_DEBUG("Get processor throttle resources");
Chris Caindfbf7de2023-04-13 16:01:04 -0500345
Ed Tanousdeae6a72024-11-11 21:58:57 -0800346 dbus::utility::getAllProperties(
347 service, objectPath, "xyz.openbmc_project.Control.Power.Throttle",
Ed Tanousac106bf2023-06-07 09:24:59 -0700348 [asyncResp](const boost::system::error_code& ec,
349 const dbus::utility::DBusPropertiesMap& properties) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400350 readThrottleProperties(asyncResp, ec, properties);
351 });
Chris Caindfbf7de2023-04-13 16:01:04 -0500352}
353
Ed Tanousac106bf2023-06-07 09:24:59 -0700354inline void getCpuAssetData(std::shared_ptr<bmcweb::AsyncResp> asyncResp,
Gunnar Millsac6a4442020-10-14 14:55:29 -0500355 const std::string& service,
356 const std::string& objPath)
357{
Ed Tanous62598e32023-07-17 17:06:25 -0700358 BMCWEB_LOG_DEBUG("Get Cpu Asset Data");
Ed Tanousdeae6a72024-11-11 21:58:57 -0800359 dbus::utility::getAllProperties(
360 service, objPath, "xyz.openbmc_project.Inventory.Decorator.Asset",
Ed Tanousac106bf2023-06-07 09:24:59 -0700361 [objPath, asyncResp{std::move(asyncResp)}](
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800362 const boost::system::error_code& ec,
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200363 const dbus::utility::DBusPropertiesMap& properties) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400364 if (ec)
Ed Tanous002d39b2022-05-31 08:59:27 -0700365 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400366 BMCWEB_LOG_DEBUG("DBUS response error");
367 messages::internalError(asyncResp->res);
368 return;
Ed Tanous002d39b2022-05-31 08:59:27 -0700369 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400370
371 const std::string* serialNumber = nullptr;
372 const std::string* model = nullptr;
373 const std::string* manufacturer = nullptr;
374 const std::string* partNumber = nullptr;
375 const std::string* sparePartNumber = nullptr;
376
377 const bool success = sdbusplus::unpackPropertiesNoThrow(
378 dbus_utils::UnpackErrorPrinter(), properties, "SerialNumber",
379 serialNumber, "Model", model, "Manufacturer", manufacturer,
380 "PartNumber", partNumber, "SparePartNumber", sparePartNumber);
381
382 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -0700383 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400384 messages::internalError(asyncResp->res);
385 return;
Ed Tanous002d39b2022-05-31 08:59:27 -0700386 }
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200387
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400388 if (serialNumber != nullptr && !serialNumber->empty())
389 {
390 asyncResp->res.jsonValue["SerialNumber"] = *serialNumber;
391 }
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200392
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400393 if ((model != nullptr) && !model->empty())
394 {
395 asyncResp->res.jsonValue["Model"] = *model;
396 }
397
398 if (manufacturer != nullptr)
399 {
400 asyncResp->res.jsonValue["Manufacturer"] = *manufacturer;
401
402 // Otherwise would be unexpected.
403 if (manufacturer->find("Intel") != std::string::npos)
404 {
405 asyncResp->res.jsonValue["ProcessorArchitecture"] = "x86";
406 asyncResp->res.jsonValue["InstructionSet"] = "x86-64";
407 }
408 else if (manufacturer->find("IBM") != std::string::npos)
409 {
410 asyncResp->res.jsonValue["ProcessorArchitecture"] = "Power";
411 asyncResp->res.jsonValue["InstructionSet"] = "PowerISA";
412 }
Rebecca Cran4d0c0c42025-08-11 14:33:12 -0600413 else if (manufacturer->find("Ampere") != std::string::npos)
414 {
415 asyncResp->res.jsonValue["ProcessorArchitecture"] = "ARM";
416 asyncResp->res.jsonValue["InstructionSet"] = "ARM-A64";
417 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400418 }
419
420 if (partNumber != nullptr)
421 {
422 asyncResp->res.jsonValue["PartNumber"] = *partNumber;
423 }
424
425 if (sparePartNumber != nullptr && !sparePartNumber->empty())
426 {
427 asyncResp->res.jsonValue["SparePartNumber"] = *sparePartNumber;
428 }
429 });
Gunnar Millsac6a4442020-10-14 14:55:29 -0500430}
431
Ed Tanousac106bf2023-06-07 09:24:59 -0700432inline void getCpuRevisionData(std::shared_ptr<bmcweb::AsyncResp> asyncResp,
Gunnar Millsac6a4442020-10-14 14:55:29 -0500433 const std::string& service,
434 const std::string& objPath)
435{
Ed Tanous62598e32023-07-17 17:06:25 -0700436 BMCWEB_LOG_DEBUG("Get Cpu Revision Data");
Ed Tanousdeae6a72024-11-11 21:58:57 -0800437 dbus::utility::getAllProperties(
438 service, objPath, "xyz.openbmc_project.Inventory.Decorator.Revision",
Ed Tanousac106bf2023-06-07 09:24:59 -0700439 [objPath, asyncResp{std::move(asyncResp)}](
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800440 const boost::system::error_code& ec,
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200441 const dbus::utility::DBusPropertiesMap& properties) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400442 if (ec)
443 {
444 BMCWEB_LOG_DEBUG("DBUS response error");
445 messages::internalError(asyncResp->res);
446 return;
447 }
Gunnar Millsac6a4442020-10-14 14:55:29 -0500448
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400449 const std::string* version = nullptr;
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200450
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400451 const bool success = sdbusplus::unpackPropertiesNoThrow(
452 dbus_utils::UnpackErrorPrinter(), properties, "Version",
453 version);
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200454
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400455 if (!success)
456 {
457 messages::internalError(asyncResp->res);
458 return;
459 }
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200460
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400461 if (version != nullptr)
462 {
463 asyncResp->res.jsonValue["Version"] = *version;
464 }
465 });
Gunnar Millsac6a4442020-10-14 14:55:29 -0500466}
467
zhanghch058d1b46d2021-04-01 11:18:24 +0800468inline void getAcceleratorDataByService(
Ed Tanousac106bf2023-06-07 09:24:59 -0700469 std::shared_ptr<bmcweb::AsyncResp> asyncResp, const std::string& acclrtrId,
zhanghch058d1b46d2021-04-01 11:18:24 +0800470 const std::string& service, const std::string& objPath)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500471{
Ed Tanous62598e32023-07-17 17:06:25 -0700472 BMCWEB_LOG_DEBUG("Get available system Accelerator resources by service.");
Ed Tanousdeae6a72024-11-11 21:58:57 -0800473 dbus::utility::getAllProperties(
474 service, objPath, "",
Ed Tanousac106bf2023-06-07 09:24:59 -0700475 [acclrtrId, asyncResp{std::move(asyncResp)}](
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800476 const boost::system::error_code& ec,
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200477 const dbus::utility::DBusPropertiesMap& properties) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400478 if (ec)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500479 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400480 BMCWEB_LOG_DEBUG("DBUS response error");
481 messages::internalError(asyncResp->res);
482 return;
Gunnar Millsac6a4442020-10-14 14:55:29 -0500483 }
484
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400485 const bool* functional = nullptr;
486 const bool* present = nullptr;
487
488 const bool success = sdbusplus::unpackPropertiesNoThrow(
489 dbus_utils::UnpackErrorPrinter(), properties, "Functional",
490 functional, "Present", present);
491
492 if (!success)
493 {
494 messages::internalError(asyncResp->res);
495 return;
496 }
497
498 std::string state = "Enabled";
499 std::string health = "OK";
500
501 if (present != nullptr && !*present)
502 {
503 state = "Absent";
504 }
505
506 if (functional != nullptr && !*functional)
507 {
508 if (state == "Enabled")
509 {
510 health = "Critical";
511 }
512 }
513
514 asyncResp->res.jsonValue["Id"] = acclrtrId;
515 asyncResp->res.jsonValue["Name"] = "Processor";
516 asyncResp->res.jsonValue["Status"]["State"] = state;
517 asyncResp->res.jsonValue["Status"]["Health"] = health;
518 asyncResp->res.jsonValue["ProcessorType"] =
519 processor::ProcessorType::Accelerator;
520 });
Gunnar Millsac6a4442020-10-14 14:55:29 -0500521}
522
Jonathan Domandba0c292020-12-02 15:34:13 -0800523// OperatingConfig D-Bus Types
524using TurboProfileProperty = std::vector<std::tuple<uint32_t, size_t>>;
525using BaseSpeedPrioritySettingsProperty =
526 std::vector<std::tuple<uint32_t, std::vector<uint32_t>>>;
527// uint32_t and size_t may or may not be the same type, requiring a dedup'd
528// variant
Jonathan Domandba0c292020-12-02 15:34:13 -0800529
530/**
531 * Fill out the HighSpeedCoreIDs in a Processor resource from the given
532 * OperatingConfig D-Bus property.
533 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700534 * @param[in,out] asyncResp Async HTTP response.
Jonathan Domandba0c292020-12-02 15:34:13 -0800535 * @param[in] baseSpeedSettings Full list of base speed priority groups,
536 * to use to determine the list of high
537 * speed cores.
538 */
539inline void highSpeedCoreIdsHandler(
Ed Tanousac106bf2023-06-07 09:24:59 -0700540 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Jonathan Domandba0c292020-12-02 15:34:13 -0800541 const BaseSpeedPrioritySettingsProperty& baseSpeedSettings)
542{
543 // The D-Bus property does not indicate which bucket is the "high
544 // priority" group, so let's discern that by looking for the one with
545 // highest base frequency.
546 auto highPriorityGroup = baseSpeedSettings.cend();
547 uint32_t highestBaseSpeed = 0;
548 for (auto it = baseSpeedSettings.cbegin(); it != baseSpeedSettings.cend();
549 ++it)
550 {
551 const uint32_t baseFreq = std::get<uint32_t>(*it);
552 if (baseFreq > highestBaseSpeed)
553 {
554 highestBaseSpeed = baseFreq;
555 highPriorityGroup = it;
556 }
557 }
558
Ed Tanousac106bf2023-06-07 09:24:59 -0700559 nlohmann::json& jsonCoreIds = asyncResp->res.jsonValue["HighSpeedCoreIDs"];
Jonathan Domandba0c292020-12-02 15:34:13 -0800560 jsonCoreIds = nlohmann::json::array();
561
562 // There may not be any entries in the D-Bus property, so only populate
563 // if there was actually something there.
564 if (highPriorityGroup != baseSpeedSettings.cend())
565 {
566 jsonCoreIds = std::get<std::vector<uint32_t>>(*highPriorityGroup);
567 }
568}
569
570/**
571 * Fill out OperatingConfig related items in a Processor resource by requesting
572 * data from the given D-Bus object.
573 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700574 * @param[in,out] asyncResp Async HTTP response.
Jonathan Domandba0c292020-12-02 15:34:13 -0800575 * @param[in] cpuId CPU D-Bus name.
576 * @param[in] service D-Bus service to query.
577 * @param[in] objPath D-Bus object to query.
578 */
Patrick Williams504af5a2025-02-03 14:29:03 -0500579inline void getCpuConfigData(
580 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
581 const std::string& cpuId, const std::string& service,
582 const std::string& objPath)
Jonathan Domandba0c292020-12-02 15:34:13 -0800583{
Ed Tanous62598e32023-07-17 17:06:25 -0700584 BMCWEB_LOG_INFO("Getting CPU operating configs for {}", cpuId);
Jonathan Domandba0c292020-12-02 15:34:13 -0800585
586 // First, GetAll CurrentOperatingConfig properties on the object
Ed Tanousdeae6a72024-11-11 21:58:57 -0800587 dbus::utility::getAllProperties(
588 service, objPath,
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200589 "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig",
Ed Tanousac106bf2023-06-07 09:24:59 -0700590 [asyncResp, cpuId,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800591 service](const boost::system::error_code& ec,
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200592 const dbus::utility::DBusPropertiesMap& properties) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400593 if (ec)
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200594 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400595 BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec, ec.message());
Ed Tanousac106bf2023-06-07 09:24:59 -0700596 messages::internalError(asyncResp->res);
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200597 return;
598 }
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200599
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400600 nlohmann::json& json = asyncResp->res.jsonValue;
601
602 const sdbusplus::message::object_path* appliedConfig = nullptr;
603 const bool* baseSpeedPriorityEnabled = nullptr;
604
605 const bool success = sdbusplus::unpackPropertiesNoThrow(
606 dbus_utils::UnpackErrorPrinter(), properties, "AppliedConfig",
607 appliedConfig, "BaseSpeedPriorityEnabled",
608 baseSpeedPriorityEnabled);
609
610 if (!success)
611 {
612 messages::internalError(asyncResp->res);
613 return;
614 }
615
616 if (appliedConfig != nullptr)
617 {
618 const std::string& dbusPath = appliedConfig->str;
619 nlohmann::json::object_t operatingConfig;
620 operatingConfig["@odata.id"] = boost::urls::format(
621 "/redfish/v1/Systems/{}/Processors/{}/OperatingConfigs",
622 BMCWEB_REDFISH_SYSTEM_URI_NAME, cpuId);
623 json["OperatingConfigs"] = std::move(operatingConfig);
624
625 // Reuse the D-Bus config object name for the Redfish
626 // URI
627 size_t baseNamePos = dbusPath.rfind('/');
628 if (baseNamePos == std::string::npos ||
629 baseNamePos == (dbusPath.size() - 1))
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200630 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400631 // If the AppliedConfig was somehow not a valid path,
632 // skip adding any more properties, since everything
633 // else is tied to this applied config.
Ed Tanousac106bf2023-06-07 09:24:59 -0700634 messages::internalError(asyncResp->res);
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200635 return;
636 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400637 nlohmann::json::object_t appliedOperatingConfig;
638 appliedOperatingConfig["@odata.id"] = boost::urls::format(
639 "/redfish/v1/Systems/{}/Processors/{}/OperatingConfigs/{}",
640 BMCWEB_REDFISH_SYSTEM_URI_NAME, cpuId,
641 dbusPath.substr(baseNamePos + 1));
642 json["AppliedOperatingConfig"] =
643 std::move(appliedOperatingConfig);
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200644
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400645 // Once we found the current applied config, queue another
646 // request to read the base freq core ids out of that
647 // config.
Ed Tanousdeae6a72024-11-11 21:58:57 -0800648 dbus::utility::getProperty<BaseSpeedPrioritySettingsProperty>(
649 service, dbusPath,
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400650 "xyz.openbmc_project.Inventory.Item.Cpu."
651 "OperatingConfig",
652 "BaseSpeedPrioritySettings",
653 [asyncResp](const boost::system::error_code& ec2,
654 const BaseSpeedPrioritySettingsProperty&
655 baseSpeedList) {
656 if (ec2)
657 {
658 BMCWEB_LOG_WARNING("D-Bus Property Get error: {}",
659 ec2);
660 messages::internalError(asyncResp->res);
661 return;
662 }
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200663
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400664 highSpeedCoreIdsHandler(asyncResp, baseSpeedList);
665 });
666 }
667
668 if (baseSpeedPriorityEnabled != nullptr)
669 {
670 json["BaseSpeedPriorityState"] =
671 *baseSpeedPriorityEnabled ? "Enabled" : "Disabled";
672 }
673 });
Jonathan Domandba0c292020-12-02 15:34:13 -0800674}
675
SunnySrivastava1984cba4f442021-01-07 12:48:16 -0600676/**
677 * @brief Fill out location info of a processor by
678 * requesting data from the given D-Bus object.
679 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700680 * @param[in,out] asyncResp Async HTTP response.
SunnySrivastava1984cba4f442021-01-07 12:48:16 -0600681 * @param[in] service D-Bus service to query.
682 * @param[in] objPath D-Bus object to query.
683 */
Ed Tanousac106bf2023-06-07 09:24:59 -0700684inline void getCpuLocationCode(std::shared_ptr<bmcweb::AsyncResp> asyncResp,
SunnySrivastava1984cba4f442021-01-07 12:48:16 -0600685 const std::string& service,
686 const std::string& objPath)
687{
Ed Tanous62598e32023-07-17 17:06:25 -0700688 BMCWEB_LOG_DEBUG("Get Cpu Location Data");
Ed Tanousdeae6a72024-11-11 21:58:57 -0800689 dbus::utility::getProperty<std::string>(
690 service, objPath,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700691 "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode",
Ed Tanousac106bf2023-06-07 09:24:59 -0700692 [objPath, asyncResp{std::move(asyncResp)}](
693 const boost::system::error_code& ec, const std::string& property) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400694 if (ec)
695 {
696 BMCWEB_LOG_DEBUG("DBUS response error");
697 messages::internalError(asyncResp->res);
698 return;
699 }
SunnySrivastava1984cba4f442021-01-07 12:48:16 -0600700
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400701 asyncResp->res
702 .jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
703 property;
704 });
SunnySrivastava1984cba4f442021-01-07 12:48:16 -0600705}
706
Jonathan Domanc9514482021-02-24 09:20:51 -0800707/**
Jonathan Doman49e429c2021-03-03 13:11:44 -0800708 * Populate the unique identifier in a Processor resource by requesting data
709 * from the given D-Bus object.
710 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700711 * @param[in,out] asyncResp Async HTTP response.
Jonathan Doman49e429c2021-03-03 13:11:44 -0800712 * @param[in] service D-Bus service to query.
713 * @param[in] objPath D-Bus object to query.
714 */
Ed Tanousac106bf2023-06-07 09:24:59 -0700715inline void getCpuUniqueId(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Jonathan Doman49e429c2021-03-03 13:11:44 -0800716 const std::string& service,
717 const std::string& objectPath)
718{
Ed Tanous62598e32023-07-17 17:06:25 -0700719 BMCWEB_LOG_DEBUG("Get CPU UniqueIdentifier");
Ed Tanousdeae6a72024-11-11 21:58:57 -0800720 dbus::utility::getProperty<std::string>(
721 service, objectPath,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700722 "xyz.openbmc_project.Inventory.Decorator.UniqueIdentifier",
723 "UniqueIdentifier",
Ed Tanousac106bf2023-06-07 09:24:59 -0700724 [asyncResp](const boost::system::error_code& ec,
725 const std::string& id) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400726 if (ec)
727 {
728 BMCWEB_LOG_ERROR("Failed to read cpu unique id: {}", ec);
729 messages::internalError(asyncResp->res);
730 return;
731 }
732 asyncResp->res
733 .jsonValue["ProcessorId"]["ProtectedIdentificationNumber"] = id;
734 });
Jonathan Doman49e429c2021-03-03 13:11:44 -0800735}
736
George Liu98eafce2020-10-03 16:46:04 +0800737inline void handleProcessorSubtree(
738 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
739 const std::string& processorId,
740 const std::function<
741 void(const std::string& objectPath,
742 const dbus::utility::MapperServiceMap& serviceMap)>& callback,
743 const boost::system::error_code& ec,
744 const dbus::utility::MapperGetSubTreeResponse& subtree)
745{
746 if (ec)
747 {
748 BMCWEB_LOG_ERROR("DBUS response error: {}", ec);
749 messages::internalError(asyncResp->res);
750 return;
751 }
752 for (const auto& [objectPath, serviceMap] : subtree)
753 {
754 // Ignore any objects which don't end with our desired cpu name
755 sdbusplus::message::object_path path(objectPath);
756 if (path.filename() == processorId)
757 {
758 // Filter out objects that don't have the CPU-specific
759 // interfaces to make sure we can return 404 on non-CPUs
760 // (e.g. /redfish/../Processors/dimm0)
761 for (const auto& [serviceName, interfaceList] : serviceMap)
762 {
763 if (std::ranges::find_first_of(interfaceList,
764 processorInterfaces) !=
765 interfaceList.end())
766 {
767 // Process the first object which matches cpu name and
768 // required interfaces, and potentially ignore any other
769 // matching objects. Assume all interfaces we want to
770 // process must be on the same object path.
771
772 callback(objectPath, serviceMap);
773 return;
774 }
775 }
776 }
777 }
778 messages::resourceNotFound(asyncResp->res, "Processor", processorId);
779}
780
Jonathan Doman49e429c2021-03-03 13:11:44 -0800781/**
Jonathan Domanc9514482021-02-24 09:20:51 -0800782 * Find the D-Bus object representing the requested Processor, and call the
783 * handler with the results. If matching object is not found, add 404 error to
784 * response and don't call the handler.
785 *
George Liu98eafce2020-10-03 16:46:04 +0800786 * @param[in,out] asyncResp Async HTTP response.
Jonathan Domanc9514482021-02-24 09:20:51 -0800787 * @param[in] processorId Redfish Processor Id.
George Liu98eafce2020-10-03 16:46:04 +0800788 * @param[in] callback Callback to continue processing request upon
Jonathan Domanc9514482021-02-24 09:20:51 -0800789 * successfully finding object.
790 */
George Liu98eafce2020-10-03 16:46:04 +0800791inline void getProcessorObject(
792 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
793 const std::string& processorId,
794 std::function<void(const std::string& objectPath,
795 const dbus::utility::MapperServiceMap& serviceMap)>&&
796 callback)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500797{
Ed Tanous62598e32023-07-17 17:06:25 -0700798 BMCWEB_LOG_DEBUG("Get available system processor resources.");
Gunnar Millsac6a4442020-10-14 14:55:29 -0500799
Jonathan Domanc9514482021-02-24 09:20:51 -0800800 // GetSubTree on all interfaces which provide info about a Processor
Chris Caindfbf7de2023-04-13 16:01:04 -0500801 constexpr std::array<std::string_view, 9> interfaces = {
George Liue99073f2022-12-09 11:06:16 +0800802 "xyz.openbmc_project.Common.UUID",
803 "xyz.openbmc_project.Inventory.Decorator.Asset",
804 "xyz.openbmc_project.Inventory.Decorator.Revision",
805 "xyz.openbmc_project.Inventory.Item.Cpu",
806 "xyz.openbmc_project.Inventory.Decorator.LocationCode",
807 "xyz.openbmc_project.Inventory.Item.Accelerator",
808 "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig",
Chris Caindfbf7de2023-04-13 16:01:04 -0500809 "xyz.openbmc_project.Inventory.Decorator.UniqueIdentifier",
810 "xyz.openbmc_project.Control.Power.Throttle"};
George Liue99073f2022-12-09 11:06:16 +0800811 dbus::utility::getSubTree(
812 "/xyz/openbmc_project/inventory", 0, interfaces,
George Liu98eafce2020-10-03 16:46:04 +0800813 [asyncResp, processorId, callback{std::move(callback)}](
George Liue99073f2022-12-09 11:06:16 +0800814 const boost::system::error_code& ec,
815 const dbus::utility::MapperGetSubTreeResponse& subtree) {
George Liu98eafce2020-10-03 16:46:04 +0800816 handleProcessorSubtree(asyncResp, processorId, callback, ec,
817 subtree);
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400818 });
Gunnar Millsac6a4442020-10-14 14:55:29 -0500819}
820
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400821inline void getProcessorData(
822 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
823 const std::string& processorId, const std::string& objectPath,
824 const dbus::utility::MapperServiceMap& serviceMap)
Jonathan Domanc9514482021-02-24 09:20:51 -0800825{
George Liu98eafce2020-10-03 16:46:04 +0800826 asyncResp->res.addHeader(
827 boost::beast::http::field::link,
828 "</redfish/v1/JsonSchemas/Processor/Processor.json>; rel=describedby");
829 asyncResp->res.jsonValue["@odata.type"] = "#Processor.v1_18_0.Processor";
830 asyncResp->res.jsonValue["@odata.id"] =
831 boost::urls::format("/redfish/v1/Systems/{}/Processors/{}",
832 BMCWEB_REDFISH_SYSTEM_URI_NAME, processorId);
833
Jonathan Domanc9514482021-02-24 09:20:51 -0800834 for (const auto& [serviceName, interfaceList] : serviceMap)
835 {
836 for (const auto& interface : interfaceList)
837 {
838 if (interface == "xyz.openbmc_project.Inventory.Decorator.Asset")
839 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700840 getCpuAssetData(asyncResp, serviceName, objectPath);
Jonathan Domanc9514482021-02-24 09:20:51 -0800841 }
George Liu0fda0f12021-11-16 10:06:17 +0800842 else if (interface ==
843 "xyz.openbmc_project.Inventory.Decorator.Revision")
Jonathan Domanc9514482021-02-24 09:20:51 -0800844 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700845 getCpuRevisionData(asyncResp, serviceName, objectPath);
Jonathan Domanc9514482021-02-24 09:20:51 -0800846 }
847 else if (interface == "xyz.openbmc_project.Inventory.Item.Cpu")
848 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700849 getCpuDataByService(asyncResp, processorId, serviceName,
Jonathan Domanc9514482021-02-24 09:20:51 -0800850 objectPath);
851 }
George Liu0fda0f12021-11-16 10:06:17 +0800852 else if (interface ==
853 "xyz.openbmc_project.Inventory.Item.Accelerator")
Jonathan Domanc9514482021-02-24 09:20:51 -0800854 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700855 getAcceleratorDataByService(asyncResp, processorId, serviceName,
Jonathan Domanc9514482021-02-24 09:20:51 -0800856 objectPath);
857 }
George Liu0fda0f12021-11-16 10:06:17 +0800858 else if (
859 interface ==
860 "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig")
Jonathan Domanc9514482021-02-24 09:20:51 -0800861 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700862 getCpuConfigData(asyncResp, processorId, serviceName,
863 objectPath);
Jonathan Domanc9514482021-02-24 09:20:51 -0800864 }
George Liu0fda0f12021-11-16 10:06:17 +0800865 else if (interface ==
866 "xyz.openbmc_project.Inventory.Decorator.LocationCode")
Jonathan Domanc9514482021-02-24 09:20:51 -0800867 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700868 getCpuLocationCode(asyncResp, serviceName, objectPath);
Jonathan Domanc9514482021-02-24 09:20:51 -0800869 }
Sharad Yadav71b82f22021-05-10 15:11:39 +0530870 else if (interface == "xyz.openbmc_project.Common.UUID")
871 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700872 getProcessorUUID(asyncResp, serviceName, objectPath);
Sharad Yadav71b82f22021-05-10 15:11:39 +0530873 }
George Liu0fda0f12021-11-16 10:06:17 +0800874 else if (interface ==
875 "xyz.openbmc_project.Inventory.Decorator.UniqueIdentifier")
Jonathan Doman49e429c2021-03-03 13:11:44 -0800876 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700877 getCpuUniqueId(asyncResp, serviceName, objectPath);
Jonathan Doman49e429c2021-03-03 13:11:44 -0800878 }
Chris Caindfbf7de2023-04-13 16:01:04 -0500879 else if (interface == "xyz.openbmc_project.Control.Power.Throttle")
880 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700881 getThrottleProperties(asyncResp, serviceName, objectPath);
Chris Caindfbf7de2023-04-13 16:01:04 -0500882 }
George Liu98eafce2020-10-03 16:46:04 +0800883 else if (interface == "xyz.openbmc_project.Association.Definitions")
884 {
885 getLocationIndicatorActive(asyncResp, objectPath);
886 }
Jonathan Domanc9514482021-02-24 09:20:51 -0800887 }
888 }
889}
890
Jonathan Domandba0c292020-12-02 15:34:13 -0800891/**
892 * Request all the properties for the given D-Bus object and fill out the
893 * related entries in the Redfish OperatingConfig response.
894 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700895 * @param[in,out] asyncResp Async HTTP response.
Jonathan Domandba0c292020-12-02 15:34:13 -0800896 * @param[in] service D-Bus service name to query.
897 * @param[in] objPath D-Bus object to query.
898 */
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400899inline void getOperatingConfigData(
900 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
901 const std::string& service, const std::string& objPath)
Jonathan Domandba0c292020-12-02 15:34:13 -0800902{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800903 dbus::utility::getAllProperties(
904 service, objPath,
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200905 "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig",
Ed Tanousac106bf2023-06-07 09:24:59 -0700906 [asyncResp](const boost::system::error_code& ec,
907 const dbus::utility::DBusPropertiesMap& properties) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400908 if (ec)
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200909 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400910 BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec, ec.message());
911 messages::internalError(asyncResp->res);
912 return;
Ed Tanous002d39b2022-05-31 08:59:27 -0700913 }
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200914
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400915 const size_t* availableCoreCount = nullptr;
916 const uint32_t* baseSpeed = nullptr;
917 const uint32_t* maxJunctionTemperature = nullptr;
918 const uint32_t* maxSpeed = nullptr;
919 const uint32_t* powerLimit = nullptr;
920 const TurboProfileProperty* turboProfile = nullptr;
921 const BaseSpeedPrioritySettingsProperty* baseSpeedPrioritySettings =
922 nullptr;
923
924 const bool success = sdbusplus::unpackPropertiesNoThrow(
925 dbus_utils::UnpackErrorPrinter(), properties,
926 "AvailableCoreCount", availableCoreCount, "BaseSpeed",
927 baseSpeed, "MaxJunctionTemperature", maxJunctionTemperature,
928 "MaxSpeed", maxSpeed, "PowerLimit", powerLimit, "TurboProfile",
929 turboProfile, "BaseSpeedPrioritySettings",
930 baseSpeedPrioritySettings);
931
932 if (!success)
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200933 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400934 messages::internalError(asyncResp->res);
935 return;
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200936 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400937
938 nlohmann::json& json = asyncResp->res.jsonValue;
939
940 if (availableCoreCount != nullptr)
941 {
942 json["TotalAvailableCoreCount"] = *availableCoreCount;
943 }
944
945 if (baseSpeed != nullptr)
946 {
947 json["BaseSpeedMHz"] = *baseSpeed;
948 }
949
950 if (maxJunctionTemperature != nullptr)
951 {
952 json["MaxJunctionTemperatureCelsius"] = *maxJunctionTemperature;
953 }
954
955 if (maxSpeed != nullptr)
956 {
957 json["MaxSpeedMHz"] = *maxSpeed;
958 }
959
960 if (powerLimit != nullptr)
961 {
962 json["TDPWatts"] = *powerLimit;
963 }
964
965 if (turboProfile != nullptr)
966 {
967 nlohmann::json& turboArray = json["TurboProfile"];
968 turboArray = nlohmann::json::array();
969 for (const auto& [turboSpeed, coreCount] : *turboProfile)
970 {
971 nlohmann::json::object_t turbo;
972 turbo["ActiveCoreCount"] = coreCount;
973 turbo["MaxSpeedMHz"] = turboSpeed;
974 turboArray.emplace_back(std::move(turbo));
975 }
976 }
977
978 if (baseSpeedPrioritySettings != nullptr)
979 {
980 nlohmann::json& baseSpeedArray =
981 json["BaseSpeedPrioritySettings"];
982 baseSpeedArray = nlohmann::json::array();
983 for (const auto& [baseSpeedMhz, coreList] :
984 *baseSpeedPrioritySettings)
985 {
986 nlohmann::json::object_t speed;
987 speed["CoreCount"] = coreList.size();
988 speed["CoreIDs"] = coreList;
989 speed["BaseSpeedMHz"] = baseSpeedMhz;
990 baseSpeedArray.emplace_back(std::move(speed));
991 }
992 }
993 });
Jonathan Domandba0c292020-12-02 15:34:13 -0800994}
995
Jonathan Doman3cde86f2020-12-02 14:50:45 -0800996/**
Jonathan Doman3cde86f2020-12-02 14:50:45 -0800997 * Handle the PATCH operation of the AppliedOperatingConfig property. Do basic
998 * validation of the input data, and then set the D-Bus property.
999 *
1000 * @param[in,out] resp Async HTTP response.
1001 * @param[in] processorId Processor's Id.
1002 * @param[in] appliedConfigUri New property value to apply.
1003 * @param[in] cpuObjectPath Path of CPU object to modify.
1004 * @param[in] serviceMap Service map for CPU object.
1005 */
1006inline void patchAppliedOperatingConfig(
1007 const std::shared_ptr<bmcweb::AsyncResp>& resp,
1008 const std::string& processorId, const std::string& appliedConfigUri,
Shantappa Teekappanavar5df6eda2022-01-18 12:29:28 -06001009 const std::string& cpuObjectPath,
1010 const dbus::utility::MapperServiceMap& serviceMap)
Jonathan Doman3cde86f2020-12-02 14:50:45 -08001011{
1012 // Check that the property even exists by checking for the interface
1013 const std::string* controlService = nullptr;
1014 for (const auto& [serviceName, interfaceList] : serviceMap)
1015 {
Ed Tanous3544d2a2023-08-06 18:12:20 -07001016 if (std::ranges::find(interfaceList,
1017 "xyz.openbmc_project.Control.Processor."
1018 "CurrentOperatingConfig") != interfaceList.end())
Jonathan Doman3cde86f2020-12-02 14:50:45 -08001019 {
1020 controlService = &serviceName;
1021 break;
1022 }
1023 }
1024
1025 if (controlService == nullptr)
1026 {
1027 messages::internalError(resp->res);
1028 return;
1029 }
1030
1031 // Check that the config URI is a child of the cpu URI being patched.
Ed Tanous253f11b2024-05-16 09:38:31 -07001032 std::string expectedPrefix(std::format("/redfish/v1/Systems/{}/Processors/",
1033 BMCWEB_REDFISH_SYSTEM_URI_NAME));
Jonathan Doman3cde86f2020-12-02 14:50:45 -08001034 expectedPrefix += processorId;
1035 expectedPrefix += "/OperatingConfigs/";
Ed Tanous11ba3972022-07-11 09:50:41 -07001036 if (!appliedConfigUri.starts_with(expectedPrefix) ||
Jonathan Doman3cde86f2020-12-02 14:50:45 -08001037 expectedPrefix.size() == appliedConfigUri.size())
1038 {
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001039 messages::propertyValueIncorrect(resp->res, "AppliedOperatingConfig",
1040 appliedConfigUri);
Jonathan Doman3cde86f2020-12-02 14:50:45 -08001041 return;
1042 }
1043
1044 // Generate the D-Bus path of the OperatingConfig object, by assuming it's a
1045 // direct child of the CPU object.
1046 // Strip the expectedPrefix from the config URI to get the "filename", and
1047 // append to the CPU's path.
1048 std::string configBaseName = appliedConfigUri.substr(expectedPrefix.size());
1049 sdbusplus::message::object_path configPath(cpuObjectPath);
1050 configPath /= configBaseName;
1051
Ed Tanous62598e32023-07-17 17:06:25 -07001052 BMCWEB_LOG_INFO("Setting config to {}", configPath.str);
Jonathan Doman3cde86f2020-12-02 14:50:45 -08001053
1054 // Set the property, with handler to check error responses
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001055 setDbusProperty(
Ginu Georgee93abac2024-06-14 17:35:27 +05301056 resp, "AppliedOperatingConfig", *controlService, cpuObjectPath,
George Liu9ae226f2023-06-21 17:56:46 +08001057 "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig",
Ginu Georgee93abac2024-06-14 17:35:27 +05301058 "AppliedConfig", configPath);
Jonathan Doman3cde86f2020-12-02 14:50:45 -08001059}
1060
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001061inline void handleProcessorHead(
1062 crow::App& app, const crow::Request& req,
1063 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1064 const std::string& /* systemName */, const std::string& /* processorId */)
Nikhil Namjoshi71a24ca2022-11-11 01:52:32 +00001065{
Ed Tanousac106bf2023-06-07 09:24:59 -07001066 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Nikhil Namjoshi71a24ca2022-11-11 01:52:32 +00001067 {
1068 return;
1069 }
Ed Tanousac106bf2023-06-07 09:24:59 -07001070 asyncResp->res.addHeader(
Nikhil Namjoshi71a24ca2022-11-11 01:52:32 +00001071 boost::beast::http::field::link,
1072 "</redfish/v1/JsonSchemas/Processor/Processor.json>; rel=describedby");
1073}
1074
1075inline void handleProcessorCollectionHead(
1076 crow::App& app, const crow::Request& req,
Ed Tanousac106bf2023-06-07 09:24:59 -07001077 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Nikhil Namjoshi71a24ca2022-11-11 01:52:32 +00001078 const std::string& /* systemName */)
1079{
Ed Tanousac106bf2023-06-07 09:24:59 -07001080 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Nikhil Namjoshi71a24ca2022-11-11 01:52:32 +00001081 {
1082 return;
1083 }
Ed Tanousac106bf2023-06-07 09:24:59 -07001084 asyncResp->res.addHeader(
Nikhil Namjoshi71a24ca2022-11-11 01:52:32 +00001085 boost::beast::http::field::link,
1086 "</redfish/v1/JsonSchemas/ProcessorCollection/ProcessorCollection.json>; rel=describedby");
1087}
1088
George Liu98eafce2020-10-03 16:46:04 +08001089inline void handleProcessorGet(
1090 App& app, const crow::Request& req,
1091 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1092 const std::string& systemName, const std::string& processorId)
1093{
1094 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1095 {
1096 return;
1097 }
1098 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1099 {
1100 // Option currently returns no systems. TBD
1101 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1102 systemName);
1103 return;
1104 }
1105 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1106 {
1107 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1108 systemName);
1109 return;
1110 }
1111
1112 getProcessorObject(
1113 asyncResp, processorId,
1114 std::bind_front(getProcessorData, asyncResp, processorId));
1115}
1116
1117inline void doPatchProcessor(
1118 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1119 const std::string& processorId,
1120 const std::optional<std::string>& appliedConfigUri,
1121 std::optional<bool> locationIndicatorActive, const std::string& objectPath,
1122 const dbus::utility::MapperServiceMap& serviceMap)
1123{
1124 if (appliedConfigUri)
1125 {
1126 patchAppliedOperatingConfig(asyncResp, processorId, *appliedConfigUri,
1127 objectPath, serviceMap);
1128 }
1129
1130 if (locationIndicatorActive)
1131 {
1132 // Utility function handles reporting errors
1133 setLocationIndicatorActive(asyncResp, objectPath,
1134 *locationIndicatorActive);
1135 }
1136}
1137
1138inline void handleProcessorPatch(
1139 App& app, const crow::Request& req,
1140 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1141 const std::string& systemName, const std::string& processorId)
1142{
1143 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1144 {
1145 return;
1146 }
1147 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1148 {
1149 // Option currently returns no systems. TBD
1150 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1151 systemName);
1152 return;
1153 }
1154 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1155 {
1156 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1157 systemName);
1158 return;
1159 }
1160
1161 std::optional<std::string> appliedConfigUri;
1162 std::optional<bool> locationIndicatorActive;
1163 if (!json_util::readJsonPatch(
1164 req, asyncResp->res, //
1165 "AppliedOperatingConfig/@odata.id", appliedConfigUri, //
1166 "LocationIndicatorActive", locationIndicatorActive //
1167 ))
1168 {
1169 return;
1170 }
1171
1172 // Check for 404 and find matching D-Bus object, then run
1173 // property patch handlers if that all succeeds.
1174 getProcessorObject(
1175 asyncResp, processorId,
1176 std::bind_front(doPatchProcessor, asyncResp, processorId,
1177 appliedConfigUri, locationIndicatorActive));
1178}
1179
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001180inline void requestRoutesOperatingConfigCollection(App& app)
Jonathan Domandba0c292020-12-02 15:34:13 -08001181{
Ed Tanous7f3e84a2022-12-28 16:22:54 -08001182 BMCWEB_ROUTE(app,
1183 "/redfish/v1/Systems/<str>/Processors/<str>/OperatingConfigs/")
Ed Tanoused398212021-06-09 17:05:54 -07001184 .privileges(redfish::privileges::getOperatingConfigCollection)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001185 .methods(
1186 boost::beast::http::verb::
1187 get)([&app](const crow::Request& req,
1188 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1189 const std::string& systemName,
1190 const std::string& cpuName) {
1191 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous45ca1b82022-03-25 13:07:27 -07001192 {
1193 return;
1194 }
Jonathan Domandba0c292020-12-02 15:34:13 -08001195
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001196 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous002d39b2022-05-31 08:59:27 -07001197 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001198 // Option currently returns no systems. TBD
1199 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1200 systemName);
Ed Tanous002d39b2022-05-31 08:59:27 -07001201 return;
1202 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001203
1204 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1205 {
1206 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1207 systemName);
1208 return;
1209 }
1210 asyncResp->res.jsonValue["@odata.type"] =
1211 "#OperatingConfigCollection.OperatingConfigCollection";
1212 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
1213 "/redfish/v1/Systems/{}/Processors/{}/OperatingConfigs",
1214 BMCWEB_REDFISH_SYSTEM_URI_NAME, cpuName);
1215 asyncResp->res.jsonValue["Name"] = "Operating Config Collection";
1216
1217 // First find the matching CPU object so we know how to
1218 // constrain our search for related Config objects.
1219 const std::array<std::string_view, 1> interfaces = {
1220 "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig"};
1221 dbus::utility::getSubTreePaths(
1222 "/xyz/openbmc_project/inventory", 0, interfaces,
1223 [asyncResp,
1224 cpuName](const boost::system::error_code& ec,
1225 const dbus::utility::MapperGetSubTreePathsResponse&
1226 objects) {
1227 if (ec)
1228 {
1229 BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec,
1230 ec.message());
1231 messages::internalError(asyncResp->res);
1232 return;
1233 }
1234
1235 for (const std::string& object : objects)
1236 {
1237 if (!object.ends_with(cpuName))
1238 {
1239 continue;
1240 }
1241
1242 // Not expected that there will be multiple matching
1243 // CPU objects, but if there are just use the first
1244 // one.
1245
1246 // Use the common search routine to construct the
1247 // Collection of all Config objects under this CPU.
1248 constexpr std::array<std::string_view, 1> interface{
1249 "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig"};
1250 collection_util::getCollectionMembers(
1251 asyncResp,
1252 boost::urls::format(
1253 "/redfish/v1/Systems/{}/Processors/{}/OperatingConfigs",
1254 BMCWEB_REDFISH_SYSTEM_URI_NAME, cpuName),
1255 interface, object);
1256 return;
1257 }
1258 });
George Liu0fda0f12021-11-16 10:06:17 +08001259 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001260}
1261
1262inline void requestRoutesOperatingConfig(App& app)
1263{
1264 BMCWEB_ROUTE(
1265 app,
Ed Tanous7f3e84a2022-12-28 16:22:54 -08001266 "/redfish/v1/Systems/<str>/Processors/<str>/OperatingConfigs/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001267 .privileges(redfish::privileges::getOperatingConfig)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001268 .methods(
1269 boost::beast::http::verb::
1270 get)([&app](const crow::Request& req,
1271 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1272 const std::string& systemName,
1273 const std::string& cpuName,
1274 const std::string& configName) {
1275 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous45ca1b82022-03-25 13:07:27 -07001276 {
1277 return;
1278 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001279 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous002d39b2022-05-31 08:59:27 -07001280 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001281 // Option currently returns no systems. TBD
1282 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1283 systemName);
Ed Tanous002d39b2022-05-31 08:59:27 -07001284 return;
1285 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001286
1287 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1288 {
1289 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1290 systemName);
1291 return;
1292 }
1293 // Ask for all objects implementing OperatingConfig so we can search
1294 // for one with a matching name
1295 constexpr std::array<std::string_view, 1> interfaces = {
1296 "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig"};
1297 dbus::utility::getSubTree(
1298 "/xyz/openbmc_project/inventory", 0, interfaces,
1299 [asyncResp, cpuName, configName](
1300 const boost::system::error_code& ec,
1301 const dbus::utility::MapperGetSubTreeResponse& subtree) {
1302 if (ec)
1303 {
1304 BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec,
1305 ec.message());
1306 messages::internalError(asyncResp->res);
1307 return;
1308 }
1309 const std::string expectedEnding =
1310 cpuName + '/' + configName;
1311 for (const auto& [objectPath, serviceMap] : subtree)
1312 {
1313 // Ignore any configs without matching cpuX/configY
1314 if (!objectPath.ends_with(expectedEnding) ||
1315 serviceMap.empty())
1316 {
1317 continue;
1318 }
1319
1320 nlohmann::json& json = asyncResp->res.jsonValue;
1321 json["@odata.type"] =
1322 "#OperatingConfig.v1_0_0.OperatingConfig";
1323 json["@odata.id"] = boost::urls::format(
1324 "/redfish/v1/Systems/{}/Processors/{}/OperatingConfigs/{}",
1325 BMCWEB_REDFISH_SYSTEM_URI_NAME, cpuName,
1326 configName);
1327 json["Name"] = "Processor Profile";
1328 json["Id"] = configName;
1329
1330 // Just use the first implementation of the object - not
1331 // expected that there would be multiple matching
1332 // services
1333 getOperatingConfigData(
1334 asyncResp, serviceMap.begin()->first, objectPath);
1335 return;
1336 }
1337 messages::resourceNotFound(asyncResp->res,
1338 "OperatingConfig", configName);
1339 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001340 });
1341}
Jonathan Domandba0c292020-12-02 15:34:13 -08001342
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001343inline void requestRoutesProcessorCollection(App& app)
Gunnar Millsac6a4442020-10-14 14:55:29 -05001344{
Gunnar Millsac6a4442020-10-14 14:55:29 -05001345 /**
1346 * Functions triggers appropriate requests on DBus
1347 */
Ed Tanous22d268c2022-05-19 09:39:07 -07001348 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/")
Nikhil Namjoshi71a24ca2022-11-11 01:52:32 +00001349 .privileges(redfish::privileges::headProcessorCollection)
1350 .methods(boost::beast::http::verb::head)(
1351 std::bind_front(handleProcessorCollectionHead, std::ref(app)));
1352
1353 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/")
Ed Tanoused398212021-06-09 17:05:54 -07001354 .privileges(redfish::privileges::getProcessorCollection)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001355 .methods(
1356 boost::beast::http::verb::
1357 get)([&app](const crow::Request& req,
1358 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1359 const std::string& systemName) {
1360 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1361 {
1362 return;
1363 }
1364 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1365 {
1366 // Option currently returns no systems. TBD
1367 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1368 systemName);
1369 return;
1370 }
Ed Tanous7f3e84a2022-12-28 16:22:54 -08001371
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001372 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1373 {
1374 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1375 systemName);
1376 return;
1377 }
Ed Tanous22d268c2022-05-19 09:39:07 -07001378
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001379 asyncResp->res.addHeader(
1380 boost::beast::http::field::link,
1381 "</redfish/v1/JsonSchemas/ProcessorCollection/ProcessorCollection.json>; rel=describedby");
Nikhil Namjoshi71a24ca2022-11-11 01:52:32 +00001382
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001383 asyncResp->res.jsonValue["@odata.type"] =
1384 "#ProcessorCollection.ProcessorCollection";
1385 asyncResp->res.jsonValue["Name"] = "Processor Collection";
Gunnar Millsac6a4442020-10-14 14:55:29 -05001386
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001387 asyncResp->res.jsonValue["@odata.id"] =
1388 std::format("/redfish/v1/Systems/{}/Processors",
1389 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Gunnar Millsac6a4442020-10-14 14:55:29 -05001390
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001391 collection_util::getCollectionMembers(
1392 asyncResp,
1393 boost::urls::format("/redfish/v1/Systems/{}/Processors",
1394 BMCWEB_REDFISH_SYSTEM_URI_NAME),
1395 processorInterfaces, "/xyz/openbmc_project/inventory");
1396 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001397}
Gunnar Millsac6a4442020-10-14 14:55:29 -05001398
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001399inline void requestRoutesProcessor(App& app)
Gunnar Millsac6a4442020-10-14 14:55:29 -05001400{
Gunnar Millsac6a4442020-10-14 14:55:29 -05001401 /**
1402 * Functions triggers appropriate requests on DBus
1403 */
Gunnar Millsac6a4442020-10-14 14:55:29 -05001404
Ed Tanous22d268c2022-05-19 09:39:07 -07001405 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/<str>/")
Nikhil Namjoshi71a24ca2022-11-11 01:52:32 +00001406 .privileges(redfish::privileges::headProcessor)
1407 .methods(boost::beast::http::verb::head)(
1408 std::bind_front(handleProcessorHead, std::ref(app)));
1409
1410 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001411 .privileges(redfish::privileges::getProcessor)
George Liu98eafce2020-10-03 16:46:04 +08001412 .methods(boost::beast::http::verb::get)(
1413 std::bind_front(handleProcessorGet, std::ref(app)));
Jonathan Doman3cde86f2020-12-02 14:50:45 -08001414
Ed Tanous22d268c2022-05-19 09:39:07 -07001415 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001416 .privileges(redfish::privileges::patchProcessor)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001417 .methods(boost::beast::http::verb::patch)(
George Liu98eafce2020-10-03 16:46:04 +08001418 std::bind_front(handleProcessorPatch, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001419}
Gunnar Millsac6a4442020-10-14 14:55:29 -05001420
1421} // namespace redfish