blob: 38230899f0e4a4da015fb513a8a65b744613ab61 [file] [log] [blame]
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001/*
2// Copyright (c) 2018 Intel Corporation
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
16#pragma once
17
James Feist35e257a2020-06-05 13:30:51 -070018#include "health.hpp"
19
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +020020#include <boost/container/flat_map.hpp>
James Feistc50e7c62020-07-27 15:39:36 -070021#include <boost/format.hpp>
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +020022#include <node.hpp>
23#include <utils/json_utils.hpp>
24
25namespace redfish
26{
27
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -060028using InterfacesProperties = boost::container::flat_map<
29 std::string,
30 boost::container::flat_map<std::string, dbus::utility::DbusVariantType>>;
31
Ed Tanous23a21a12020-07-25 04:45:05 +000032inline void getResourceList(std::shared_ptr<AsyncResp> aResp,
33 const std::string& subclass,
34 const std::vector<const char*>& collectionName)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +020035{
36 BMCWEB_LOG_DEBUG << "Get available system cpu/mem resources.";
37 crow::connections::systemBus->async_method_call(
Ed Tanous029573d2019-02-01 10:57:49 -080038 [subclass, aResp{std::move(aResp)}](
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +020039 const boost::system::error_code ec,
40 const boost::container::flat_map<
41 std::string, boost::container::flat_map<
Gunnar Mills1214b7e2020-06-04 10:11:30 -050042 std::string, std::vector<std::string>>>&
43 subtree) {
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +020044 if (ec)
45 {
46 BMCWEB_LOG_DEBUG << "DBUS response error";
47 messages::internalError(aResp->res);
48 return;
49 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -050050 nlohmann::json& members = aResp->res.jsonValue["Members"];
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +020051 members = nlohmann::json::array();
52
Gunnar Mills1214b7e2020-06-04 10:11:30 -050053 for (const auto& object : subtree)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +020054 {
55 auto iter = object.first.rfind("/");
56 if ((iter != std::string::npos) && (iter < object.first.size()))
57 {
58 members.push_back(
Ed Tanous029573d2019-02-01 10:57:49 -080059 {{"@odata.id", "/redfish/v1/Systems/system/" +
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +020060 subclass + "/" +
61 object.first.substr(iter + 1)}});
62 }
63 }
64 aResp->res.jsonValue["Members@odata.count"] = members.size();
65 },
66 "xyz.openbmc_project.ObjectMapper",
67 "/xyz/openbmc_project/object_mapper",
68 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous271584a2019-07-09 16:24:22 -070069 "/xyz/openbmc_project/inventory", 0, collectionName);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +020070}
71
Ed Tanous23a21a12020-07-25 04:45:05 +000072inline void
Ed Tanousb5a76932020-09-29 16:16:58 -070073 getCpuDataByInterface(const std::shared_ptr<AsyncResp>& aResp,
Ed Tanous23a21a12020-07-25 04:45:05 +000074 const InterfacesProperties& cpuInterfacesProperties)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +020075{
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -060076 BMCWEB_LOG_DEBUG << "Get CPU resources by interface.";
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +020077
Zhikui Ren029cc1f2020-08-25 15:21:41 -070078 // Added for future purpose. Once present and functional attributes added
79 // in busctl call, need to add actual logic to fetch original values.
80 bool present = false;
81 const bool functional = true;
82 auto health = std::make_shared<HealthPopulate>(aResp);
83 health->populate();
84
Gunnar Mills1214b7e2020-06-04 10:11:30 -050085 for (const auto& interface : cpuInterfacesProperties)
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -060086 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -050087 for (const auto& property : interface.second)
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -060088 {
Zhikui Ren029cc1f2020-08-25 15:21:41 -070089 if (property.first == "CoreCount")
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +020090 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -050091 const uint16_t* coresCount =
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -060092 std::get_if<uint16_t>(&property.second);
Ed Tanous883b3112018-12-06 16:13:35 -080093 if (coresCount == nullptr)
94 {
95 // Important property not in desired type
96 messages::internalError(aResp->res);
97 return;
98 }
99 if (*coresCount == 0)
100 {
101 // Slot is not populated, set status end return
102 aResp->res.jsonValue["Status"]["State"] = "Absent";
Ed Tanous883b3112018-12-06 16:13:35 -0800103 // HTTP Code will be set up automatically, just return
104 return;
105 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700106 aResp->res.jsonValue["Status"]["State"] = "Enabled";
107 present = true;
Ed Tanous883b3112018-12-06 16:13:35 -0800108 aResp->res.jsonValue["TotalCores"] = *coresCount;
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200109 }
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700110 else if (property.first == "Socket")
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -0600111 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500112 const std::string* value =
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -0600113 std::get_if<std::string>(&property.second);
114 if (value != nullptr)
115 {
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700116 aResp->res.jsonValue["Socket"] = *value;
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -0600117 }
118 }
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700119 else if (property.first == "ThreadCount")
Gunnar Millsf9dcc112020-02-13 13:19:43 -0600120 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700121 const int64_t* value = std::get_if<int64_t>(&property.second);
122 if (value != nullptr)
123 {
124 aResp->res.jsonValue["TotalThreads"] = *value;
125 }
Gunnar Millsf9dcc112020-02-13 13:19:43 -0600126 }
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700127 else if (property.first == "Family")
Gunnar Millsf9dcc112020-02-13 13:19:43 -0600128 {
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700129 const std::string* value =
130 std::get_if<std::string>(&property.second);
131 if (value != nullptr)
132 {
133 aResp->res.jsonValue["ProcessorId"]["EffectiveFamily"] =
134 *value;
135 }
Gunnar Millsf9dcc112020-02-13 13:19:43 -0600136 }
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700137 else if (property.first == "Id")
Gunnar Millsf9dcc112020-02-13 13:19:43 -0600138 {
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700139 const uint64_t* value = std::get_if<uint64_t>(&property.second);
140 if (value != nullptr && *value != 0)
141 {
142 present = true;
143 aResp->res
144 .jsonValue["ProcessorId"]["IdentificationRegisters"] =
145 boost::lexical_cast<std::string>(*value);
146 }
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -0600147 }
148 }
149 }
150
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700151 if (present == false)
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -0600152 {
153 aResp->res.jsonValue["Status"]["State"] = "Absent";
154 aResp->res.jsonValue["Status"]["Health"] = "OK";
155 }
156 else
157 {
158 aResp->res.jsonValue["Status"]["State"] = "Enabled";
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700159 if (functional)
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -0600160 {
161 aResp->res.jsonValue["Status"]["Health"] = "OK";
162 }
163 else
164 {
165 aResp->res.jsonValue["Status"]["Health"] = "Critical";
166 }
167 }
168
169 return;
170}
171
Ed Tanous23a21a12020-07-25 04:45:05 +0000172inline void getCpuDataByService(std::shared_ptr<AsyncResp> aResp,
173 const std::string& cpuId,
174 const std::string& service,
175 const std::string& objPath)
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -0600176{
177 BMCWEB_LOG_DEBUG << "Get available system cpu resources by service.";
178
179 crow::connections::systemBus->async_method_call(
180 [cpuId, service, objPath, aResp{std::move(aResp)}](
181 const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500182 const dbus::utility::ManagedObjectType& dbusData) {
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -0600183 if (ec)
184 {
185 BMCWEB_LOG_DEBUG << "DBUS response error";
186 messages::internalError(aResp->res);
187 return;
188 }
189 aResp->res.jsonValue["Id"] = cpuId;
190 aResp->res.jsonValue["Name"] = "Processor";
191 aResp->res.jsonValue["ProcessorType"] = "CPU";
192
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700193 bool slotPresent = false;
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -0600194 std::string corePath = objPath + "/core";
195 size_t totalCores = 0;
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500196 for (const auto& object : dbusData)
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -0600197 {
198 if (object.first.str == objPath)
199 {
200 getCpuDataByInterface(aResp, object.second);
201 }
202 else if (boost::starts_with(object.first.str, corePath))
203 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500204 for (const auto& interface : object.second)
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -0600205 {
206 if (interface.first ==
207 "xyz.openbmc_project.Inventory.Item")
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200208 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500209 for (const auto& property : interface.second)
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -0600210 {
211 if (property.first == "Present")
212 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500213 const bool* present =
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -0600214 std::get_if<bool>(&property.second);
215 if (present != nullptr)
216 {
217 if (*present == true)
218 {
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700219 slotPresent = true;
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -0600220 totalCores++;
221 }
222 }
223 }
224 }
Gunnar Millsb957ba52019-01-31 15:58:15 -0600225 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200226 }
227 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200228 }
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -0600229 // In getCpuDataByInterface(), state and health are set
230 // based on the present and functional status. If core
231 // count is zero, then it has a higher precedence.
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700232 if (slotPresent)
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -0600233 {
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700234 if (totalCores == 0)
235 {
236 // Slot is not populated, set status end return
237 aResp->res.jsonValue["Status"]["State"] = "Absent";
238 aResp->res.jsonValue["Status"]["Health"] = "OK";
239 }
240 aResp->res.jsonValue["TotalCores"] = totalCores;
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -0600241 }
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -0600242 return;
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200243 },
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -0600244 service, "/xyz/openbmc_project/inventory",
245 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200246}
247
Ed Tanous23a21a12020-07-25 04:45:05 +0000248inline void getCpuAssetData(std::shared_ptr<AsyncResp> aResp,
249 const std::string& service,
250 const std::string& objPath)
Zhikui Ren5e54a362020-07-13 15:31:38 -0700251{
252 BMCWEB_LOG_DEBUG << "Get Cpu Asset Data";
253 crow::connections::systemBus->async_method_call(
254 [objPath, aResp{std::move(aResp)}](
255 const boost::system::error_code ec,
256 const boost::container::flat_map<
257 std::string, std::variant<std::string, uint32_t, uint16_t,
258 bool>>& properties) {
259 if (ec)
260 {
261 BMCWEB_LOG_DEBUG << "DBUS response error";
262 messages::internalError(aResp->res);
263 return;
264 }
265
266 for (const auto& property : properties)
267 {
268 if (property.first == "SerialNumber")
269 {
270 const std::string* sn =
271 std::get_if<std::string>(&property.second);
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700272 if (sn != nullptr && !sn->empty())
Zhikui Ren5e54a362020-07-13 15:31:38 -0700273 {
274 aResp->res.jsonValue["SerialNumber"] = *sn;
275 }
276 }
277 else if (property.first == "Model")
278 {
279 const std::string* model =
280 std::get_if<std::string>(&property.second);
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700281 if (model != nullptr && !model->empty())
Zhikui Ren5e54a362020-07-13 15:31:38 -0700282 {
283 aResp->res.jsonValue["Model"] = *model;
284 }
285 }
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700286 else if (property.first == "Manufacturer")
287 {
288
289 const std::string* mfg =
290 std::get_if<std::string>(&property.second);
291 if (mfg != nullptr)
292 {
293 aResp->res.jsonValue["Manufacturer"] = *mfg;
294
295 // Otherwise would be unexpected.
296 if (mfg->find("Intel") != std::string::npos)
297 {
298 aResp->res.jsonValue["ProcessorArchitecture"] =
299 "x86";
300 aResp->res.jsonValue["InstructionSet"] = "x86-64";
301 }
302 else if (mfg->find("IBM") != std::string::npos)
303 {
304 aResp->res.jsonValue["ProcessorArchitecture"] =
305 "Power";
306 aResp->res.jsonValue["InstructionSet"] = "PowerISA";
307 }
308 }
309 }
Zhikui Ren5e54a362020-07-13 15:31:38 -0700310 }
311 },
312 service, objPath, "org.freedesktop.DBus.Properties", "GetAll",
313 "xyz.openbmc_project.Inventory.Decorator.Asset");
314}
315
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700316inline void getCpuRevisionData(std::shared_ptr<AsyncResp> aResp,
317 const std::string& service,
318 const std::string& objPath)
319{
320 BMCWEB_LOG_DEBUG << "Get Cpu Revision Data";
321 crow::connections::systemBus->async_method_call(
322 [objPath, aResp{std::move(aResp)}](
323 const boost::system::error_code ec,
324 const boost::container::flat_map<
325 std::string, std::variant<std::string, uint32_t, uint16_t,
326 bool>>& properties) {
327 if (ec)
328 {
329 BMCWEB_LOG_DEBUG << "DBUS response error";
330 messages::internalError(aResp->res);
331 return;
332 }
333
334 for (const auto& property : properties)
335 {
336 if (property.first == "Version")
337 {
338 const std::string* ver =
339 std::get_if<std::string>(&property.second);
340 if (ver != nullptr)
341 {
342 aResp->res.jsonValue["Version"] = *ver;
343 }
344 break;
345 }
346 }
347 },
348 service, objPath, "org.freedesktop.DBus.Properties", "GetAll",
349 "xyz.openbmc_project.Inventory.Decorator.Revision");
350}
351
Ed Tanous23a21a12020-07-25 04:45:05 +0000352inline void getAcceleratorDataByService(std::shared_ptr<AsyncResp> aResp,
353 const std::string& acclrtrId,
354 const std::string& service,
355 const std::string& objPath)
Alpana Kumari32bee762019-04-25 04:47:57 -0500356{
357 BMCWEB_LOG_DEBUG
358 << "Get available system Accelerator resources by service.";
359 crow::connections::systemBus->async_method_call(
360 [acclrtrId, aResp{std::move(aResp)}](
361 const boost::system::error_code ec,
362 const boost::container::flat_map<
Santosh Puranik94e1b822019-07-24 04:48:32 -0500363 std::string, std::variant<std::string, uint32_t, uint16_t,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500364 bool>>& properties) {
Alpana Kumari32bee762019-04-25 04:47:57 -0500365 if (ec)
366 {
367 BMCWEB_LOG_DEBUG << "DBUS response error";
368 messages::internalError(aResp->res);
369 return;
370 }
371 aResp->res.jsonValue["Id"] = acclrtrId;
372 aResp->res.jsonValue["Name"] = "Processor";
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500373 const bool* accPresent = nullptr;
374 const bool* accFunctional = nullptr;
Alpana Kumari32bee762019-04-25 04:47:57 -0500375
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500376 for (const auto& property : properties)
Alpana Kumari32bee762019-04-25 04:47:57 -0500377 {
378 if (property.first == "Functional")
379 {
Santosh Puranik94e1b822019-07-24 04:48:32 -0500380 accFunctional = std::get_if<bool>(&property.second);
Alpana Kumari32bee762019-04-25 04:47:57 -0500381 }
382 else if (property.first == "Present")
383 {
Santosh Puranik94e1b822019-07-24 04:48:32 -0500384 accPresent = std::get_if<bool>(&property.second);
Alpana Kumari32bee762019-04-25 04:47:57 -0500385 }
386 }
387
Alpana Kumaric24e6b82020-10-01 06:58:46 -0500388 std::string state = "Enabled";
389 std::string health = "OK";
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700390
Alpana Kumaric24e6b82020-10-01 06:58:46 -0500391 if (accPresent != nullptr && *accPresent == false)
Alpana Kumari32bee762019-04-25 04:47:57 -0500392 {
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700393 state = "Absent";
Alpana Kumari32bee762019-04-25 04:47:57 -0500394 }
Alpana Kumaric24e6b82020-10-01 06:58:46 -0500395
396 if ((accFunctional != nullptr) && (*accFunctional == false))
397 {
398 if (state == "Enabled")
399 {
400 health = "Critical";
401 }
Alpana Kumaric24e6b82020-10-01 06:58:46 -0500402 }
403
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700404 aResp->res.jsonValue["Status"]["State"] = state;
Alpana Kumaric24e6b82020-10-01 06:58:46 -0500405 aResp->res.jsonValue["Status"]["Health"] = health;
Alpana Kumari32bee762019-04-25 04:47:57 -0500406 aResp->res.jsonValue["ProcessorType"] = "Accelerator";
407 },
408 service, objPath, "org.freedesktop.DBus.Properties", "GetAll", "");
409}
410
Gunnar Millse851f8a2020-10-14 14:36:13 -0500411inline void getProcessorData(std::shared_ptr<AsyncResp> aResp,
412 const std::string& processorId,
413 const std::vector<const char*>& inventoryItems)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200414{
Gunnar Millse851f8a2020-10-14 14:36:13 -0500415 BMCWEB_LOG_DEBUG << "Get available system processor resources.";
Alpana Kumari32bee762019-04-25 04:47:57 -0500416
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200417 crow::connections::systemBus->async_method_call(
Gunnar Millse851f8a2020-10-14 14:36:13 -0500418 [processorId, aResp{std::move(aResp)}](
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200419 const boost::system::error_code ec,
420 const boost::container::flat_map<
421 std::string, boost::container::flat_map<
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500422 std::string, std::vector<std::string>>>&
423 subtree) {
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200424 if (ec)
425 {
426 BMCWEB_LOG_DEBUG << "DBUS response error";
427 messages::internalError(aResp->res);
428 return;
429 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500430 for (const auto& object : subtree)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200431 {
Gunnar Millse851f8a2020-10-14 14:36:13 -0500432 if (boost::ends_with(object.first, processorId))
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200433 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500434 for (const auto& service : object.second)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200435 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500436 for (const auto& inventory : service.second)
Zhikui Ren5e54a362020-07-13 15:31:38 -0700437 {
438 if (inventory == "xyz.openbmc_project."
439 "Inventory.Decorator.Asset")
440 {
441 getCpuAssetData(aResp, service.first,
442 object.first);
443 }
444 else if (inventory ==
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700445 "xyz.openbmc_project."
446 "Inventory.Decorator.Revision")
447 {
448 getCpuRevisionData(aResp, service.first,
449 object.first);
450 }
451 else if (inventory == "xyz.openbmc_project."
452 "Inventory.Item.Cpu")
Alpana Kumari32bee762019-04-25 04:47:57 -0500453 {
Gunnar Millse851f8a2020-10-14 14:36:13 -0500454 getCpuDataByService(aResp, processorId,
455 service.first,
Alpana Kumari32bee762019-04-25 04:47:57 -0500456 object.first);
457 }
458 else if (inventory == "xyz.openbmc_project."
459 "Inventory.Item.Accelerator")
460 {
Gunnar Millse851f8a2020-10-14 14:36:13 -0500461 getAcceleratorDataByService(aResp, processorId,
462 service.first,
463 object.first);
Alpana Kumari32bee762019-04-25 04:47:57 -0500464 }
Zhikui Ren5e54a362020-07-13 15:31:38 -0700465 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200466 }
Zhikui Ren5e54a362020-07-13 15:31:38 -0700467 return;
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200468 }
469 }
470 // Object not found
Gunnar Millse851f8a2020-10-14 14:36:13 -0500471 messages::resourceNotFound(aResp->res, "Processor", processorId);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200472 return;
473 },
474 "xyz.openbmc_project.ObjectMapper",
475 "/xyz/openbmc_project/object_mapper",
476 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous271584a2019-07-09 16:24:22 -0700477 "/xyz/openbmc_project/inventory", 0, inventoryItems);
478}
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200479
James Feistc50e7c62020-07-27 15:39:36 -0700480using DimmProperty =
481 std::variant<std::string, std::vector<uint32_t>, std::vector<uint16_t>,
482 uint64_t, uint32_t, uint16_t, uint8_t, bool>;
483
484using DimmProperties = boost::container::flat_map<std::string, DimmProperty>;
485
Ed Tanousb5a76932020-09-29 16:16:58 -0700486inline void dimmPropToHex(const std::shared_ptr<AsyncResp>& aResp,
487 const char* key,
Ed Tanous80789c82020-08-19 09:19:09 -0700488 const std::pair<std::string, DimmProperty>& property)
James Feistc50e7c62020-07-27 15:39:36 -0700489{
490 const uint16_t* value = std::get_if<uint16_t>(&property.second);
491 if (value == nullptr)
492 {
493 messages::internalError(aResp->res);
494 BMCWEB_LOG_DEBUG << "Invalid property type for " << property.first;
495 return;
496 }
497
498 aResp->res.jsonValue[key] = (boost::format("0x%04x") % *value).str();
499}
500
Ed Tanousb5a76932020-09-29 16:16:58 -0700501inline void
502 getPersistentMemoryProperties(const std::shared_ptr<AsyncResp>& aResp,
503 const DimmProperties& properties)
James Feistc50e7c62020-07-27 15:39:36 -0700504{
505 for (const auto& property : properties)
506 {
507 if (property.first == "ModuleManufacturerID")
508 {
509 dimmPropToHex(aResp, "ModuleManufacturerID", property);
510 }
511 else if (property.first == "ModuleProductID")
512 {
513 dimmPropToHex(aResp, "ModuleProductID", property);
514 }
515 else if (property.first == "SubsystemVendorID")
516 {
517 dimmPropToHex(aResp, "MemorySubsystemControllerManufacturerID",
518 property);
519 }
520 else if (property.first == "SubsystemDeviceID")
521 {
522 dimmPropToHex(aResp, "MemorySubsystemControllerProductID",
523 property);
524 }
525 else if (property.first == "VolatileRegionSizeLimitInKiB")
526 {
527 const uint64_t* value = std::get_if<uint64_t>(&property.second);
528
529 if (value == nullptr)
530 {
531 messages::internalError(aResp->res);
532 BMCWEB_LOG_DEBUG << "Invalid property type for "
533 "VolatileRegionSizeLimitKiB";
534 continue;
535 }
536 aResp->res.jsonValue["VolatileRegionSizeLimitMiB"] = (*value) >> 10;
537 }
538 else if (property.first == "PmRegionSizeLimitInKiB")
539 {
540 const uint64_t* value = std::get_if<uint64_t>(&property.second);
541
542 if (value == nullptr)
543 {
544 messages::internalError(aResp->res);
545 BMCWEB_LOG_DEBUG
546 << "Invalid property type for PmRegioSizeLimitKiB";
547 continue;
548 }
549 aResp->res.jsonValue["PersistentRegionSizeLimitMiB"] =
550 (*value) >> 10;
551 }
552 else if (property.first == "VolatileSizeInKiB")
553 {
554 const uint64_t* value = std::get_if<uint64_t>(&property.second);
555
556 if (value == nullptr)
557 {
558 messages::internalError(aResp->res);
559 BMCWEB_LOG_DEBUG
560 << "Invalid property type for VolatileSizeInKiB";
561 continue;
562 }
563 aResp->res.jsonValue["VolatileSizeMiB"] = (*value) >> 10;
564 }
565 else if (property.first == "PmSizeInKiB")
566 {
567 const uint64_t* value = std::get_if<uint64_t>(&property.second);
568 if (value == nullptr)
569 {
570 messages::internalError(aResp->res);
571 BMCWEB_LOG_DEBUG << "Invalid property type for PmSizeInKiB";
572 continue;
573 }
574 aResp->res.jsonValue["NonVolatileSizeMiB"] = (*value) >> 10;
575 }
576 else if (property.first == "CacheSizeInKB")
577 {
578 const uint64_t* value = std::get_if<uint64_t>(&property.second);
579 if (value == nullptr)
580 {
581 messages::internalError(aResp->res);
582 BMCWEB_LOG_DEBUG << "Invalid property type for CacheSizeInKB";
583 continue;
584 }
585 aResp->res.jsonValue["CacheSizeMiB"] = (*value >> 10);
586 }
587
588 else if (property.first == "VoltaileRegionMaxSizeInKib")
589 {
590 const uint64_t* value = std::get_if<uint64_t>(&property.second);
591
592 if (value == nullptr)
593 {
594 messages::internalError(aResp->res);
595 BMCWEB_LOG_DEBUG << "Invalid property type for "
596 "VolatileRegionMaxSizeInKib";
597 continue;
598 }
599 aResp->res.jsonValue["VolatileRegionSizeMaxMiB"] = (*value) >> 10;
600 }
601 else if (property.first == "PmRegionMaxSizeInKiB")
602 {
603 const uint64_t* value = std::get_if<uint64_t>(&property.second);
604
605 if (value == nullptr)
606 {
607 messages::internalError(aResp->res);
608 BMCWEB_LOG_DEBUG
609 << "Invalid property type for PmRegionMaxSizeInKiB";
610 continue;
611 }
612 aResp->res.jsonValue["PersistentRegionSizeMaxMiB"] = (*value) >> 10;
613 }
614 else if (property.first == "AllocationIncrementInKiB")
615 {
616 const uint64_t* value = std::get_if<uint64_t>(&property.second);
617
618 if (value == nullptr)
619 {
620 messages::internalError(aResp->res);
621 BMCWEB_LOG_DEBUG << "Invalid property type for "
622 "AllocationIncrementInKiB";
623 continue;
624 }
625 aResp->res.jsonValue["AllocationIncrementMiB"] = (*value) >> 10;
626 }
627 else if (property.first == "AllocationAlignmentInKiB")
628 {
629 const uint64_t* value = std::get_if<uint64_t>(&property.second);
630
631 if (value == nullptr)
632 {
633 messages::internalError(aResp->res);
634 BMCWEB_LOG_DEBUG << "Invalid property type for "
635 "AllocationAlignmentInKiB";
636 continue;
637 }
638 aResp->res.jsonValue["AllocationAlignmentMiB"] = (*value) >> 10;
639 }
640 else if (property.first == "VolatileRegionNumberLimit")
641 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700642 const uint64_t* value = std::get_if<uint64_t>(&property.second);
643 if (value == nullptr)
644 {
645 messages::internalError(aResp->res);
646 continue;
647 }
648 aResp->res.jsonValue["VolatileRegionNumberLimit"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700649 }
650 else if (property.first == "PmRegionNumberLimit")
651 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700652 const uint64_t* value = std::get_if<uint64_t>(&property.second);
653 if (value == nullptr)
654 {
655 messages::internalError(aResp->res);
656 continue;
657 }
658 aResp->res.jsonValue["PersistentRegionNumberLimit"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700659 }
660 else if (property.first == "SpareDeviceCount")
661 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700662 const uint64_t* value = std::get_if<uint64_t>(&property.second);
663 if (value == nullptr)
664 {
665 messages::internalError(aResp->res);
666 continue;
667 }
668 aResp->res.jsonValue["SpareDeviceCount"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700669 }
670 else if (property.first == "IsSpareDeviceInUse")
671 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700672 const bool* value = std::get_if<bool>(&property.second);
673 if (value == nullptr)
674 {
675 messages::internalError(aResp->res);
676 continue;
677 }
678 aResp->res.jsonValue["IsSpareDeviceEnabled"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700679 }
680 else if (property.first == "IsRankSpareEnabled")
681 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700682 const bool* value = std::get_if<bool>(&property.second);
683 if (value == nullptr)
684 {
685 messages::internalError(aResp->res);
686 continue;
687 }
688 aResp->res.jsonValue["IsRankSpareEnabled"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700689 }
690 else if (property.first == "MaxAveragePowerLimitmW")
691 {
692 const auto* value =
693 std::get_if<std::vector<uint32_t>>(&property.second);
694 if (value == nullptr)
695 {
696 messages::internalError(aResp->res);
697 BMCWEB_LOG_DEBUG << "Invalid property type for "
698 "MaxAveragePowerLimitmW";
699 continue;
700 }
701 aResp->res.jsonValue["MaxTDPMilliWatts"] = *value;
702 }
James Feistc50e7c62020-07-27 15:39:36 -0700703 else if (property.first == "ConfigurationLocked")
704 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700705 const bool* value = std::get_if<bool>(&property.second);
706 if (value == nullptr)
707 {
708 messages::internalError(aResp->res);
709 continue;
710 }
711 aResp->res.jsonValue["ConfigurationLocked"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700712 }
713 else if (property.first == "AllowedMemoryModes")
714 {
715 const std::string* value =
716 std::get_if<std::string>(&property.second);
717 if (value == nullptr)
718 {
719 messages::internalError(aResp->res);
720 BMCWEB_LOG_DEBUG << "Invalid property type for FormFactor";
721 continue;
722 }
723 constexpr const std::array<const char*, 3> values{"Volatile",
724 "PMEM", "Block"};
725
726 for (const char* v : values)
727 {
728 if (boost::ends_with(*value, v))
729 {
730 aResp->res.jsonValue["OperatingMemoryModes "] = v;
731 break;
732 }
733 }
734 }
735 else if (property.first == "MemoryMedia")
736 {
737 const std::string* value =
738 std::get_if<std::string>(&property.second);
739 if (value == nullptr)
740 {
741 messages::internalError(aResp->res);
742 BMCWEB_LOG_DEBUG << "Invalid property type for MemoryMedia";
743 continue;
744 }
745 constexpr const std::array<const char*, 3> values{"DRAM", "NAND",
746 "Intel3DXPoint"};
747
748 for (const char* v : values)
749 {
750 if (boost::ends_with(*value, v))
751 {
752 aResp->res.jsonValue["MemoryMedia"] = v;
753 break;
754 }
755 }
756 }
James Feistc50e7c62020-07-27 15:39:36 -0700757 // PersistantMemory.SecurityCapabilites interface
758 else if (property.first == "ConfigurationLockCapable" ||
759 property.first == "DataLockCapable" ||
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700760 property.first == "PassphraseCapable")
761 {
762 const bool* value = std::get_if<bool>(&property.second);
763 if (value == nullptr)
764 {
765 messages::internalError(aResp->res);
766 continue;
767 }
768 aResp->res.jsonValue["SecurityCapabilities"][property.first] =
769 *value;
770 }
771 else if (property.first == "MaxPassphraseCount" ||
James Feistc50e7c62020-07-27 15:39:36 -0700772 property.first == "PassphraseLockLimit")
773 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700774 const uint64_t* value = std::get_if<uint64_t>(&property.second);
775 if (value == nullptr)
776 {
777 messages::internalError(aResp->res);
778 continue;
779 }
James Feistc50e7c62020-07-27 15:39:36 -0700780 aResp->res.jsonValue["SecurityCapabilities"][property.first] =
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700781 *value;
James Feistc50e7c62020-07-27 15:39:36 -0700782 }
783 }
784}
785
Ed Tanous80789c82020-08-19 09:19:09 -0700786inline void getDimmDataByService(std::shared_ptr<AsyncResp> aResp,
787 const std::string& dimmId,
788 const std::string& service,
789 const std::string& objPath)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200790{
James Feist35e257a2020-06-05 13:30:51 -0700791 auto health = std::make_shared<HealthPopulate>(aResp);
792 health->selfPath = objPath;
793 health->populate();
794
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200795 BMCWEB_LOG_DEBUG << "Get available system components.";
796 crow::connections::systemBus->async_method_call(
James Feistc50e7c62020-07-27 15:39:36 -0700797 [dimmId, aResp{std::move(aResp)}](const boost::system::error_code ec,
798 const DimmProperties& properties) {
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200799 if (ec)
800 {
801 BMCWEB_LOG_DEBUG << "DBUS response error";
802 messages::internalError(aResp->res);
803
804 return;
805 }
806 aResp->res.jsonValue["Id"] = dimmId;
807 aResp->res.jsonValue["Name"] = "DIMM Slot";
808
809 const auto memorySizeProperty = properties.find("MemorySizeInKB");
Gunnar Millsaceb7fc2018-12-10 15:17:20 -0600810 if (memorySizeProperty != properties.end())
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200811 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500812 const uint32_t* memorySize =
Ed Tanousabf2add2019-01-22 16:40:12 -0800813 std::get_if<uint32_t>(&memorySizeProperty->second);
Gunnar Millsaceb7fc2018-12-10 15:17:20 -0600814 if (memorySize == nullptr)
815 {
816 // Important property not in desired type
817 messages::internalError(aResp->res);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200818
Gunnar Millsaceb7fc2018-12-10 15:17:20 -0600819 return;
820 }
821 if (*memorySize == 0)
822 {
823 // Slot is not populated, set status end return
824 aResp->res.jsonValue["Status"]["State"] = "Absent";
825 aResp->res.jsonValue["Status"]["Health"] = "OK";
826 // HTTP Code will be set up automatically, just return
827 return;
828 }
829 aResp->res.jsonValue["CapacityMiB"] = (*memorySize >> 10);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200830 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200831 aResp->res.jsonValue["Status"]["State"] = "Enabled";
832 aResp->res.jsonValue["Status"]["Health"] = "OK";
833
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500834 for (const auto& property : properties)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200835 {
836 if (property.first == "MemoryDataWidth")
837 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700838 const uint16_t* value =
839 std::get_if<uint16_t>(&property.second);
840 if (value == nullptr)
841 {
842 continue;
843 }
844 aResp->res.jsonValue["DataWidthBits"] = *value;
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200845 }
Manojkiran Eda7e236ca2019-06-25 23:06:32 +0530846 else if (property.first == "PartNumber")
847 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700848 const std::string* value =
849 std::get_if<std::string>(&property.second);
850 if (value == nullptr)
851 {
852 continue;
853 }
854 aResp->res.jsonValue["PartNumber"] = *value;
Manojkiran Eda7e236ca2019-06-25 23:06:32 +0530855 }
856 else if (property.first == "SerialNumber")
857 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700858 const std::string* value =
859 std::get_if<std::string>(&property.second);
860 if (value == nullptr)
861 {
862 continue;
863 }
864 aResp->res.jsonValue["SerialNumber"] = *value;
Manojkiran Eda7e236ca2019-06-25 23:06:32 +0530865 }
866 else if (property.first == "Manufacturer")
867 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700868 const std::string* value =
869 std::get_if<std::string>(&property.second);
870 if (value == nullptr)
871 {
872 continue;
873 }
874 aResp->res.jsonValue["Manufacturer"] = *value;
Manojkiran Eda7e236ca2019-06-25 23:06:32 +0530875 }
James Feistc50e7c62020-07-27 15:39:36 -0700876 else if (property.first == "RevisionCode")
877 {
878 const uint16_t* value =
879 std::get_if<uint16_t>(&property.second);
880
881 if (value == nullptr)
882 {
883 messages::internalError(aResp->res);
884 BMCWEB_LOG_DEBUG
885 << "Invalid property type for RevisionCode";
886 continue;
887 }
888 aResp->res.jsonValue["FirmwareRevision"] =
889 std::to_string(*value);
890 }
891 else if (property.first == "MemoryTotalWidth")
892 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700893 const uint16_t* value =
894 std::get_if<uint16_t>(&property.second);
895 if (value == nullptr)
896 {
897 continue;
898 }
899 aResp->res.jsonValue["BusWidthBits"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700900 }
901 else if (property.first == "ECC")
902 {
903 const std::string* value =
904 std::get_if<std::string>(&property.second);
905 if (value == nullptr)
906 {
907 messages::internalError(aResp->res);
908 BMCWEB_LOG_DEBUG << "Invalid property type for ECC";
909 continue;
910 }
911 constexpr const std::array<const char*, 4> values{
912 "NoECC", "SingleBitECC", "MultiBitECC",
913 "AddressParity"};
914
915 for (const char* v : values)
916 {
917 if (boost::ends_with(*value, v))
918 {
919 aResp->res.jsonValue["ErrorCorrection"] = v;
920 break;
921 }
922 }
923 }
924 else if (property.first == "FormFactor")
925 {
926 const std::string* value =
927 std::get_if<std::string>(&property.second);
928 if (value == nullptr)
929 {
930 messages::internalError(aResp->res);
931 BMCWEB_LOG_DEBUG
932 << "Invalid property type for FormFactor";
933 continue;
934 }
935 constexpr const std::array<const char*, 11> values{
936 "RDIMM", "UDIMM", "SO_DIMM",
937 "LRDIMM", "Mini_RDIMM", "Mini_UDIMM",
938 "SO_RDIMM_72b", "SO_UDIMM_72b", "SO_DIMM_16b",
939 "SO_DIMM_32b", "Die"};
940
941 for (const char* v : values)
942 {
943 if (boost::ends_with(*value, v))
944 {
945 aResp->res.jsonValue["BaseModuleType"] = v;
946 break;
947 }
948 }
949 }
950 else if (property.first == "AllowedSpeedsMT")
951 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700952 const std::vector<uint16_t>* value =
953 std::get_if<std::vector<uint16_t>>(&property.second);
954 if (value == nullptr)
955 {
956 continue;
957 }
958 nlohmann::json& jValue =
959 aResp->res.jsonValue["AllowedSpeedsMHz"];
960 jValue = nlohmann::json::array();
961 for (uint16_t subVal : *value)
962 {
963 jValue.push_back(subVal);
964 }
James Feistc50e7c62020-07-27 15:39:36 -0700965 }
966 else if (property.first == "MemoryAttributes")
967 {
968 const uint8_t* value =
969 std::get_if<uint8_t>(&property.second);
970
971 if (value == nullptr)
972 {
973 messages::internalError(aResp->res);
974 BMCWEB_LOG_DEBUG
975 << "Invalid property type for MemoryAttributes";
976 continue;
977 }
978 aResp->res.jsonValue["RankCount"] =
979 static_cast<uint64_t>(*value);
980 }
981 else if (property.first == "MemoryConfiguredSpeedInMhz")
982 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700983 const uint16_t* value =
984 std::get_if<uint16_t>(&property.second);
985 if (value == nullptr)
986 {
987 continue;
988 }
989 aResp->res.jsonValue["OperatingSpeedMhz"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700990 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200991 else if (property.first == "MemoryType")
992 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500993 const auto* value =
Ed Tanousabf2add2019-01-22 16:40:12 -0800994 std::get_if<std::string>(&property.second);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200995 if (value != nullptr)
996 {
James Feistc50e7c62020-07-27 15:39:36 -0700997 size_t idx = value->rfind(".");
998 if (idx == std::string::npos ||
999 idx + 1 >= value->size())
1000 {
1001 messages::internalError(aResp->res);
1002 BMCWEB_LOG_DEBUG << "Invalid property type for "
1003 "MemoryType";
1004 }
1005 std::string result = value->substr(idx + 1);
1006 aResp->res.jsonValue["MemoryDeviceType"] = result;
1007 if (value->find("DDR") != std::string::npos)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001008 {
1009 aResp->res.jsonValue["MemoryType"] = "DRAM";
1010 }
James Feistc50e7c62020-07-27 15:39:36 -07001011 else if (boost::ends_with(*value, "Logical"))
1012 {
1013 aResp->res.jsonValue["MemoryType"] = "IntelOptane";
1014 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001015 }
1016 }
James Feistc50e7c62020-07-27 15:39:36 -07001017 // memory location interface
1018 else if (property.first == "Channel" ||
1019 property.first == "MemoryController" ||
1020 property.first == "Slot" || property.first == "Socket")
1021 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -07001022 const std::string* value =
1023 std::get_if<std::string>(&property.second);
1024 if (value == nullptr)
1025 {
1026 messages::internalError(aResp->res);
1027 continue;
1028 }
James Feistc50e7c62020-07-27 15:39:36 -07001029 aResp->res.jsonValue["MemoryLocation"][property.first] =
Ed Tanous5fb91ba2020-09-28 15:41:28 -07001030 *value;
James Feistc50e7c62020-07-27 15:39:36 -07001031 }
1032 else
1033 {
1034 getPersistentMemoryProperties(aResp, properties);
1035 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001036 }
1037 },
1038 service, objPath, "org.freedesktop.DBus.Properties", "GetAll", "");
1039}
1040
Ed Tanous23a21a12020-07-25 04:45:05 +00001041inline void getDimmPartitionData(std::shared_ptr<AsyncResp> aResp,
1042 const std::string& service,
1043 const std::string& path)
James Feist45094ad2020-04-29 14:02:30 -07001044{
1045 crow::connections::systemBus->async_method_call(
1046 [aResp{std::move(aResp)}](
1047 const boost::system::error_code ec,
1048 const boost::container::flat_map<
1049 std::string, std::variant<std::string, uint64_t, uint32_t,
1050 bool>>& properties) {
1051 if (ec)
1052 {
1053 BMCWEB_LOG_DEBUG << "DBUS response error";
1054 messages::internalError(aResp->res);
1055
1056 return;
1057 }
1058
1059 nlohmann::json& partition =
1060 aResp->res.jsonValue["Regions"].emplace_back(
1061 nlohmann::json::object());
1062 for (const auto& [key, val] : properties)
1063 {
1064 if (key == "MemoryClassification")
1065 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -07001066 const std::string* value = std::get_if<std::string>(&val);
1067 if (value == nullptr)
1068 {
1069 messages::internalError(aResp->res);
1070 continue;
1071 }
1072 partition[key] = *value;
James Feist45094ad2020-04-29 14:02:30 -07001073 }
1074 else if (key == "OffsetInKiB")
1075 {
1076 const uint64_t* value = std::get_if<uint64_t>(&val);
1077 if (value == nullptr)
1078 {
1079 messages::internalError(aResp->res);
James Feist45094ad2020-04-29 14:02:30 -07001080 continue;
1081 }
1082
1083 partition["OffsetMiB"] = (*value >> 10);
1084 }
1085 else if (key == "PartitionId")
1086 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -07001087 const std::string* value = std::get_if<std::string>(&val);
1088 if (value == nullptr)
1089 {
1090 messages::internalError(aResp->res);
1091 continue;
1092 }
1093 partition["RegionId"] = *value;
James Feist45094ad2020-04-29 14:02:30 -07001094 }
1095
1096 else if (key == "PassphraseState")
1097 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -07001098 const bool* value = std::get_if<bool>(&val);
1099 if (value == nullptr)
1100 {
1101 messages::internalError(aResp->res);
1102 continue;
1103 }
1104 partition["PassphraseEnabled"] = *value;
James Feist45094ad2020-04-29 14:02:30 -07001105 }
1106 else if (key == "SizeInKiB")
1107 {
1108 const uint64_t* value = std::get_if<uint64_t>(&val);
1109 if (value == nullptr)
1110 {
1111 messages::internalError(aResp->res);
1112 BMCWEB_LOG_DEBUG
1113 << "Invalid property type for SizeInKiB";
1114 continue;
1115 }
1116 partition["SizeMiB"] = (*value >> 10);
1117 }
1118 }
1119 },
1120
1121 service, path, "org.freedesktop.DBus.Properties", "GetAll",
1122 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition");
1123}
1124
Ed Tanous23a21a12020-07-25 04:45:05 +00001125inline void getDimmData(std::shared_ptr<AsyncResp> aResp,
1126 const std::string& dimmId)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001127{
1128 BMCWEB_LOG_DEBUG << "Get available system dimm resources.";
1129 crow::connections::systemBus->async_method_call(
Ed Tanous029573d2019-02-01 10:57:49 -08001130 [dimmId, aResp{std::move(aResp)}](
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001131 const boost::system::error_code ec,
1132 const boost::container::flat_map<
1133 std::string, boost::container::flat_map<
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001134 std::string, std::vector<std::string>>>&
1135 subtree) {
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001136 if (ec)
1137 {
1138 BMCWEB_LOG_DEBUG << "DBUS response error";
1139 messages::internalError(aResp->res);
1140
1141 return;
1142 }
James Feist45094ad2020-04-29 14:02:30 -07001143 bool found = false;
1144 for (const auto& [path, object] : subtree)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001145 {
James Feist45094ad2020-04-29 14:02:30 -07001146 if (path.find(dimmId) != std::string::npos)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001147 {
James Feist45094ad2020-04-29 14:02:30 -07001148 for (const auto& [service, interfaces] : object)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001149 {
James Feist45094ad2020-04-29 14:02:30 -07001150 if (!found &&
1151 (std::find(
1152 interfaces.begin(), interfaces.end(),
1153 "xyz.openbmc_project.Inventory.Item.Dimm") !=
1154 interfaces.end()))
1155 {
1156 getDimmDataByService(aResp, dimmId, service, path);
1157 found = true;
1158 }
1159
1160 // partitions are separate as there can be multiple per
1161 // device, i.e.
1162 // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition1
1163 // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition2
1164 if (std::find(interfaces.begin(), interfaces.end(),
1165 "xyz.openbmc_project.Inventory.Item."
1166 "PersistentMemory.Partition") !=
1167 interfaces.end())
1168 {
1169 getDimmPartitionData(aResp, service, path);
1170 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001171 }
1172 }
1173 }
1174 // Object not found
James Feist45094ad2020-04-29 14:02:30 -07001175 if (!found)
1176 {
1177 messages::resourceNotFound(aResp->res, "Memory", dimmId);
1178 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001179 return;
1180 },
1181 "xyz.openbmc_project.ObjectMapper",
1182 "/xyz/openbmc_project/object_mapper",
1183 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous271584a2019-07-09 16:24:22 -07001184 "/xyz/openbmc_project/inventory", 0,
James Feist45094ad2020-04-29 14:02:30 -07001185 std::array<const char*, 2>{
1186 "xyz.openbmc_project.Inventory.Item.Dimm",
1187 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition"});
Ed Tanous271584a2019-07-09 16:24:22 -07001188}
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001189
1190class ProcessorCollection : public Node
1191{
1192 public:
1193 /*
1194 * Default Constructor
1195 */
Ed Tanous52cc1122020-07-18 13:51:21 -07001196 ProcessorCollection(App& app) :
Ed Tanous029573d2019-02-01 10:57:49 -08001197 Node(app, "/redfish/v1/Systems/system/Processors/")
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001198 {
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001199 entityPrivileges = {
1200 {boost::beast::http::verb::get, {{"Login"}}},
1201 {boost::beast::http::verb::head, {{"Login"}}},
1202 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
1203 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
1204 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
1205 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
1206 }
1207
1208 private:
1209 /**
1210 * Functions triggers appropriate requests on DBus
1211 */
Ed Tanouscb13a392020-07-25 19:02:03 +00001212 void doGet(crow::Response& res, const crow::Request&,
1213 const std::vector<std::string>&) override
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001214 {
Ed Tanous0f74e642018-11-12 15:17:05 -08001215 res.jsonValue["@odata.type"] =
1216 "#ProcessorCollection.ProcessorCollection";
1217 res.jsonValue["Name"] = "Processor Collection";
Ed Tanous0f74e642018-11-12 15:17:05 -08001218
Ed Tanous029573d2019-02-01 10:57:49 -08001219 res.jsonValue["@odata.id"] = "/redfish/v1/Systems/system/Processors/";
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001220 auto asyncResp = std::make_shared<AsyncResp>(res);
1221
Ed Tanous029573d2019-02-01 10:57:49 -08001222 getResourceList(asyncResp, "Processors",
Alpana Kumari32bee762019-04-25 04:47:57 -05001223 {"xyz.openbmc_project.Inventory.Item.Cpu",
1224 "xyz.openbmc_project.Inventory.Item.Accelerator"});
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001225 }
1226};
1227
1228class Processor : public Node
1229{
1230 public:
1231 /*
1232 * Default Constructor
1233 */
Ed Tanous52cc1122020-07-18 13:51:21 -07001234 Processor(App& app) :
Ed Tanous029573d2019-02-01 10:57:49 -08001235 Node(app, "/redfish/v1/Systems/system/Processors/<str>/", std::string())
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001236 {
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001237 entityPrivileges = {
1238 {boost::beast::http::verb::get, {{"Login"}}},
1239 {boost::beast::http::verb::head, {{"Login"}}},
1240 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
1241 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
1242 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
1243 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
1244 }
1245
1246 private:
1247 /**
1248 * Functions triggers appropriate requests on DBus
1249 */
Ed Tanouscb13a392020-07-25 19:02:03 +00001250 void doGet(crow::Response& res, const crow::Request&,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001251 const std::vector<std::string>& params) override
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001252 {
1253 // Check if there is required param, truly entering this shall be
1254 // impossible
1255 if (params.size() != 1)
1256 {
1257 messages::internalError(res);
1258
1259 res.end();
1260 return;
1261 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001262 const std::string& processorId = params[0];
Zhikui Ren029cc1f2020-08-25 15:21:41 -07001263 res.jsonValue["@odata.type"] = "#Processor.v1_9_0.Processor";
Ed Tanous029573d2019-02-01 10:57:49 -08001264 res.jsonValue["@odata.id"] =
Alpana Kumari32bee762019-04-25 04:47:57 -05001265 "/redfish/v1/Systems/system/Processors/" + processorId;
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001266
Ed Tanous029573d2019-02-01 10:57:49 -08001267 auto asyncResp = std::make_shared<AsyncResp>(res);
1268
Gunnar Millse851f8a2020-10-14 14:36:13 -05001269 getProcessorData(asyncResp, processorId,
1270 {"xyz.openbmc_project.Inventory.Item.Cpu",
1271 "xyz.openbmc_project.Inventory.Decorator.Asset",
1272 "xyz.openbmc_project.Inventory.Item.Accelerator"});
Ed Tanous029573d2019-02-01 10:57:49 -08001273 }
1274};
1275
1276class MemoryCollection : public Node
1277{
1278 public:
1279 /*
1280 * Default Constructor
1281 */
Ed Tanous52cc1122020-07-18 13:51:21 -07001282 MemoryCollection(App& app) : Node(app, "/redfish/v1/Systems/system/Memory/")
Ed Tanous029573d2019-02-01 10:57:49 -08001283 {
1284 entityPrivileges = {
1285 {boost::beast::http::verb::get, {{"Login"}}},
1286 {boost::beast::http::verb::head, {{"Login"}}},
1287 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
1288 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
1289 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
1290 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
1291 }
1292
1293 private:
1294 /**
1295 * Functions triggers appropriate requests on DBus
1296 */
Ed Tanouscb13a392020-07-25 19:02:03 +00001297 void doGet(crow::Response& res, const crow::Request&,
1298 const std::vector<std::string>&) override
Ed Tanous029573d2019-02-01 10:57:49 -08001299 {
Ed Tanous0f74e642018-11-12 15:17:05 -08001300 res.jsonValue["@odata.type"] = "#MemoryCollection.MemoryCollection";
1301 res.jsonValue["Name"] = "Memory Module Collection";
James Feistc50e7c62020-07-27 15:39:36 -07001302 res.jsonValue["@odata.id"] = "/redfish/v1/Systems/system/Memory";
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001303 auto asyncResp = std::make_shared<AsyncResp>(res);
1304
Ed Tanous029573d2019-02-01 10:57:49 -08001305 getResourceList(asyncResp, "Memory",
Alpana Kumari32bee762019-04-25 04:47:57 -05001306 {"xyz.openbmc_project.Inventory.Item.Dimm"});
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001307 }
1308};
1309
1310class Memory : public Node
1311{
1312 public:
1313 /*
1314 * Default Constructor
1315 */
Ed Tanous52cc1122020-07-18 13:51:21 -07001316 Memory(App& app) :
Ed Tanous029573d2019-02-01 10:57:49 -08001317 Node(app, "/redfish/v1/Systems/system/Memory/<str>/", std::string())
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001318 {
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001319 entityPrivileges = {
1320 {boost::beast::http::verb::get, {{"Login"}}},
1321 {boost::beast::http::verb::head, {{"Login"}}},
1322 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
1323 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
1324 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
1325 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
1326 }
1327
1328 private:
1329 /**
1330 * Functions triggers appropriate requests on DBus
1331 */
Ed Tanouscb13a392020-07-25 19:02:03 +00001332 void doGet(crow::Response& res, const crow::Request&,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001333 const std::vector<std::string>& params) override
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001334 {
1335 // Check if there is required param, truly entering this shall be
1336 // impossible
Ed Tanous029573d2019-02-01 10:57:49 -08001337 if (params.size() != 1)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001338 {
1339 messages::internalError(res);
1340 res.end();
1341 return;
1342 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001343 const std::string& dimmId = params[0];
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001344
James Feistc50e7c62020-07-27 15:39:36 -07001345 res.jsonValue["@odata.type"] = "#Memory.v1_7_0.Memory";
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001346 res.jsonValue["@odata.id"] =
Ed Tanous029573d2019-02-01 10:57:49 -08001347 "/redfish/v1/Systems/system/Memory/" + dimmId;
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001348 auto asyncResp = std::make_shared<AsyncResp>(res);
1349
Ed Tanous029573d2019-02-01 10:57:49 -08001350 getDimmData(asyncResp, dimmId);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001351 }
1352};
1353
1354} // namespace redfish