blob: 82781d3bd93cf5b6a5f6d6f8dd300ef9cf6a0be6 [file] [log] [blame]
Gunnar Millsac6a4442020-10-14 14:55:29 -05001/*
Ed Tanous6be832e2024-09-10 11:44:48 -07002Copyright (c) 2018 Intel Corporation
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
Gunnar Millsac6a4442020-10-14 14:55:29 -050015*/
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 Tanous539d8c62024-06-19 14:38:27 -070023#include "generated/enums/resource.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080024#include "query.hpp"
25#include "registries/privilege_registry.hpp"
26#include "utils/collection.hpp"
27#include "utils/dbus_utils.hpp"
28#include "utils/json_utils.hpp"
Gunnar Millsac6a4442020-10-14 14:55:29 -050029
30#include <boost/container/flat_map.hpp>
George Liue99073f2022-12-09 11:06:16 +080031#include <boost/system/error_code.hpp>
Ed Tanousef4c65b2023-04-24 15:28:50 -070032#include <boost/url/format.hpp>
Jonathan Doman1e1e5982021-06-11 09:36:17 -070033#include <sdbusplus/asio/property.hpp>
Jonathan Domandba0c292020-12-02 15:34:13 -080034#include <sdbusplus/message/native_types.hpp>
Krzysztof Grobelny351053f2022-07-28 15:44:22 +020035#include <sdbusplus/unpack_properties.hpp>
Jonathan Domandba0c292020-12-02 15:34:13 -080036#include <sdbusplus/utility/dedup_variant.hpp>
Gunnar Millsac6a4442020-10-14 14:55:29 -050037
George Liu7a1dbc42022-12-07 16:03:22 +080038#include <array>
Michael Shenb9d679d2023-02-13 02:29:04 +000039#include <limits>
Ed Tanous3544d2a2023-08-06 18:12:20 -070040#include <ranges>
Ed Tanous3c569212024-03-06 14:46:18 -080041#include <string>
George Liu7a1dbc42022-12-07 16:03:22 +080042#include <string_view>
43
Gunnar Millsac6a4442020-10-14 14:55:29 -050044namespace redfish
45{
46
Jonathan Domanc9514482021-02-24 09:20:51 -080047// Interfaces which imply a D-Bus object represents a Processor
George Liu7a1dbc42022-12-07 16:03:22 +080048constexpr std::array<std::string_view, 2> processorInterfaces = {
Jonathan Domanc9514482021-02-24 09:20:51 -080049 "xyz.openbmc_project.Inventory.Item.Cpu",
50 "xyz.openbmc_project.Inventory.Item.Accelerator"};
Jonathan Doman2bab9832020-12-02 15:27:40 -080051
Sharad Yadav71b82f22021-05-10 15:11:39 +053052/**
53 * @brief Fill out uuid info of a processor by
54 * requesting data from the given D-Bus object.
55 *
Ed Tanousac106bf2023-06-07 09:24:59 -070056 * @param[in,out] asyncResp Async HTTP response.
Sharad Yadav71b82f22021-05-10 15:11:39 +053057 * @param[in] service D-Bus service to query.
58 * @param[in] objPath D-Bus object to query.
59 */
Ed Tanousac106bf2023-06-07 09:24:59 -070060inline void getProcessorUUID(std::shared_ptr<bmcweb::AsyncResp> asyncResp,
Sharad Yadav71b82f22021-05-10 15:11:39 +053061 const std::string& service,
62 const std::string& objPath)
63{
Ed Tanous62598e32023-07-17 17:06:25 -070064 BMCWEB_LOG_DEBUG("Get Processor UUID");
Jonathan Doman1e1e5982021-06-11 09:36:17 -070065 sdbusplus::asio::getProperty<std::string>(
66 *crow::connections::systemBus, service, objPath,
67 "xyz.openbmc_project.Common.UUID", "UUID",
Ed Tanousac106bf2023-06-07 09:24:59 -070068 [objPath, asyncResp{std::move(asyncResp)}](
69 const boost::system::error_code& ec, const std::string& property) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -040070 if (ec)
71 {
72 BMCWEB_LOG_DEBUG("DBUS response error");
73 messages::internalError(asyncResp->res);
74 return;
75 }
76 asyncResp->res.jsonValue["UUID"] = property;
77 });
Sharad Yadav71b82f22021-05-10 15:11:39 +053078}
79
Ed Tanous711ac7a2021-12-20 09:34:41 -080080inline void getCpuDataByInterface(
Ed Tanousac106bf2023-06-07 09:24:59 -070081 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Michael Shen80f79a42023-08-24 13:41:53 +000082 const dbus::utility::DBusInterfacesMap& cpuInterfacesProperties)
Gunnar Millsac6a4442020-10-14 14:55:29 -050083{
Ed Tanous62598e32023-07-17 17:06:25 -070084 BMCWEB_LOG_DEBUG("Get CPU resources by interface.");
Gunnar Millsac6a4442020-10-14 14:55:29 -050085
Chicago Duana1649ec2021-03-30 16:54:58 +080086 // Set the default value of state
Ed Tanous539d8c62024-06-19 14:38:27 -070087 asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled;
88 asyncResp->res.jsonValue["Status"]["Health"] = resource::Health::OK;
Gunnar Millsac6a4442020-10-14 14:55:29 -050089
90 for (const auto& interface : cpuInterfacesProperties)
91 {
92 for (const auto& property : interface.second)
93 {
Chicago Duana1649ec2021-03-30 16:54:58 +080094 if (property.first == "Present")
Gunnar Millsac6a4442020-10-14 14:55:29 -050095 {
Chicago Duana1649ec2021-03-30 16:54:58 +080096 const bool* cpuPresent = std::get_if<bool>(&property.second);
97 if (cpuPresent == nullptr)
Gunnar Millsac6a4442020-10-14 14:55:29 -050098 {
99 // Important property not in desired type
Ed Tanousac106bf2023-06-07 09:24:59 -0700100 messages::internalError(asyncResp->res);
Gunnar Millsac6a4442020-10-14 14:55:29 -0500101 return;
102 }
Ed Tanouse05aec52022-01-25 10:28:56 -0800103 if (!*cpuPresent)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500104 {
Chicago Duana1649ec2021-03-30 16:54:58 +0800105 // Slot is not populated
Ed Tanous539d8c62024-06-19 14:38:27 -0700106 asyncResp->res.jsonValue["Status"]["State"] =
107 resource::State::Absent;
Chicago Duana1649ec2021-03-30 16:54:58 +0800108 }
109 }
110 else if (property.first == "Functional")
111 {
112 const bool* cpuFunctional = std::get_if<bool>(&property.second);
113 if (cpuFunctional == nullptr)
114 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700115 messages::internalError(asyncResp->res);
Gunnar Millsac6a4442020-10-14 14:55:29 -0500116 return;
117 }
Ed Tanouse05aec52022-01-25 10:28:56 -0800118 if (!*cpuFunctional)
Chicago Duana1649ec2021-03-30 16:54:58 +0800119 {
Ed Tanous539d8c62024-06-19 14:38:27 -0700120 asyncResp->res.jsonValue["Status"]["Health"] =
121 resource::Health::Critical;
Chicago Duana1649ec2021-03-30 16:54:58 +0800122 }
123 }
124 else if (property.first == "CoreCount")
125 {
126 const uint16_t* coresCount =
127 std::get_if<uint16_t>(&property.second);
128 if (coresCount == nullptr)
129 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700130 messages::internalError(asyncResp->res);
Chicago Duana1649ec2021-03-30 16:54:58 +0800131 return;
132 }
Ed Tanousac106bf2023-06-07 09:24:59 -0700133 asyncResp->res.jsonValue["TotalCores"] = *coresCount;
Gunnar Millsac6a4442020-10-14 14:55:29 -0500134 }
Jonathan Domandc3fa662020-10-26 23:10:24 -0700135 else if (property.first == "MaxSpeedInMhz")
136 {
137 const uint32_t* value = std::get_if<uint32_t>(&property.second);
138 if (value != nullptr)
139 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700140 asyncResp->res.jsonValue["MaxSpeedMHz"] = *value;
Jonathan Domandc3fa662020-10-26 23:10:24 -0700141 }
142 }
Gunnar Millsac6a4442020-10-14 14:55:29 -0500143 else if (property.first == "Socket")
144 {
145 const std::string* value =
146 std::get_if<std::string>(&property.second);
147 if (value != nullptr)
148 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700149 asyncResp->res.jsonValue["Socket"] = *value;
Gunnar Millsac6a4442020-10-14 14:55:29 -0500150 }
151 }
152 else if (property.first == "ThreadCount")
153 {
Jonathan Domandc3fa662020-10-26 23:10:24 -0700154 const uint16_t* value = std::get_if<uint16_t>(&property.second);
Gunnar Millsac6a4442020-10-14 14:55:29 -0500155 if (value != nullptr)
156 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700157 asyncResp->res.jsonValue["TotalThreads"] = *value;
Gunnar Millsac6a4442020-10-14 14:55:29 -0500158 }
159 }
Brandon Kim1930fbd2021-09-14 17:52:51 -0700160 else if (property.first == "EffectiveFamily")
Gunnar Millsac6a4442020-10-14 14:55:29 -0500161 {
Brandon Kim1930fbd2021-09-14 17:52:51 -0700162 const uint16_t* value = std::get_if<uint16_t>(&property.second);
Brad Bishop6169de22022-09-14 13:08:32 -0400163 if (value != nullptr && *value != 2)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500164 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700165 asyncResp->res.jsonValue["ProcessorId"]["EffectiveFamily"] =
Ed Tanous866e4862022-02-17 11:40:25 -0800166 "0x" + intToHexString(*value, 4);
Gunnar Millsac6a4442020-10-14 14:55:29 -0500167 }
168 }
Brandon Kim1930fbd2021-09-14 17:52:51 -0700169 else if (property.first == "EffectiveModel")
170 {
171 const uint16_t* value = std::get_if<uint16_t>(&property.second);
172 if (value == nullptr)
173 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700174 messages::internalError(asyncResp->res);
Brandon Kim1930fbd2021-09-14 17:52:51 -0700175 return;
176 }
Brad Bishop6169de22022-09-14 13:08:32 -0400177 if (*value != 0)
178 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700179 asyncResp->res.jsonValue["ProcessorId"]["EffectiveModel"] =
Brad Bishop6169de22022-09-14 13:08:32 -0400180 "0x" + intToHexString(*value, 4);
181 }
Brandon Kim1930fbd2021-09-14 17:52:51 -0700182 }
Gunnar Millsac6a4442020-10-14 14:55:29 -0500183 else if (property.first == "Id")
184 {
185 const uint64_t* value = std::get_if<uint64_t>(&property.second);
186 if (value != nullptr && *value != 0)
187 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700188 asyncResp->res
Gunnar Millsac6a4442020-10-14 14:55:29 -0500189 .jsonValue["ProcessorId"]["IdentificationRegisters"] =
Ed Tanous866e4862022-02-17 11:40:25 -0800190 "0x" + intToHexString(*value, 16);
Gunnar Millsac6a4442020-10-14 14:55:29 -0500191 }
192 }
Brandon Kim1930fbd2021-09-14 17:52:51 -0700193 else if (property.first == "Microcode")
194 {
195 const uint32_t* value = std::get_if<uint32_t>(&property.second);
196 if (value == nullptr)
197 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700198 messages::internalError(asyncResp->res);
Brandon Kim1930fbd2021-09-14 17:52:51 -0700199 return;
200 }
Brad Bishop6169de22022-09-14 13:08:32 -0400201 if (*value != 0)
202 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700203 asyncResp->res.jsonValue["ProcessorId"]["MicrocodeInfo"] =
Brad Bishop6169de22022-09-14 13:08:32 -0400204 "0x" + intToHexString(*value, 8);
205 }
Brandon Kim1930fbd2021-09-14 17:52:51 -0700206 }
207 else if (property.first == "Step")
208 {
209 const uint16_t* value = std::get_if<uint16_t>(&property.second);
210 if (value == nullptr)
211 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700212 messages::internalError(asyncResp->res);
Brandon Kim1930fbd2021-09-14 17:52:51 -0700213 return;
214 }
Michael Shenb9d679d2023-02-13 02:29:04 +0000215 if (*value != std::numeric_limits<uint16_t>::max())
Brad Bishop6169de22022-09-14 13:08:32 -0400216 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700217 asyncResp->res.jsonValue["ProcessorId"]["Step"] =
Brad Bishop6169de22022-09-14 13:08:32 -0400218 "0x" + intToHexString(*value, 4);
219 }
Brandon Kim1930fbd2021-09-14 17:52:51 -0700220 }
Gunnar Millsac6a4442020-10-14 14:55:29 -0500221 }
222 }
Gunnar Millsac6a4442020-10-14 14:55:29 -0500223}
224
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400225inline void getCpuDataByService(
226 std::shared_ptr<bmcweb::AsyncResp> asyncResp, const std::string& cpuId,
227 const std::string& service, const std::string& objPath)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500228{
Ed Tanous62598e32023-07-17 17:06:25 -0700229 BMCWEB_LOG_DEBUG("Get available system cpu resources by service.");
Gunnar Millsac6a4442020-10-14 14:55:29 -0500230
George Liu5eb468d2023-06-20 17:03:24 +0800231 sdbusplus::message::object_path path("/xyz/openbmc_project/inventory");
232 dbus::utility::getManagedObjects(
233 service, path,
Ed Tanousac106bf2023-06-07 09:24:59 -0700234 [cpuId, service, objPath, asyncResp{std::move(asyncResp)}](
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800235 const boost::system::error_code& ec,
Gunnar Millsac6a4442020-10-14 14:55:29 -0500236 const dbus::utility::ManagedObjectType& dbusData) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400237 if (ec)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500238 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400239 BMCWEB_LOG_DEBUG("DBUS response error");
240 messages::internalError(asyncResp->res);
241 return;
Ed Tanous002d39b2022-05-31 08:59:27 -0700242 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400243 asyncResp->res.jsonValue["Id"] = cpuId;
244 asyncResp->res.jsonValue["Name"] = "Processor";
245 asyncResp->res.jsonValue["ProcessorType"] =
246 processor::ProcessorType::CPU;
247
248 bool slotPresent = false;
249 std::string corePath = objPath + "/core";
250 size_t totalCores = 0;
251 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 }
257 else if (object.first.str.starts_with(corePath))
258 {
259 for (const auto& interface : object.second)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500260 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400261 if (interface.first ==
262 "xyz.openbmc_project.Inventory.Item")
Gunnar Millsac6a4442020-10-14 14:55:29 -0500263 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400264 for (const auto& property : interface.second)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500265 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400266 if (property.first == "Present")
Gunnar Millsac6a4442020-10-14 14:55:29 -0500267 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400268 const bool* present =
269 std::get_if<bool>(&property.second);
270 if (present != nullptr)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500271 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400272 if (*present)
273 {
274 slotPresent = true;
275 totalCores++;
276 }
Gunnar Millsac6a4442020-10-14 14:55:29 -0500277 }
278 }
279 }
280 }
281 }
282 }
283 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400284 // In getCpuDataByInterface(), state and health are set
285 // based on the present and functional status. If core
286 // count is zero, then it has a higher precedence.
287 if (slotPresent)
288 {
289 asyncResp->res.jsonValue["TotalCores"] = totalCores;
290 }
291 return;
292 });
Gunnar Millsac6a4442020-10-14 14:55:29 -0500293}
294
Chris Caindfbf7de2023-04-13 16:01:04 -0500295/**
296 * @brief Translates throttle cause DBUS property to redfish.
297 *
298 * @param[in] dbusSource The throttle cause from DBUS
299 *
300 * @return Returns as a string, the throttle cause in Redfish terms. If
301 * translation cannot be done, returns "Unknown" throttle reason.
302 */
303inline processor::ThrottleCause
304 dbusToRfThrottleCause(const std::string& dbusSource)
305{
306 if (dbusSource ==
307 "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.ClockLimit")
308 {
309 return processor::ThrottleCause::ClockLimit;
310 }
311 if (dbusSource ==
312 "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.ManagementDetectedFault")
313 {
314 return processor::ThrottleCause::ManagementDetectedFault;
315 }
316 if (dbusSource ==
317 "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.PowerLimit")
318 {
319 return processor::ThrottleCause::PowerLimit;
320 }
321 if (dbusSource ==
322 "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.ThermalLimit")
323 {
324 return processor::ThrottleCause::ThermalLimit;
325 }
326 if (dbusSource ==
327 "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.Unknown")
328 {
329 return processor::ThrottleCause::Unknown;
330 }
331 return processor::ThrottleCause::Invalid;
332}
333
334inline void
Ed Tanousac106bf2023-06-07 09:24:59 -0700335 readThrottleProperties(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Chris Caindfbf7de2023-04-13 16:01:04 -0500336 const boost::system::error_code& ec,
337 const dbus::utility::DBusPropertiesMap& properties)
338{
339 if (ec)
340 {
Ed Tanous62598e32023-07-17 17:06:25 -0700341 BMCWEB_LOG_ERROR("Processor Throttle getAllProperties error {}", ec);
Ed Tanousac106bf2023-06-07 09:24:59 -0700342 messages::internalError(asyncResp->res);
Chris Caindfbf7de2023-04-13 16:01:04 -0500343 return;
344 }
345
346 const bool* status = nullptr;
347 const std::vector<std::string>* causes = nullptr;
348
349 if (!sdbusplus::unpackPropertiesNoThrow(dbus_utils::UnpackErrorPrinter(),
350 properties, "Throttled", status,
351 "ThrottleCauses", causes))
352 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700353 messages::internalError(asyncResp->res);
Chris Caindfbf7de2023-04-13 16:01:04 -0500354 return;
355 }
356
Ed Tanousac106bf2023-06-07 09:24:59 -0700357 asyncResp->res.jsonValue["Throttled"] = *status;
Chris Caindfbf7de2023-04-13 16:01:04 -0500358 nlohmann::json::array_t rCauses;
359 for (const std::string& cause : *causes)
360 {
361 processor::ThrottleCause rfCause = dbusToRfThrottleCause(cause);
362 if (rfCause == processor::ThrottleCause::Invalid)
363 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700364 messages::internalError(asyncResp->res);
Chris Caindfbf7de2023-04-13 16:01:04 -0500365 return;
366 }
367
368 rCauses.emplace_back(rfCause);
369 }
Ed Tanousac106bf2023-06-07 09:24:59 -0700370 asyncResp->res.jsonValue["ThrottleCauses"] = std::move(rCauses);
Chris Caindfbf7de2023-04-13 16:01:04 -0500371}
372
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400373inline void getThrottleProperties(
374 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
375 const std::string& service, const std::string& objectPath)
Chris Caindfbf7de2023-04-13 16:01:04 -0500376{
Ed Tanous62598e32023-07-17 17:06:25 -0700377 BMCWEB_LOG_DEBUG("Get processor throttle resources");
Chris Caindfbf7de2023-04-13 16:01:04 -0500378
379 sdbusplus::asio::getAllProperties(
380 *crow::connections::systemBus, service, objectPath,
381 "xyz.openbmc_project.Control.Power.Throttle",
Ed Tanousac106bf2023-06-07 09:24:59 -0700382 [asyncResp](const boost::system::error_code& ec,
383 const dbus::utility::DBusPropertiesMap& properties) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400384 readThrottleProperties(asyncResp, ec, properties);
385 });
Chris Caindfbf7de2023-04-13 16:01:04 -0500386}
387
Ed Tanousac106bf2023-06-07 09:24:59 -0700388inline void getCpuAssetData(std::shared_ptr<bmcweb::AsyncResp> asyncResp,
Gunnar Millsac6a4442020-10-14 14:55:29 -0500389 const std::string& service,
390 const std::string& objPath)
391{
Ed Tanous62598e32023-07-17 17:06:25 -0700392 BMCWEB_LOG_DEBUG("Get Cpu Asset Data");
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200393 sdbusplus::asio::getAllProperties(
394 *crow::connections::systemBus, service, objPath,
395 "xyz.openbmc_project.Inventory.Decorator.Asset",
Ed Tanousac106bf2023-06-07 09:24:59 -0700396 [objPath, asyncResp{std::move(asyncResp)}](
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800397 const boost::system::error_code& ec,
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200398 const dbus::utility::DBusPropertiesMap& properties) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400399 if (ec)
Ed Tanous002d39b2022-05-31 08:59:27 -0700400 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400401 BMCWEB_LOG_DEBUG("DBUS response error");
402 messages::internalError(asyncResp->res);
403 return;
Ed Tanous002d39b2022-05-31 08:59:27 -0700404 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400405
406 const std::string* serialNumber = nullptr;
407 const std::string* model = nullptr;
408 const std::string* manufacturer = nullptr;
409 const std::string* partNumber = nullptr;
410 const std::string* sparePartNumber = nullptr;
411
412 const bool success = sdbusplus::unpackPropertiesNoThrow(
413 dbus_utils::UnpackErrorPrinter(), properties, "SerialNumber",
414 serialNumber, "Model", model, "Manufacturer", manufacturer,
415 "PartNumber", partNumber, "SparePartNumber", sparePartNumber);
416
417 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -0700418 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400419 messages::internalError(asyncResp->res);
420 return;
Ed Tanous002d39b2022-05-31 08:59:27 -0700421 }
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200422
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400423 if (serialNumber != nullptr && !serialNumber->empty())
424 {
425 asyncResp->res.jsonValue["SerialNumber"] = *serialNumber;
426 }
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200427
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400428 if ((model != nullptr) && !model->empty())
429 {
430 asyncResp->res.jsonValue["Model"] = *model;
431 }
432
433 if (manufacturer != nullptr)
434 {
435 asyncResp->res.jsonValue["Manufacturer"] = *manufacturer;
436
437 // Otherwise would be unexpected.
438 if (manufacturer->find("Intel") != std::string::npos)
439 {
440 asyncResp->res.jsonValue["ProcessorArchitecture"] = "x86";
441 asyncResp->res.jsonValue["InstructionSet"] = "x86-64";
442 }
443 else if (manufacturer->find("IBM") != std::string::npos)
444 {
445 asyncResp->res.jsonValue["ProcessorArchitecture"] = "Power";
446 asyncResp->res.jsonValue["InstructionSet"] = "PowerISA";
447 }
448 }
449
450 if (partNumber != nullptr)
451 {
452 asyncResp->res.jsonValue["PartNumber"] = *partNumber;
453 }
454
455 if (sparePartNumber != nullptr && !sparePartNumber->empty())
456 {
457 asyncResp->res.jsonValue["SparePartNumber"] = *sparePartNumber;
458 }
459 });
Gunnar Millsac6a4442020-10-14 14:55:29 -0500460}
461
Ed Tanousac106bf2023-06-07 09:24:59 -0700462inline void getCpuRevisionData(std::shared_ptr<bmcweb::AsyncResp> asyncResp,
Gunnar Millsac6a4442020-10-14 14:55:29 -0500463 const std::string& service,
464 const std::string& objPath)
465{
Ed Tanous62598e32023-07-17 17:06:25 -0700466 BMCWEB_LOG_DEBUG("Get Cpu Revision Data");
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200467 sdbusplus::asio::getAllProperties(
468 *crow::connections::systemBus, service, objPath,
469 "xyz.openbmc_project.Inventory.Decorator.Revision",
Ed Tanousac106bf2023-06-07 09:24:59 -0700470 [objPath, asyncResp{std::move(asyncResp)}](
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800471 const boost::system::error_code& ec,
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200472 const dbus::utility::DBusPropertiesMap& properties) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400473 if (ec)
474 {
475 BMCWEB_LOG_DEBUG("DBUS response error");
476 messages::internalError(asyncResp->res);
477 return;
478 }
Gunnar Millsac6a4442020-10-14 14:55:29 -0500479
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400480 const std::string* version = nullptr;
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200481
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400482 const bool success = sdbusplus::unpackPropertiesNoThrow(
483 dbus_utils::UnpackErrorPrinter(), properties, "Version",
484 version);
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200485
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400486 if (!success)
487 {
488 messages::internalError(asyncResp->res);
489 return;
490 }
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200491
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400492 if (version != nullptr)
493 {
494 asyncResp->res.jsonValue["Version"] = *version;
495 }
496 });
Gunnar Millsac6a4442020-10-14 14:55:29 -0500497}
498
zhanghch058d1b46d2021-04-01 11:18:24 +0800499inline void getAcceleratorDataByService(
Ed Tanousac106bf2023-06-07 09:24:59 -0700500 std::shared_ptr<bmcweb::AsyncResp> asyncResp, const std::string& acclrtrId,
zhanghch058d1b46d2021-04-01 11:18:24 +0800501 const std::string& service, const std::string& objPath)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500502{
Ed Tanous62598e32023-07-17 17:06:25 -0700503 BMCWEB_LOG_DEBUG("Get available system Accelerator resources by service.");
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200504 sdbusplus::asio::getAllProperties(
505 *crow::connections::systemBus, service, objPath, "",
Ed Tanousac106bf2023-06-07 09:24:59 -0700506 [acclrtrId, asyncResp{std::move(asyncResp)}](
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800507 const boost::system::error_code& ec,
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200508 const dbus::utility::DBusPropertiesMap& properties) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400509 if (ec)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500510 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400511 BMCWEB_LOG_DEBUG("DBUS response error");
512 messages::internalError(asyncResp->res);
513 return;
Gunnar Millsac6a4442020-10-14 14:55:29 -0500514 }
515
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400516 const bool* functional = nullptr;
517 const bool* present = nullptr;
518
519 const bool success = sdbusplus::unpackPropertiesNoThrow(
520 dbus_utils::UnpackErrorPrinter(), properties, "Functional",
521 functional, "Present", present);
522
523 if (!success)
524 {
525 messages::internalError(asyncResp->res);
526 return;
527 }
528
529 std::string state = "Enabled";
530 std::string health = "OK";
531
532 if (present != nullptr && !*present)
533 {
534 state = "Absent";
535 }
536
537 if (functional != nullptr && !*functional)
538 {
539 if (state == "Enabled")
540 {
541 health = "Critical";
542 }
543 }
544
545 asyncResp->res.jsonValue["Id"] = acclrtrId;
546 asyncResp->res.jsonValue["Name"] = "Processor";
547 asyncResp->res.jsonValue["Status"]["State"] = state;
548 asyncResp->res.jsonValue["Status"]["Health"] = health;
549 asyncResp->res.jsonValue["ProcessorType"] =
550 processor::ProcessorType::Accelerator;
551 });
Gunnar Millsac6a4442020-10-14 14:55:29 -0500552}
553
Jonathan Domandba0c292020-12-02 15:34:13 -0800554// OperatingConfig D-Bus Types
555using TurboProfileProperty = std::vector<std::tuple<uint32_t, size_t>>;
556using BaseSpeedPrioritySettingsProperty =
557 std::vector<std::tuple<uint32_t, std::vector<uint32_t>>>;
558// uint32_t and size_t may or may not be the same type, requiring a dedup'd
559// variant
Jonathan Domandba0c292020-12-02 15:34:13 -0800560
561/**
562 * Fill out the HighSpeedCoreIDs in a Processor resource from the given
563 * OperatingConfig D-Bus property.
564 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700565 * @param[in,out] asyncResp Async HTTP response.
Jonathan Domandba0c292020-12-02 15:34:13 -0800566 * @param[in] baseSpeedSettings Full list of base speed priority groups,
567 * to use to determine the list of high
568 * speed cores.
569 */
570inline void highSpeedCoreIdsHandler(
Ed Tanousac106bf2023-06-07 09:24:59 -0700571 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Jonathan Domandba0c292020-12-02 15:34:13 -0800572 const BaseSpeedPrioritySettingsProperty& baseSpeedSettings)
573{
574 // The D-Bus property does not indicate which bucket is the "high
575 // priority" group, so let's discern that by looking for the one with
576 // highest base frequency.
577 auto highPriorityGroup = baseSpeedSettings.cend();
578 uint32_t highestBaseSpeed = 0;
579 for (auto it = baseSpeedSettings.cbegin(); it != baseSpeedSettings.cend();
580 ++it)
581 {
582 const uint32_t baseFreq = std::get<uint32_t>(*it);
583 if (baseFreq > highestBaseSpeed)
584 {
585 highestBaseSpeed = baseFreq;
586 highPriorityGroup = it;
587 }
588 }
589
Ed Tanousac106bf2023-06-07 09:24:59 -0700590 nlohmann::json& jsonCoreIds = asyncResp->res.jsonValue["HighSpeedCoreIDs"];
Jonathan Domandba0c292020-12-02 15:34:13 -0800591 jsonCoreIds = nlohmann::json::array();
592
593 // There may not be any entries in the D-Bus property, so only populate
594 // if there was actually something there.
595 if (highPriorityGroup != baseSpeedSettings.cend())
596 {
597 jsonCoreIds = std::get<std::vector<uint32_t>>(*highPriorityGroup);
598 }
599}
600
601/**
602 * Fill out OperatingConfig related items in a Processor resource by requesting
603 * data from the given D-Bus object.
604 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700605 * @param[in,out] asyncResp Async HTTP response.
Jonathan Domandba0c292020-12-02 15:34:13 -0800606 * @param[in] cpuId CPU D-Bus name.
607 * @param[in] service D-Bus service to query.
608 * @param[in] objPath D-Bus object to query.
609 */
Ed Tanousac106bf2023-06-07 09:24:59 -0700610inline void
611 getCpuConfigData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
612 const std::string& cpuId, const std::string& service,
613 const std::string& objPath)
Jonathan Domandba0c292020-12-02 15:34:13 -0800614{
Ed Tanous62598e32023-07-17 17:06:25 -0700615 BMCWEB_LOG_INFO("Getting CPU operating configs for {}", cpuId);
Jonathan Domandba0c292020-12-02 15:34:13 -0800616
617 // First, GetAll CurrentOperatingConfig properties on the object
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200618 sdbusplus::asio::getAllProperties(
619 *crow::connections::systemBus, service, objPath,
620 "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig",
Ed Tanousac106bf2023-06-07 09:24:59 -0700621 [asyncResp, cpuId,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800622 service](const boost::system::error_code& ec,
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200623 const dbus::utility::DBusPropertiesMap& properties) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400624 if (ec)
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200625 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400626 BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec, ec.message());
Ed Tanousac106bf2023-06-07 09:24:59 -0700627 messages::internalError(asyncResp->res);
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200628 return;
629 }
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200630
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400631 nlohmann::json& json = asyncResp->res.jsonValue;
632
633 const sdbusplus::message::object_path* appliedConfig = nullptr;
634 const bool* baseSpeedPriorityEnabled = nullptr;
635
636 const bool success = sdbusplus::unpackPropertiesNoThrow(
637 dbus_utils::UnpackErrorPrinter(), properties, "AppliedConfig",
638 appliedConfig, "BaseSpeedPriorityEnabled",
639 baseSpeedPriorityEnabled);
640
641 if (!success)
642 {
643 messages::internalError(asyncResp->res);
644 return;
645 }
646
647 if (appliedConfig != nullptr)
648 {
649 const std::string& dbusPath = appliedConfig->str;
650 nlohmann::json::object_t operatingConfig;
651 operatingConfig["@odata.id"] = boost::urls::format(
652 "/redfish/v1/Systems/{}/Processors/{}/OperatingConfigs",
653 BMCWEB_REDFISH_SYSTEM_URI_NAME, cpuId);
654 json["OperatingConfigs"] = std::move(operatingConfig);
655
656 // Reuse the D-Bus config object name for the Redfish
657 // URI
658 size_t baseNamePos = dbusPath.rfind('/');
659 if (baseNamePos == std::string::npos ||
660 baseNamePos == (dbusPath.size() - 1))
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200661 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400662 // If the AppliedConfig was somehow not a valid path,
663 // skip adding any more properties, since everything
664 // else is tied to this applied config.
Ed Tanousac106bf2023-06-07 09:24:59 -0700665 messages::internalError(asyncResp->res);
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200666 return;
667 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400668 nlohmann::json::object_t appliedOperatingConfig;
669 appliedOperatingConfig["@odata.id"] = boost::urls::format(
670 "/redfish/v1/Systems/{}/Processors/{}/OperatingConfigs/{}",
671 BMCWEB_REDFISH_SYSTEM_URI_NAME, cpuId,
672 dbusPath.substr(baseNamePos + 1));
673 json["AppliedOperatingConfig"] =
674 std::move(appliedOperatingConfig);
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200675
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400676 // Once we found the current applied config, queue another
677 // request to read the base freq core ids out of that
678 // config.
679 sdbusplus::asio::getProperty<BaseSpeedPrioritySettingsProperty>(
680 *crow::connections::systemBus, service, dbusPath,
681 "xyz.openbmc_project.Inventory.Item.Cpu."
682 "OperatingConfig",
683 "BaseSpeedPrioritySettings",
684 [asyncResp](const boost::system::error_code& ec2,
685 const BaseSpeedPrioritySettingsProperty&
686 baseSpeedList) {
687 if (ec2)
688 {
689 BMCWEB_LOG_WARNING("D-Bus Property Get error: {}",
690 ec2);
691 messages::internalError(asyncResp->res);
692 return;
693 }
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200694
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400695 highSpeedCoreIdsHandler(asyncResp, baseSpeedList);
696 });
697 }
698
699 if (baseSpeedPriorityEnabled != nullptr)
700 {
701 json["BaseSpeedPriorityState"] =
702 *baseSpeedPriorityEnabled ? "Enabled" : "Disabled";
703 }
704 });
Jonathan Domandba0c292020-12-02 15:34:13 -0800705}
706
SunnySrivastava1984cba4f442021-01-07 12:48:16 -0600707/**
708 * @brief Fill out location info of a processor by
709 * requesting data from the given D-Bus object.
710 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700711 * @param[in,out] asyncResp Async HTTP response.
SunnySrivastava1984cba4f442021-01-07 12:48:16 -0600712 * @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 getCpuLocationCode(std::shared_ptr<bmcweb::AsyncResp> asyncResp,
SunnySrivastava1984cba4f442021-01-07 12:48:16 -0600716 const std::string& service,
717 const std::string& objPath)
718{
Ed Tanous62598e32023-07-17 17:06:25 -0700719 BMCWEB_LOG_DEBUG("Get Cpu Location Data");
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700720 sdbusplus::asio::getProperty<std::string>(
721 *crow::connections::systemBus, service, objPath,
722 "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode",
Ed Tanousac106bf2023-06-07 09:24:59 -0700723 [objPath, asyncResp{std::move(asyncResp)}](
724 const boost::system::error_code& ec, const std::string& property) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400725 if (ec)
726 {
727 BMCWEB_LOG_DEBUG("DBUS response error");
728 messages::internalError(asyncResp->res);
729 return;
730 }
SunnySrivastava1984cba4f442021-01-07 12:48:16 -0600731
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400732 asyncResp->res
733 .jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
734 property;
735 });
SunnySrivastava1984cba4f442021-01-07 12:48:16 -0600736}
737
Jonathan Domanc9514482021-02-24 09:20:51 -0800738/**
Jonathan Doman49e429c2021-03-03 13:11:44 -0800739 * Populate the unique identifier in a Processor resource by requesting data
740 * from the given D-Bus object.
741 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700742 * @param[in,out] asyncResp Async HTTP response.
Jonathan Doman49e429c2021-03-03 13:11:44 -0800743 * @param[in] service D-Bus service to query.
744 * @param[in] objPath D-Bus object to query.
745 */
Ed Tanousac106bf2023-06-07 09:24:59 -0700746inline void getCpuUniqueId(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Jonathan Doman49e429c2021-03-03 13:11:44 -0800747 const std::string& service,
748 const std::string& objectPath)
749{
Ed Tanous62598e32023-07-17 17:06:25 -0700750 BMCWEB_LOG_DEBUG("Get CPU UniqueIdentifier");
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700751 sdbusplus::asio::getProperty<std::string>(
752 *crow::connections::systemBus, service, objectPath,
753 "xyz.openbmc_project.Inventory.Decorator.UniqueIdentifier",
754 "UniqueIdentifier",
Ed Tanousac106bf2023-06-07 09:24:59 -0700755 [asyncResp](const boost::system::error_code& ec,
756 const std::string& id) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400757 if (ec)
758 {
759 BMCWEB_LOG_ERROR("Failed to read cpu unique id: {}", ec);
760 messages::internalError(asyncResp->res);
761 return;
762 }
763 asyncResp->res
764 .jsonValue["ProcessorId"]["ProtectedIdentificationNumber"] = id;
765 });
Jonathan Doman49e429c2021-03-03 13:11:44 -0800766}
767
768/**
Jonathan Domanc9514482021-02-24 09:20:51 -0800769 * Find the D-Bus object representing the requested Processor, and call the
770 * handler with the results. If matching object is not found, add 404 error to
771 * response and don't call the handler.
772 *
773 * @param[in,out] resp Async HTTP response.
774 * @param[in] processorId Redfish Processor Id.
775 * @param[in] handler Callback to continue processing request upon
776 * successfully finding object.
777 */
778template <typename Handler>
zhanghch058d1b46d2021-04-01 11:18:24 +0800779inline void getProcessorObject(const std::shared_ptr<bmcweb::AsyncResp>& resp,
Jonathan Domanc9514482021-02-24 09:20:51 -0800780 const std::string& processorId,
781 Handler&& handler)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500782{
Ed Tanous62598e32023-07-17 17:06:25 -0700783 BMCWEB_LOG_DEBUG("Get available system processor resources.");
Gunnar Millsac6a4442020-10-14 14:55:29 -0500784
Jonathan Domanc9514482021-02-24 09:20:51 -0800785 // GetSubTree on all interfaces which provide info about a Processor
Chris Caindfbf7de2023-04-13 16:01:04 -0500786 constexpr std::array<std::string_view, 9> interfaces = {
George Liue99073f2022-12-09 11:06:16 +0800787 "xyz.openbmc_project.Common.UUID",
788 "xyz.openbmc_project.Inventory.Decorator.Asset",
789 "xyz.openbmc_project.Inventory.Decorator.Revision",
790 "xyz.openbmc_project.Inventory.Item.Cpu",
791 "xyz.openbmc_project.Inventory.Decorator.LocationCode",
792 "xyz.openbmc_project.Inventory.Item.Accelerator",
793 "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig",
Chris Caindfbf7de2023-04-13 16:01:04 -0500794 "xyz.openbmc_project.Inventory.Decorator.UniqueIdentifier",
795 "xyz.openbmc_project.Control.Power.Throttle"};
George Liue99073f2022-12-09 11:06:16 +0800796 dbus::utility::getSubTree(
797 "/xyz/openbmc_project/inventory", 0, interfaces,
Jonathan Domanc9514482021-02-24 09:20:51 -0800798 [resp, processorId, handler = std::forward<Handler>(handler)](
George Liue99073f2022-12-09 11:06:16 +0800799 const boost::system::error_code& ec,
800 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400801 if (ec)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500802 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400803 BMCWEB_LOG_DEBUG("DBUS response error: {}", ec);
804 messages::internalError(resp->res);
805 return;
Gunnar Millsac6a4442020-10-14 14:55:29 -0500806 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400807 for (const auto& [objectPath, serviceMap] : subtree)
Gunnar Millsac6a4442020-10-14 14:55:29 -0500808 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400809 // Ignore any objects which don't end with our desired cpu name
810 if (!objectPath.ends_with(processorId))
Gunnar Millsac6a4442020-10-14 14:55:29 -0500811 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400812 continue;
Jonathan Doman2bab9832020-12-02 15:27:40 -0800813 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400814
815 bool found = false;
816 // Filter out objects that don't have the CPU-specific
817 // interfaces to make sure we can return 404 on non-CPUs
818 // (e.g. /redfish/../Processors/dimm0)
819 for (const auto& [serviceName, interfaceList] : serviceMap)
820 {
821 if (std::ranges::find_first_of(interfaceList,
822 processorInterfaces) !=
823 std::end(interfaceList))
824 {
825 found = true;
826 break;
827 }
828 }
829
830 if (!found)
831 {
832 continue;
833 }
834
835 // Process the first object which does match our cpu name and
836 // required interfaces, and potentially ignore any other
837 // matching objects. Assume all interfaces we want to process
838 // must be on the same object path.
839
840 handler(objectPath, serviceMap);
841 return;
Gunnar Millsac6a4442020-10-14 14:55:29 -0500842 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400843 messages::resourceNotFound(resp->res, "Processor", processorId);
844 });
Gunnar Millsac6a4442020-10-14 14:55:29 -0500845}
846
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400847inline void getProcessorData(
848 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
849 const std::string& processorId, const std::string& objectPath,
850 const dbus::utility::MapperServiceMap& serviceMap)
Jonathan Domanc9514482021-02-24 09:20:51 -0800851{
852 for (const auto& [serviceName, interfaceList] : serviceMap)
853 {
854 for (const auto& interface : interfaceList)
855 {
856 if (interface == "xyz.openbmc_project.Inventory.Decorator.Asset")
857 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700858 getCpuAssetData(asyncResp, serviceName, objectPath);
Jonathan Domanc9514482021-02-24 09:20:51 -0800859 }
George Liu0fda0f12021-11-16 10:06:17 +0800860 else if (interface ==
861 "xyz.openbmc_project.Inventory.Decorator.Revision")
Jonathan Domanc9514482021-02-24 09:20:51 -0800862 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700863 getCpuRevisionData(asyncResp, serviceName, objectPath);
Jonathan Domanc9514482021-02-24 09:20:51 -0800864 }
865 else if (interface == "xyz.openbmc_project.Inventory.Item.Cpu")
866 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700867 getCpuDataByService(asyncResp, processorId, serviceName,
Jonathan Domanc9514482021-02-24 09:20:51 -0800868 objectPath);
869 }
George Liu0fda0f12021-11-16 10:06:17 +0800870 else if (interface ==
871 "xyz.openbmc_project.Inventory.Item.Accelerator")
Jonathan Domanc9514482021-02-24 09:20:51 -0800872 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700873 getAcceleratorDataByService(asyncResp, processorId, serviceName,
Jonathan Domanc9514482021-02-24 09:20:51 -0800874 objectPath);
875 }
George Liu0fda0f12021-11-16 10:06:17 +0800876 else if (
877 interface ==
878 "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig")
Jonathan Domanc9514482021-02-24 09:20:51 -0800879 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700880 getCpuConfigData(asyncResp, processorId, serviceName,
881 objectPath);
Jonathan Domanc9514482021-02-24 09:20:51 -0800882 }
George Liu0fda0f12021-11-16 10:06:17 +0800883 else if (interface ==
884 "xyz.openbmc_project.Inventory.Decorator.LocationCode")
Jonathan Domanc9514482021-02-24 09:20:51 -0800885 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700886 getCpuLocationCode(asyncResp, serviceName, objectPath);
Jonathan Domanc9514482021-02-24 09:20:51 -0800887 }
Sharad Yadav71b82f22021-05-10 15:11:39 +0530888 else if (interface == "xyz.openbmc_project.Common.UUID")
889 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700890 getProcessorUUID(asyncResp, serviceName, objectPath);
Sharad Yadav71b82f22021-05-10 15:11:39 +0530891 }
George Liu0fda0f12021-11-16 10:06:17 +0800892 else if (interface ==
893 "xyz.openbmc_project.Inventory.Decorator.UniqueIdentifier")
Jonathan Doman49e429c2021-03-03 13:11:44 -0800894 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700895 getCpuUniqueId(asyncResp, serviceName, objectPath);
Jonathan Doman49e429c2021-03-03 13:11:44 -0800896 }
Chris Caindfbf7de2023-04-13 16:01:04 -0500897 else if (interface == "xyz.openbmc_project.Control.Power.Throttle")
898 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700899 getThrottleProperties(asyncResp, serviceName, objectPath);
Chris Caindfbf7de2023-04-13 16:01:04 -0500900 }
Jonathan Domanc9514482021-02-24 09:20:51 -0800901 }
902 }
903}
904
Jonathan Domandba0c292020-12-02 15:34:13 -0800905/**
906 * Request all the properties for the given D-Bus object and fill out the
907 * related entries in the Redfish OperatingConfig response.
908 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700909 * @param[in,out] asyncResp Async HTTP response.
Jonathan Domandba0c292020-12-02 15:34:13 -0800910 * @param[in] service D-Bus service name to query.
911 * @param[in] objPath D-Bus object to query.
912 */
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400913inline void getOperatingConfigData(
914 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
915 const std::string& service, const std::string& objPath)
Jonathan Domandba0c292020-12-02 15:34:13 -0800916{
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200917 sdbusplus::asio::getAllProperties(
918 *crow::connections::systemBus, service, objPath,
919 "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig",
Ed Tanousac106bf2023-06-07 09:24:59 -0700920 [asyncResp](const boost::system::error_code& ec,
921 const dbus::utility::DBusPropertiesMap& properties) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400922 if (ec)
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200923 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400924 BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec, ec.message());
925 messages::internalError(asyncResp->res);
926 return;
Ed Tanous002d39b2022-05-31 08:59:27 -0700927 }
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200928
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400929 const size_t* availableCoreCount = nullptr;
930 const uint32_t* baseSpeed = nullptr;
931 const uint32_t* maxJunctionTemperature = nullptr;
932 const uint32_t* maxSpeed = nullptr;
933 const uint32_t* powerLimit = nullptr;
934 const TurboProfileProperty* turboProfile = nullptr;
935 const BaseSpeedPrioritySettingsProperty* baseSpeedPrioritySettings =
936 nullptr;
937
938 const bool success = sdbusplus::unpackPropertiesNoThrow(
939 dbus_utils::UnpackErrorPrinter(), properties,
940 "AvailableCoreCount", availableCoreCount, "BaseSpeed",
941 baseSpeed, "MaxJunctionTemperature", maxJunctionTemperature,
942 "MaxSpeed", maxSpeed, "PowerLimit", powerLimit, "TurboProfile",
943 turboProfile, "BaseSpeedPrioritySettings",
944 baseSpeedPrioritySettings);
945
946 if (!success)
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200947 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400948 messages::internalError(asyncResp->res);
949 return;
Krzysztof Grobelny351053f2022-07-28 15:44:22 +0200950 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400951
952 nlohmann::json& json = asyncResp->res.jsonValue;
953
954 if (availableCoreCount != nullptr)
955 {
956 json["TotalAvailableCoreCount"] = *availableCoreCount;
957 }
958
959 if (baseSpeed != nullptr)
960 {
961 json["BaseSpeedMHz"] = *baseSpeed;
962 }
963
964 if (maxJunctionTemperature != nullptr)
965 {
966 json["MaxJunctionTemperatureCelsius"] = *maxJunctionTemperature;
967 }
968
969 if (maxSpeed != nullptr)
970 {
971 json["MaxSpeedMHz"] = *maxSpeed;
972 }
973
974 if (powerLimit != nullptr)
975 {
976 json["TDPWatts"] = *powerLimit;
977 }
978
979 if (turboProfile != nullptr)
980 {
981 nlohmann::json& turboArray = json["TurboProfile"];
982 turboArray = nlohmann::json::array();
983 for (const auto& [turboSpeed, coreCount] : *turboProfile)
984 {
985 nlohmann::json::object_t turbo;
986 turbo["ActiveCoreCount"] = coreCount;
987 turbo["MaxSpeedMHz"] = turboSpeed;
988 turboArray.emplace_back(std::move(turbo));
989 }
990 }
991
992 if (baseSpeedPrioritySettings != nullptr)
993 {
994 nlohmann::json& baseSpeedArray =
995 json["BaseSpeedPrioritySettings"];
996 baseSpeedArray = nlohmann::json::array();
997 for (const auto& [baseSpeedMhz, coreList] :
998 *baseSpeedPrioritySettings)
999 {
1000 nlohmann::json::object_t speed;
1001 speed["CoreCount"] = coreList.size();
1002 speed["CoreIDs"] = coreList;
1003 speed["BaseSpeedMHz"] = baseSpeedMhz;
1004 baseSpeedArray.emplace_back(std::move(speed));
1005 }
1006 }
1007 });
Jonathan Domandba0c292020-12-02 15:34:13 -08001008}
1009
Jonathan Doman3cde86f2020-12-02 14:50:45 -08001010/**
Jonathan Doman3cde86f2020-12-02 14:50:45 -08001011 * Handle the PATCH operation of the AppliedOperatingConfig property. Do basic
1012 * validation of the input data, and then set the D-Bus property.
1013 *
1014 * @param[in,out] resp Async HTTP response.
1015 * @param[in] processorId Processor's Id.
1016 * @param[in] appliedConfigUri New property value to apply.
1017 * @param[in] cpuObjectPath Path of CPU object to modify.
1018 * @param[in] serviceMap Service map for CPU object.
1019 */
1020inline void patchAppliedOperatingConfig(
1021 const std::shared_ptr<bmcweb::AsyncResp>& resp,
1022 const std::string& processorId, const std::string& appliedConfigUri,
Shantappa Teekappanavar5df6eda2022-01-18 12:29:28 -06001023 const std::string& cpuObjectPath,
1024 const dbus::utility::MapperServiceMap& serviceMap)
Jonathan Doman3cde86f2020-12-02 14:50:45 -08001025{
1026 // Check that the property even exists by checking for the interface
1027 const std::string* controlService = nullptr;
1028 for (const auto& [serviceName, interfaceList] : serviceMap)
1029 {
Ed Tanous3544d2a2023-08-06 18:12:20 -07001030 if (std::ranges::find(interfaceList,
1031 "xyz.openbmc_project.Control.Processor."
1032 "CurrentOperatingConfig") != interfaceList.end())
Jonathan Doman3cde86f2020-12-02 14:50:45 -08001033 {
1034 controlService = &serviceName;
1035 break;
1036 }
1037 }
1038
1039 if (controlService == nullptr)
1040 {
1041 messages::internalError(resp->res);
1042 return;
1043 }
1044
1045 // Check that the config URI is a child of the cpu URI being patched.
Ed Tanous253f11b2024-05-16 09:38:31 -07001046 std::string expectedPrefix(std::format("/redfish/v1/Systems/{}/Processors/",
1047 BMCWEB_REDFISH_SYSTEM_URI_NAME));
Jonathan Doman3cde86f2020-12-02 14:50:45 -08001048 expectedPrefix += processorId;
1049 expectedPrefix += "/OperatingConfigs/";
Ed Tanous11ba3972022-07-11 09:50:41 -07001050 if (!appliedConfigUri.starts_with(expectedPrefix) ||
Jonathan Doman3cde86f2020-12-02 14:50:45 -08001051 expectedPrefix.size() == appliedConfigUri.size())
1052 {
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001053 messages::propertyValueIncorrect(resp->res, "AppliedOperatingConfig",
1054 appliedConfigUri);
Jonathan Doman3cde86f2020-12-02 14:50:45 -08001055 return;
1056 }
1057
1058 // Generate the D-Bus path of the OperatingConfig object, by assuming it's a
1059 // direct child of the CPU object.
1060 // Strip the expectedPrefix from the config URI to get the "filename", and
1061 // append to the CPU's path.
1062 std::string configBaseName = appliedConfigUri.substr(expectedPrefix.size());
1063 sdbusplus::message::object_path configPath(cpuObjectPath);
1064 configPath /= configBaseName;
1065
Ed Tanous62598e32023-07-17 17:06:25 -07001066 BMCWEB_LOG_INFO("Setting config to {}", configPath.str);
Jonathan Doman3cde86f2020-12-02 14:50:45 -08001067
1068 // Set the property, with handler to check error responses
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001069 setDbusProperty(
Ginu Georgee93abac2024-06-14 17:35:27 +05301070 resp, "AppliedOperatingConfig", *controlService, cpuObjectPath,
George Liu9ae226f2023-06-21 17:56:46 +08001071 "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig",
Ginu Georgee93abac2024-06-14 17:35:27 +05301072 "AppliedConfig", configPath);
Jonathan Doman3cde86f2020-12-02 14:50:45 -08001073}
1074
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001075inline void handleProcessorHead(
1076 crow::App& app, const crow::Request& req,
1077 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1078 const std::string& /* systemName */, const std::string& /* processorId */)
Nikhil Namjoshi71a24ca2022-11-11 01:52:32 +00001079{
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/Processor/Processor.json>; rel=describedby");
1087}
1088
1089inline void handleProcessorCollectionHead(
1090 crow::App& app, const crow::Request& req,
Ed Tanousac106bf2023-06-07 09:24:59 -07001091 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Nikhil Namjoshi71a24ca2022-11-11 01:52:32 +00001092 const std::string& /* systemName */)
1093{
Ed Tanousac106bf2023-06-07 09:24:59 -07001094 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Nikhil Namjoshi71a24ca2022-11-11 01:52:32 +00001095 {
1096 return;
1097 }
Ed Tanousac106bf2023-06-07 09:24:59 -07001098 asyncResp->res.addHeader(
Nikhil Namjoshi71a24ca2022-11-11 01:52:32 +00001099 boost::beast::http::field::link,
1100 "</redfish/v1/JsonSchemas/ProcessorCollection/ProcessorCollection.json>; rel=describedby");
1101}
1102
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001103inline void requestRoutesOperatingConfigCollection(App& app)
Jonathan Domandba0c292020-12-02 15:34:13 -08001104{
Ed Tanous7f3e84a2022-12-28 16:22:54 -08001105 BMCWEB_ROUTE(app,
1106 "/redfish/v1/Systems/<str>/Processors/<str>/OperatingConfigs/")
Ed Tanoused398212021-06-09 17:05:54 -07001107 .privileges(redfish::privileges::getOperatingConfigCollection)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001108 .methods(
1109 boost::beast::http::verb::
1110 get)([&app](const crow::Request& req,
1111 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1112 const std::string& systemName,
1113 const std::string& cpuName) {
1114 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous45ca1b82022-03-25 13:07:27 -07001115 {
1116 return;
1117 }
Jonathan Domandba0c292020-12-02 15:34:13 -08001118
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001119 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous002d39b2022-05-31 08:59:27 -07001120 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001121 // Option currently returns no systems. TBD
1122 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1123 systemName);
Ed Tanous002d39b2022-05-31 08:59:27 -07001124 return;
1125 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001126
1127 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1128 {
1129 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1130 systemName);
1131 return;
1132 }
1133 asyncResp->res.jsonValue["@odata.type"] =
1134 "#OperatingConfigCollection.OperatingConfigCollection";
1135 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
1136 "/redfish/v1/Systems/{}/Processors/{}/OperatingConfigs",
1137 BMCWEB_REDFISH_SYSTEM_URI_NAME, cpuName);
1138 asyncResp->res.jsonValue["Name"] = "Operating Config Collection";
1139
1140 // First find the matching CPU object so we know how to
1141 // constrain our search for related Config objects.
1142 const std::array<std::string_view, 1> interfaces = {
1143 "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig"};
1144 dbus::utility::getSubTreePaths(
1145 "/xyz/openbmc_project/inventory", 0, interfaces,
1146 [asyncResp,
1147 cpuName](const boost::system::error_code& ec,
1148 const dbus::utility::MapperGetSubTreePathsResponse&
1149 objects) {
1150 if (ec)
1151 {
1152 BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec,
1153 ec.message());
1154 messages::internalError(asyncResp->res);
1155 return;
1156 }
1157
1158 for (const std::string& object : objects)
1159 {
1160 if (!object.ends_with(cpuName))
1161 {
1162 continue;
1163 }
1164
1165 // Not expected that there will be multiple matching
1166 // CPU objects, but if there are just use the first
1167 // one.
1168
1169 // Use the common search routine to construct the
1170 // Collection of all Config objects under this CPU.
1171 constexpr std::array<std::string_view, 1> interface{
1172 "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig"};
1173 collection_util::getCollectionMembers(
1174 asyncResp,
1175 boost::urls::format(
1176 "/redfish/v1/Systems/{}/Processors/{}/OperatingConfigs",
1177 BMCWEB_REDFISH_SYSTEM_URI_NAME, cpuName),
1178 interface, object);
1179 return;
1180 }
1181 });
George Liu0fda0f12021-11-16 10:06:17 +08001182 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001183}
1184
1185inline void requestRoutesOperatingConfig(App& app)
1186{
1187 BMCWEB_ROUTE(
1188 app,
Ed Tanous7f3e84a2022-12-28 16:22:54 -08001189 "/redfish/v1/Systems/<str>/Processors/<str>/OperatingConfigs/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001190 .privileges(redfish::privileges::getOperatingConfig)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001191 .methods(
1192 boost::beast::http::verb::
1193 get)([&app](const crow::Request& req,
1194 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1195 const std::string& systemName,
1196 const std::string& cpuName,
1197 const std::string& configName) {
1198 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous45ca1b82022-03-25 13:07:27 -07001199 {
1200 return;
1201 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001202 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous002d39b2022-05-31 08:59:27 -07001203 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001204 // Option currently returns no systems. TBD
1205 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1206 systemName);
Ed Tanous002d39b2022-05-31 08:59:27 -07001207 return;
1208 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001209
1210 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1211 {
1212 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1213 systemName);
1214 return;
1215 }
1216 // Ask for all objects implementing OperatingConfig so we can search
1217 // for one with a matching name
1218 constexpr std::array<std::string_view, 1> interfaces = {
1219 "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig"};
1220 dbus::utility::getSubTree(
1221 "/xyz/openbmc_project/inventory", 0, interfaces,
1222 [asyncResp, cpuName, configName](
1223 const boost::system::error_code& ec,
1224 const dbus::utility::MapperGetSubTreeResponse& subtree) {
1225 if (ec)
1226 {
1227 BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec,
1228 ec.message());
1229 messages::internalError(asyncResp->res);
1230 return;
1231 }
1232 const std::string expectedEnding =
1233 cpuName + '/' + configName;
1234 for (const auto& [objectPath, serviceMap] : subtree)
1235 {
1236 // Ignore any configs without matching cpuX/configY
1237 if (!objectPath.ends_with(expectedEnding) ||
1238 serviceMap.empty())
1239 {
1240 continue;
1241 }
1242
1243 nlohmann::json& json = asyncResp->res.jsonValue;
1244 json["@odata.type"] =
1245 "#OperatingConfig.v1_0_0.OperatingConfig";
1246 json["@odata.id"] = boost::urls::format(
1247 "/redfish/v1/Systems/{}/Processors/{}/OperatingConfigs/{}",
1248 BMCWEB_REDFISH_SYSTEM_URI_NAME, cpuName,
1249 configName);
1250 json["Name"] = "Processor Profile";
1251 json["Id"] = configName;
1252
1253 // Just use the first implementation of the object - not
1254 // expected that there would be multiple matching
1255 // services
1256 getOperatingConfigData(
1257 asyncResp, serviceMap.begin()->first, objectPath);
1258 return;
1259 }
1260 messages::resourceNotFound(asyncResp->res,
1261 "OperatingConfig", configName);
1262 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001263 });
1264}
Jonathan Domandba0c292020-12-02 15:34:13 -08001265
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001266inline void requestRoutesProcessorCollection(App& app)
Gunnar Millsac6a4442020-10-14 14:55:29 -05001267{
Gunnar Millsac6a4442020-10-14 14:55:29 -05001268 /**
1269 * Functions triggers appropriate requests on DBus
1270 */
Ed Tanous22d268c2022-05-19 09:39:07 -07001271 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/")
Nikhil Namjoshi71a24ca2022-11-11 01:52:32 +00001272 .privileges(redfish::privileges::headProcessorCollection)
1273 .methods(boost::beast::http::verb::head)(
1274 std::bind_front(handleProcessorCollectionHead, std::ref(app)));
1275
1276 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/")
Ed Tanoused398212021-06-09 17:05:54 -07001277 .privileges(redfish::privileges::getProcessorCollection)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001278 .methods(
1279 boost::beast::http::verb::
1280 get)([&app](const crow::Request& req,
1281 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1282 const std::string& systemName) {
1283 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1284 {
1285 return;
1286 }
1287 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1288 {
1289 // Option currently returns no systems. TBD
1290 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1291 systemName);
1292 return;
1293 }
Ed Tanous7f3e84a2022-12-28 16:22:54 -08001294
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001295 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1296 {
1297 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1298 systemName);
1299 return;
1300 }
Ed Tanous22d268c2022-05-19 09:39:07 -07001301
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001302 asyncResp->res.addHeader(
1303 boost::beast::http::field::link,
1304 "</redfish/v1/JsonSchemas/ProcessorCollection/ProcessorCollection.json>; rel=describedby");
Nikhil Namjoshi71a24ca2022-11-11 01:52:32 +00001305
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001306 asyncResp->res.jsonValue["@odata.type"] =
1307 "#ProcessorCollection.ProcessorCollection";
1308 asyncResp->res.jsonValue["Name"] = "Processor Collection";
Gunnar Millsac6a4442020-10-14 14:55:29 -05001309
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001310 asyncResp->res.jsonValue["@odata.id"] =
1311 std::format("/redfish/v1/Systems/{}/Processors",
1312 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Gunnar Millsac6a4442020-10-14 14:55:29 -05001313
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001314 collection_util::getCollectionMembers(
1315 asyncResp,
1316 boost::urls::format("/redfish/v1/Systems/{}/Processors",
1317 BMCWEB_REDFISH_SYSTEM_URI_NAME),
1318 processorInterfaces, "/xyz/openbmc_project/inventory");
1319 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001320}
Gunnar Millsac6a4442020-10-14 14:55:29 -05001321
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001322inline void requestRoutesProcessor(App& app)
Gunnar Millsac6a4442020-10-14 14:55:29 -05001323{
Gunnar Millsac6a4442020-10-14 14:55:29 -05001324 /**
1325 * Functions triggers appropriate requests on DBus
1326 */
Gunnar Millsac6a4442020-10-14 14:55:29 -05001327
Ed Tanous22d268c2022-05-19 09:39:07 -07001328 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/<str>/")
Nikhil Namjoshi71a24ca2022-11-11 01:52:32 +00001329 .privileges(redfish::privileges::headProcessor)
1330 .methods(boost::beast::http::verb::head)(
1331 std::bind_front(handleProcessorHead, std::ref(app)));
1332
1333 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001334 .privileges(redfish::privileges::getProcessor)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001335 .methods(
1336 boost::beast::http::verb::
1337 get)([&app](const crow::Request& req,
1338 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1339 const std::string& systemName,
1340 const std::string& processorId) {
1341 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1342 {
1343 return;
1344 }
1345 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1346 {
1347 // Option currently returns no systems. TBD
1348 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1349 systemName);
1350 return;
1351 }
1352 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1353 {
1354 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1355 systemName);
1356 return;
1357 }
Ed Tanous22d268c2022-05-19 09:39:07 -07001358
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001359 asyncResp->res.addHeader(
1360 boost::beast::http::field::link,
1361 "</redfish/v1/JsonSchemas/Processor/Processor.json>; rel=describedby");
1362 asyncResp->res.jsonValue["@odata.type"] =
1363 "#Processor.v1_18_0.Processor";
1364 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
1365 "/redfish/v1/Systems/{}/Processors/{}",
1366 BMCWEB_REDFISH_SYSTEM_URI_NAME, processorId);
Jonathan Doman3cde86f2020-12-02 14:50:45 -08001367
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001368 getProcessorObject(
1369 asyncResp, processorId,
1370 std::bind_front(getProcessorData, asyncResp, processorId));
1371 });
Jonathan Doman3cde86f2020-12-02 14:50:45 -08001372
Ed Tanous22d268c2022-05-19 09:39:07 -07001373 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001374 .privileges(redfish::privileges::patchProcessor)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001375 .methods(boost::beast::http::verb::patch)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07001376 [&app](const crow::Request& req,
1377 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous22d268c2022-05-19 09:39:07 -07001378 const std::string& systemName,
Ed Tanous45ca1b82022-03-25 13:07:27 -07001379 const std::string& processorId) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001380 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1381 {
1382 return;
1383 }
1384 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1385 {
1386 // Option currently returns no systems. TBD
1387 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1388 systemName);
1389 return;
1390 }
1391 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1392 {
1393 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1394 systemName);
1395 return;
1396 }
Ed Tanous22d268c2022-05-19 09:39:07 -07001397
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001398 std::optional<std::string> appliedConfigUri;
1399 if (!json_util::readJsonPatch(
1400 req, asyncResp->res, "AppliedOperatingConfig/@odata.id",
1401 appliedConfigUri))
1402 {
1403 return;
1404 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001405
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001406 if (appliedConfigUri)
1407 {
1408 // Check for 404 and find matching D-Bus object, then run
1409 // property patch handlers if that all succeeds.
1410 getProcessorObject(
1411 asyncResp, processorId,
1412 std::bind_front(patchAppliedOperatingConfig, asyncResp,
1413 processorId, *appliedConfigUri));
1414 }
1415 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001416}
Gunnar Millsac6a4442020-10-14 14:55:29 -05001417
1418} // namespace redfish