blob: 7a306a357a07fb3f45c7aa2dd6043302abd84d14 [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
Ed Tanous23a21a12020-07-25 04:45:05 +0000411inline void getCpuData(std::shared_ptr<AsyncResp> aResp,
412 const std::string& cpuId,
Ed Tanousb5a76932020-09-29 16:16:58 -0700413 const std::vector<const char*>& inventoryItems)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200414{
415 BMCWEB_LOG_DEBUG << "Get available system cpu resources.";
Alpana Kumari32bee762019-04-25 04:47:57 -0500416
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200417 crow::connections::systemBus->async_method_call(
Ed Tanous029573d2019-02-01 10:57:49 -0800418 [cpuId, 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 {
432 if (boost::ends_with(object.first, cpuId))
433 {
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 {
454 getCpuDataByService(aResp, cpuId, service.first,
455 object.first);
456 }
457 else if (inventory == "xyz.openbmc_project."
458 "Inventory.Item.Accelerator")
459 {
460 getAcceleratorDataByService(
461 aResp, cpuId, service.first, object.first);
462 }
Zhikui Ren5e54a362020-07-13 15:31:38 -0700463 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200464 }
Zhikui Ren5e54a362020-07-13 15:31:38 -0700465 return;
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200466 }
467 }
468 // Object not found
469 messages::resourceNotFound(aResp->res, "Processor", cpuId);
470 return;
471 },
472 "xyz.openbmc_project.ObjectMapper",
473 "/xyz/openbmc_project/object_mapper",
474 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous271584a2019-07-09 16:24:22 -0700475 "/xyz/openbmc_project/inventory", 0, inventoryItems);
476}
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200477
James Feistc50e7c62020-07-27 15:39:36 -0700478using DimmProperty =
479 std::variant<std::string, std::vector<uint32_t>, std::vector<uint16_t>,
480 uint64_t, uint32_t, uint16_t, uint8_t, bool>;
481
482using DimmProperties = boost::container::flat_map<std::string, DimmProperty>;
483
Ed Tanousb5a76932020-09-29 16:16:58 -0700484inline void dimmPropToHex(const std::shared_ptr<AsyncResp>& aResp,
485 const char* key,
Ed Tanous80789c82020-08-19 09:19:09 -0700486 const std::pair<std::string, DimmProperty>& property)
James Feistc50e7c62020-07-27 15:39:36 -0700487{
488 const uint16_t* value = std::get_if<uint16_t>(&property.second);
489 if (value == nullptr)
490 {
491 messages::internalError(aResp->res);
492 BMCWEB_LOG_DEBUG << "Invalid property type for " << property.first;
493 return;
494 }
495
496 aResp->res.jsonValue[key] = (boost::format("0x%04x") % *value).str();
497}
498
Ed Tanousb5a76932020-09-29 16:16:58 -0700499inline void
500 getPersistentMemoryProperties(const std::shared_ptr<AsyncResp>& aResp,
501 const DimmProperties& properties)
James Feistc50e7c62020-07-27 15:39:36 -0700502{
503 for (const auto& property : properties)
504 {
505 if (property.first == "ModuleManufacturerID")
506 {
507 dimmPropToHex(aResp, "ModuleManufacturerID", property);
508 }
509 else if (property.first == "ModuleProductID")
510 {
511 dimmPropToHex(aResp, "ModuleProductID", property);
512 }
513 else if (property.first == "SubsystemVendorID")
514 {
515 dimmPropToHex(aResp, "MemorySubsystemControllerManufacturerID",
516 property);
517 }
518 else if (property.first == "SubsystemDeviceID")
519 {
520 dimmPropToHex(aResp, "MemorySubsystemControllerProductID",
521 property);
522 }
523 else if (property.first == "VolatileRegionSizeLimitInKiB")
524 {
525 const uint64_t* value = std::get_if<uint64_t>(&property.second);
526
527 if (value == nullptr)
528 {
529 messages::internalError(aResp->res);
530 BMCWEB_LOG_DEBUG << "Invalid property type for "
531 "VolatileRegionSizeLimitKiB";
532 continue;
533 }
534 aResp->res.jsonValue["VolatileRegionSizeLimitMiB"] = (*value) >> 10;
535 }
536 else if (property.first == "PmRegionSizeLimitInKiB")
537 {
538 const uint64_t* value = std::get_if<uint64_t>(&property.second);
539
540 if (value == nullptr)
541 {
542 messages::internalError(aResp->res);
543 BMCWEB_LOG_DEBUG
544 << "Invalid property type for PmRegioSizeLimitKiB";
545 continue;
546 }
547 aResp->res.jsonValue["PersistentRegionSizeLimitMiB"] =
548 (*value) >> 10;
549 }
550 else if (property.first == "VolatileSizeInKiB")
551 {
552 const uint64_t* value = std::get_if<uint64_t>(&property.second);
553
554 if (value == nullptr)
555 {
556 messages::internalError(aResp->res);
557 BMCWEB_LOG_DEBUG
558 << "Invalid property type for VolatileSizeInKiB";
559 continue;
560 }
561 aResp->res.jsonValue["VolatileSizeMiB"] = (*value) >> 10;
562 }
563 else if (property.first == "PmSizeInKiB")
564 {
565 const uint64_t* value = std::get_if<uint64_t>(&property.second);
566 if (value == nullptr)
567 {
568 messages::internalError(aResp->res);
569 BMCWEB_LOG_DEBUG << "Invalid property type for PmSizeInKiB";
570 continue;
571 }
572 aResp->res.jsonValue["NonVolatileSizeMiB"] = (*value) >> 10;
573 }
574 else if (property.first == "CacheSizeInKB")
575 {
576 const uint64_t* value = std::get_if<uint64_t>(&property.second);
577 if (value == nullptr)
578 {
579 messages::internalError(aResp->res);
580 BMCWEB_LOG_DEBUG << "Invalid property type for CacheSizeInKB";
581 continue;
582 }
583 aResp->res.jsonValue["CacheSizeMiB"] = (*value >> 10);
584 }
585
586 else if (property.first == "VoltaileRegionMaxSizeInKib")
587 {
588 const uint64_t* value = std::get_if<uint64_t>(&property.second);
589
590 if (value == nullptr)
591 {
592 messages::internalError(aResp->res);
593 BMCWEB_LOG_DEBUG << "Invalid property type for "
594 "VolatileRegionMaxSizeInKib";
595 continue;
596 }
597 aResp->res.jsonValue["VolatileRegionSizeMaxMiB"] = (*value) >> 10;
598 }
599 else if (property.first == "PmRegionMaxSizeInKiB")
600 {
601 const uint64_t* value = std::get_if<uint64_t>(&property.second);
602
603 if (value == nullptr)
604 {
605 messages::internalError(aResp->res);
606 BMCWEB_LOG_DEBUG
607 << "Invalid property type for PmRegionMaxSizeInKiB";
608 continue;
609 }
610 aResp->res.jsonValue["PersistentRegionSizeMaxMiB"] = (*value) >> 10;
611 }
612 else if (property.first == "AllocationIncrementInKiB")
613 {
614 const uint64_t* value = std::get_if<uint64_t>(&property.second);
615
616 if (value == nullptr)
617 {
618 messages::internalError(aResp->res);
619 BMCWEB_LOG_DEBUG << "Invalid property type for "
620 "AllocationIncrementInKiB";
621 continue;
622 }
623 aResp->res.jsonValue["AllocationIncrementMiB"] = (*value) >> 10;
624 }
625 else if (property.first == "AllocationAlignmentInKiB")
626 {
627 const uint64_t* value = std::get_if<uint64_t>(&property.second);
628
629 if (value == nullptr)
630 {
631 messages::internalError(aResp->res);
632 BMCWEB_LOG_DEBUG << "Invalid property type for "
633 "AllocationAlignmentInKiB";
634 continue;
635 }
636 aResp->res.jsonValue["AllocationAlignmentMiB"] = (*value) >> 10;
637 }
638 else if (property.first == "VolatileRegionNumberLimit")
639 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700640 const uint64_t* value = std::get_if<uint64_t>(&property.second);
641 if (value == nullptr)
642 {
643 messages::internalError(aResp->res);
644 continue;
645 }
646 aResp->res.jsonValue["VolatileRegionNumberLimit"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700647 }
648 else if (property.first == "PmRegionNumberLimit")
649 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700650 const uint64_t* value = std::get_if<uint64_t>(&property.second);
651 if (value == nullptr)
652 {
653 messages::internalError(aResp->res);
654 continue;
655 }
656 aResp->res.jsonValue["PersistentRegionNumberLimit"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700657 }
658 else if (property.first == "SpareDeviceCount")
659 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700660 const uint64_t* value = std::get_if<uint64_t>(&property.second);
661 if (value == nullptr)
662 {
663 messages::internalError(aResp->res);
664 continue;
665 }
666 aResp->res.jsonValue["SpareDeviceCount"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700667 }
668 else if (property.first == "IsSpareDeviceInUse")
669 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700670 const bool* value = std::get_if<bool>(&property.second);
671 if (value == nullptr)
672 {
673 messages::internalError(aResp->res);
674 continue;
675 }
676 aResp->res.jsonValue["IsSpareDeviceEnabled"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700677 }
678 else if (property.first == "IsRankSpareEnabled")
679 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700680 const bool* value = std::get_if<bool>(&property.second);
681 if (value == nullptr)
682 {
683 messages::internalError(aResp->res);
684 continue;
685 }
686 aResp->res.jsonValue["IsRankSpareEnabled"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700687 }
688 else if (property.first == "MaxAveragePowerLimitmW")
689 {
690 const auto* value =
691 std::get_if<std::vector<uint32_t>>(&property.second);
692 if (value == nullptr)
693 {
694 messages::internalError(aResp->res);
695 BMCWEB_LOG_DEBUG << "Invalid property type for "
696 "MaxAveragePowerLimitmW";
697 continue;
698 }
699 aResp->res.jsonValue["MaxTDPMilliWatts"] = *value;
700 }
James Feistc50e7c62020-07-27 15:39:36 -0700701 else if (property.first == "ConfigurationLocked")
702 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700703 const bool* value = std::get_if<bool>(&property.second);
704 if (value == nullptr)
705 {
706 messages::internalError(aResp->res);
707 continue;
708 }
709 aResp->res.jsonValue["ConfigurationLocked"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700710 }
711 else if (property.first == "AllowedMemoryModes")
712 {
713 const std::string* value =
714 std::get_if<std::string>(&property.second);
715 if (value == nullptr)
716 {
717 messages::internalError(aResp->res);
718 BMCWEB_LOG_DEBUG << "Invalid property type for FormFactor";
719 continue;
720 }
721 constexpr const std::array<const char*, 3> values{"Volatile",
722 "PMEM", "Block"};
723
724 for (const char* v : values)
725 {
726 if (boost::ends_with(*value, v))
727 {
728 aResp->res.jsonValue["OperatingMemoryModes "] = v;
729 break;
730 }
731 }
732 }
733 else if (property.first == "MemoryMedia")
734 {
735 const std::string* value =
736 std::get_if<std::string>(&property.second);
737 if (value == nullptr)
738 {
739 messages::internalError(aResp->res);
740 BMCWEB_LOG_DEBUG << "Invalid property type for MemoryMedia";
741 continue;
742 }
743 constexpr const std::array<const char*, 3> values{"DRAM", "NAND",
744 "Intel3DXPoint"};
745
746 for (const char* v : values)
747 {
748 if (boost::ends_with(*value, v))
749 {
750 aResp->res.jsonValue["MemoryMedia"] = v;
751 break;
752 }
753 }
754 }
James Feistc50e7c62020-07-27 15:39:36 -0700755 // PersistantMemory.SecurityCapabilites interface
756 else if (property.first == "ConfigurationLockCapable" ||
757 property.first == "DataLockCapable" ||
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700758 property.first == "PassphraseCapable")
759 {
760 const bool* value = std::get_if<bool>(&property.second);
761 if (value == nullptr)
762 {
763 messages::internalError(aResp->res);
764 continue;
765 }
766 aResp->res.jsonValue["SecurityCapabilities"][property.first] =
767 *value;
768 }
769 else if (property.first == "MaxPassphraseCount" ||
James Feistc50e7c62020-07-27 15:39:36 -0700770 property.first == "PassphraseLockLimit")
771 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700772 const uint64_t* value = std::get_if<uint64_t>(&property.second);
773 if (value == nullptr)
774 {
775 messages::internalError(aResp->res);
776 continue;
777 }
James Feistc50e7c62020-07-27 15:39:36 -0700778 aResp->res.jsonValue["SecurityCapabilities"][property.first] =
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700779 *value;
James Feistc50e7c62020-07-27 15:39:36 -0700780 }
781 }
782}
783
Ed Tanous80789c82020-08-19 09:19:09 -0700784inline void getDimmDataByService(std::shared_ptr<AsyncResp> aResp,
785 const std::string& dimmId,
786 const std::string& service,
787 const std::string& objPath)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200788{
James Feist35e257a2020-06-05 13:30:51 -0700789 auto health = std::make_shared<HealthPopulate>(aResp);
790 health->selfPath = objPath;
791 health->populate();
792
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200793 BMCWEB_LOG_DEBUG << "Get available system components.";
794 crow::connections::systemBus->async_method_call(
James Feistc50e7c62020-07-27 15:39:36 -0700795 [dimmId, aResp{std::move(aResp)}](const boost::system::error_code ec,
796 const DimmProperties& properties) {
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200797 if (ec)
798 {
799 BMCWEB_LOG_DEBUG << "DBUS response error";
800 messages::internalError(aResp->res);
801
802 return;
803 }
804 aResp->res.jsonValue["Id"] = dimmId;
805 aResp->res.jsonValue["Name"] = "DIMM Slot";
806
807 const auto memorySizeProperty = properties.find("MemorySizeInKB");
Gunnar Millsaceb7fc2018-12-10 15:17:20 -0600808 if (memorySizeProperty != properties.end())
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200809 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500810 const uint32_t* memorySize =
Ed Tanousabf2add2019-01-22 16:40:12 -0800811 std::get_if<uint32_t>(&memorySizeProperty->second);
Gunnar Millsaceb7fc2018-12-10 15:17:20 -0600812 if (memorySize == nullptr)
813 {
814 // Important property not in desired type
815 messages::internalError(aResp->res);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200816
Gunnar Millsaceb7fc2018-12-10 15:17:20 -0600817 return;
818 }
819 if (*memorySize == 0)
820 {
821 // Slot is not populated, set status end return
822 aResp->res.jsonValue["Status"]["State"] = "Absent";
823 aResp->res.jsonValue["Status"]["Health"] = "OK";
824 // HTTP Code will be set up automatically, just return
825 return;
826 }
827 aResp->res.jsonValue["CapacityMiB"] = (*memorySize >> 10);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200828 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200829 aResp->res.jsonValue["Status"]["State"] = "Enabled";
830 aResp->res.jsonValue["Status"]["Health"] = "OK";
831
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500832 for (const auto& property : properties)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200833 {
834 if (property.first == "MemoryDataWidth")
835 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700836 const uint16_t* value =
837 std::get_if<uint16_t>(&property.second);
838 if (value == nullptr)
839 {
840 continue;
841 }
842 aResp->res.jsonValue["DataWidthBits"] = *value;
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200843 }
Manojkiran Eda7e236ca2019-06-25 23:06:32 +0530844 else if (property.first == "PartNumber")
845 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700846 const std::string* value =
847 std::get_if<std::string>(&property.second);
848 if (value == nullptr)
849 {
850 continue;
851 }
852 aResp->res.jsonValue["PartNumber"] = *value;
Manojkiran Eda7e236ca2019-06-25 23:06:32 +0530853 }
854 else if (property.first == "SerialNumber")
855 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700856 const std::string* value =
857 std::get_if<std::string>(&property.second);
858 if (value == nullptr)
859 {
860 continue;
861 }
862 aResp->res.jsonValue["SerialNumber"] = *value;
Manojkiran Eda7e236ca2019-06-25 23:06:32 +0530863 }
864 else if (property.first == "Manufacturer")
865 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700866 const std::string* value =
867 std::get_if<std::string>(&property.second);
868 if (value == nullptr)
869 {
870 continue;
871 }
872 aResp->res.jsonValue["Manufacturer"] = *value;
Manojkiran Eda7e236ca2019-06-25 23:06:32 +0530873 }
James Feistc50e7c62020-07-27 15:39:36 -0700874 else if (property.first == "RevisionCode")
875 {
876 const uint16_t* value =
877 std::get_if<uint16_t>(&property.second);
878
879 if (value == nullptr)
880 {
881 messages::internalError(aResp->res);
882 BMCWEB_LOG_DEBUG
883 << "Invalid property type for RevisionCode";
884 continue;
885 }
886 aResp->res.jsonValue["FirmwareRevision"] =
887 std::to_string(*value);
888 }
889 else if (property.first == "MemoryTotalWidth")
890 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700891 const uint16_t* value =
892 std::get_if<uint16_t>(&property.second);
893 if (value == nullptr)
894 {
895 continue;
896 }
897 aResp->res.jsonValue["BusWidthBits"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700898 }
899 else if (property.first == "ECC")
900 {
901 const std::string* value =
902 std::get_if<std::string>(&property.second);
903 if (value == nullptr)
904 {
905 messages::internalError(aResp->res);
906 BMCWEB_LOG_DEBUG << "Invalid property type for ECC";
907 continue;
908 }
909 constexpr const std::array<const char*, 4> values{
910 "NoECC", "SingleBitECC", "MultiBitECC",
911 "AddressParity"};
912
913 for (const char* v : values)
914 {
915 if (boost::ends_with(*value, v))
916 {
917 aResp->res.jsonValue["ErrorCorrection"] = v;
918 break;
919 }
920 }
921 }
922 else if (property.first == "FormFactor")
923 {
924 const std::string* value =
925 std::get_if<std::string>(&property.second);
926 if (value == nullptr)
927 {
928 messages::internalError(aResp->res);
929 BMCWEB_LOG_DEBUG
930 << "Invalid property type for FormFactor";
931 continue;
932 }
933 constexpr const std::array<const char*, 11> values{
934 "RDIMM", "UDIMM", "SO_DIMM",
935 "LRDIMM", "Mini_RDIMM", "Mini_UDIMM",
936 "SO_RDIMM_72b", "SO_UDIMM_72b", "SO_DIMM_16b",
937 "SO_DIMM_32b", "Die"};
938
939 for (const char* v : values)
940 {
941 if (boost::ends_with(*value, v))
942 {
943 aResp->res.jsonValue["BaseModuleType"] = v;
944 break;
945 }
946 }
947 }
948 else if (property.first == "AllowedSpeedsMT")
949 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700950 const std::vector<uint16_t>* value =
951 std::get_if<std::vector<uint16_t>>(&property.second);
952 if (value == nullptr)
953 {
954 continue;
955 }
956 nlohmann::json& jValue =
957 aResp->res.jsonValue["AllowedSpeedsMHz"];
958 jValue = nlohmann::json::array();
959 for (uint16_t subVal : *value)
960 {
961 jValue.push_back(subVal);
962 }
James Feistc50e7c62020-07-27 15:39:36 -0700963 }
964 else if (property.first == "MemoryAttributes")
965 {
966 const uint8_t* value =
967 std::get_if<uint8_t>(&property.second);
968
969 if (value == nullptr)
970 {
971 messages::internalError(aResp->res);
972 BMCWEB_LOG_DEBUG
973 << "Invalid property type for MemoryAttributes";
974 continue;
975 }
976 aResp->res.jsonValue["RankCount"] =
977 static_cast<uint64_t>(*value);
978 }
979 else if (property.first == "MemoryConfiguredSpeedInMhz")
980 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700981 const uint16_t* value =
982 std::get_if<uint16_t>(&property.second);
983 if (value == nullptr)
984 {
985 continue;
986 }
987 aResp->res.jsonValue["OperatingSpeedMhz"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700988 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200989 else if (property.first == "MemoryType")
990 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500991 const auto* value =
Ed Tanousabf2add2019-01-22 16:40:12 -0800992 std::get_if<std::string>(&property.second);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200993 if (value != nullptr)
994 {
James Feistc50e7c62020-07-27 15:39:36 -0700995 size_t idx = value->rfind(".");
996 if (idx == std::string::npos ||
997 idx + 1 >= value->size())
998 {
999 messages::internalError(aResp->res);
1000 BMCWEB_LOG_DEBUG << "Invalid property type for "
1001 "MemoryType";
1002 }
1003 std::string result = value->substr(idx + 1);
1004 aResp->res.jsonValue["MemoryDeviceType"] = result;
1005 if (value->find("DDR") != std::string::npos)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001006 {
1007 aResp->res.jsonValue["MemoryType"] = "DRAM";
1008 }
James Feistc50e7c62020-07-27 15:39:36 -07001009 else if (boost::ends_with(*value, "Logical"))
1010 {
1011 aResp->res.jsonValue["MemoryType"] = "IntelOptane";
1012 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001013 }
1014 }
James Feistc50e7c62020-07-27 15:39:36 -07001015 // memory location interface
1016 else if (property.first == "Channel" ||
1017 property.first == "MemoryController" ||
1018 property.first == "Slot" || property.first == "Socket")
1019 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -07001020 const std::string* value =
1021 std::get_if<std::string>(&property.second);
1022 if (value == nullptr)
1023 {
1024 messages::internalError(aResp->res);
1025 continue;
1026 }
James Feistc50e7c62020-07-27 15:39:36 -07001027 aResp->res.jsonValue["MemoryLocation"][property.first] =
Ed Tanous5fb91ba2020-09-28 15:41:28 -07001028 *value;
James Feistc50e7c62020-07-27 15:39:36 -07001029 }
1030 else
1031 {
1032 getPersistentMemoryProperties(aResp, properties);
1033 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001034 }
1035 },
1036 service, objPath, "org.freedesktop.DBus.Properties", "GetAll", "");
1037}
1038
Ed Tanous23a21a12020-07-25 04:45:05 +00001039inline void getDimmPartitionData(std::shared_ptr<AsyncResp> aResp,
1040 const std::string& service,
1041 const std::string& path)
James Feist45094ad2020-04-29 14:02:30 -07001042{
1043 crow::connections::systemBus->async_method_call(
1044 [aResp{std::move(aResp)}](
1045 const boost::system::error_code ec,
1046 const boost::container::flat_map<
1047 std::string, std::variant<std::string, uint64_t, uint32_t,
1048 bool>>& properties) {
1049 if (ec)
1050 {
1051 BMCWEB_LOG_DEBUG << "DBUS response error";
1052 messages::internalError(aResp->res);
1053
1054 return;
1055 }
1056
1057 nlohmann::json& partition =
1058 aResp->res.jsonValue["Regions"].emplace_back(
1059 nlohmann::json::object());
1060 for (const auto& [key, val] : properties)
1061 {
1062 if (key == "MemoryClassification")
1063 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -07001064 const std::string* value = std::get_if<std::string>(&val);
1065 if (value == nullptr)
1066 {
1067 messages::internalError(aResp->res);
1068 continue;
1069 }
1070 partition[key] = *value;
James Feist45094ad2020-04-29 14:02:30 -07001071 }
1072 else if (key == "OffsetInKiB")
1073 {
1074 const uint64_t* value = std::get_if<uint64_t>(&val);
1075 if (value == nullptr)
1076 {
1077 messages::internalError(aResp->res);
James Feist45094ad2020-04-29 14:02:30 -07001078 continue;
1079 }
1080
1081 partition["OffsetMiB"] = (*value >> 10);
1082 }
1083 else if (key == "PartitionId")
1084 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -07001085 const std::string* value = std::get_if<std::string>(&val);
1086 if (value == nullptr)
1087 {
1088 messages::internalError(aResp->res);
1089 continue;
1090 }
1091 partition["RegionId"] = *value;
James Feist45094ad2020-04-29 14:02:30 -07001092 }
1093
1094 else if (key == "PassphraseState")
1095 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -07001096 const bool* value = std::get_if<bool>(&val);
1097 if (value == nullptr)
1098 {
1099 messages::internalError(aResp->res);
1100 continue;
1101 }
1102 partition["PassphraseEnabled"] = *value;
James Feist45094ad2020-04-29 14:02:30 -07001103 }
1104 else if (key == "SizeInKiB")
1105 {
1106 const uint64_t* value = std::get_if<uint64_t>(&val);
1107 if (value == nullptr)
1108 {
1109 messages::internalError(aResp->res);
1110 BMCWEB_LOG_DEBUG
1111 << "Invalid property type for SizeInKiB";
1112 continue;
1113 }
1114 partition["SizeMiB"] = (*value >> 10);
1115 }
1116 }
1117 },
1118
1119 service, path, "org.freedesktop.DBus.Properties", "GetAll",
1120 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition");
1121}
1122
Ed Tanous23a21a12020-07-25 04:45:05 +00001123inline void getDimmData(std::shared_ptr<AsyncResp> aResp,
1124 const std::string& dimmId)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001125{
1126 BMCWEB_LOG_DEBUG << "Get available system dimm resources.";
1127 crow::connections::systemBus->async_method_call(
Ed Tanous029573d2019-02-01 10:57:49 -08001128 [dimmId, aResp{std::move(aResp)}](
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001129 const boost::system::error_code ec,
1130 const boost::container::flat_map<
1131 std::string, boost::container::flat_map<
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001132 std::string, std::vector<std::string>>>&
1133 subtree) {
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001134 if (ec)
1135 {
1136 BMCWEB_LOG_DEBUG << "DBUS response error";
1137 messages::internalError(aResp->res);
1138
1139 return;
1140 }
James Feist45094ad2020-04-29 14:02:30 -07001141 bool found = false;
1142 for (const auto& [path, object] : subtree)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001143 {
James Feist45094ad2020-04-29 14:02:30 -07001144 if (path.find(dimmId) != std::string::npos)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001145 {
James Feist45094ad2020-04-29 14:02:30 -07001146 for (const auto& [service, interfaces] : object)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001147 {
James Feist45094ad2020-04-29 14:02:30 -07001148 if (!found &&
1149 (std::find(
1150 interfaces.begin(), interfaces.end(),
1151 "xyz.openbmc_project.Inventory.Item.Dimm") !=
1152 interfaces.end()))
1153 {
1154 getDimmDataByService(aResp, dimmId, service, path);
1155 found = true;
1156 }
1157
1158 // partitions are separate as there can be multiple per
1159 // device, i.e.
1160 // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition1
1161 // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition2
1162 if (std::find(interfaces.begin(), interfaces.end(),
1163 "xyz.openbmc_project.Inventory.Item."
1164 "PersistentMemory.Partition") !=
1165 interfaces.end())
1166 {
1167 getDimmPartitionData(aResp, service, path);
1168 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001169 }
1170 }
1171 }
1172 // Object not found
James Feist45094ad2020-04-29 14:02:30 -07001173 if (!found)
1174 {
1175 messages::resourceNotFound(aResp->res, "Memory", dimmId);
1176 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001177 return;
1178 },
1179 "xyz.openbmc_project.ObjectMapper",
1180 "/xyz/openbmc_project/object_mapper",
1181 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous271584a2019-07-09 16:24:22 -07001182 "/xyz/openbmc_project/inventory", 0,
James Feist45094ad2020-04-29 14:02:30 -07001183 std::array<const char*, 2>{
1184 "xyz.openbmc_project.Inventory.Item.Dimm",
1185 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition"});
Ed Tanous271584a2019-07-09 16:24:22 -07001186}
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001187
1188class ProcessorCollection : public Node
1189{
1190 public:
1191 /*
1192 * Default Constructor
1193 */
Ed Tanous52cc1122020-07-18 13:51:21 -07001194 ProcessorCollection(App& app) :
Ed Tanous029573d2019-02-01 10:57:49 -08001195 Node(app, "/redfish/v1/Systems/system/Processors/")
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001196 {
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001197 entityPrivileges = {
1198 {boost::beast::http::verb::get, {{"Login"}}},
1199 {boost::beast::http::verb::head, {{"Login"}}},
1200 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
1201 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
1202 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
1203 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
1204 }
1205
1206 private:
1207 /**
1208 * Functions triggers appropriate requests on DBus
1209 */
Ed Tanouscb13a392020-07-25 19:02:03 +00001210 void doGet(crow::Response& res, const crow::Request&,
1211 const std::vector<std::string>&) override
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001212 {
Ed Tanous0f74e642018-11-12 15:17:05 -08001213 res.jsonValue["@odata.type"] =
1214 "#ProcessorCollection.ProcessorCollection";
1215 res.jsonValue["Name"] = "Processor Collection";
Ed Tanous0f74e642018-11-12 15:17:05 -08001216
Ed Tanous029573d2019-02-01 10:57:49 -08001217 res.jsonValue["@odata.id"] = "/redfish/v1/Systems/system/Processors/";
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001218 auto asyncResp = std::make_shared<AsyncResp>(res);
1219
Ed Tanous029573d2019-02-01 10:57:49 -08001220 getResourceList(asyncResp, "Processors",
Alpana Kumari32bee762019-04-25 04:47:57 -05001221 {"xyz.openbmc_project.Inventory.Item.Cpu",
1222 "xyz.openbmc_project.Inventory.Item.Accelerator"});
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001223 }
1224};
1225
1226class Processor : public Node
1227{
1228 public:
1229 /*
1230 * Default Constructor
1231 */
Ed Tanous52cc1122020-07-18 13:51:21 -07001232 Processor(App& app) :
Ed Tanous029573d2019-02-01 10:57:49 -08001233 Node(app, "/redfish/v1/Systems/system/Processors/<str>/", std::string())
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001234 {
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001235 entityPrivileges = {
1236 {boost::beast::http::verb::get, {{"Login"}}},
1237 {boost::beast::http::verb::head, {{"Login"}}},
1238 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
1239 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
1240 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
1241 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
1242 }
1243
1244 private:
1245 /**
1246 * Functions triggers appropriate requests on DBus
1247 */
Ed Tanouscb13a392020-07-25 19:02:03 +00001248 void doGet(crow::Response& res, const crow::Request&,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001249 const std::vector<std::string>& params) override
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001250 {
1251 // Check if there is required param, truly entering this shall be
1252 // impossible
1253 if (params.size() != 1)
1254 {
1255 messages::internalError(res);
1256
1257 res.end();
1258 return;
1259 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001260 const std::string& processorId = params[0];
Zhikui Ren029cc1f2020-08-25 15:21:41 -07001261 res.jsonValue["@odata.type"] = "#Processor.v1_9_0.Processor";
Ed Tanous029573d2019-02-01 10:57:49 -08001262 res.jsonValue["@odata.id"] =
Alpana Kumari32bee762019-04-25 04:47:57 -05001263 "/redfish/v1/Systems/system/Processors/" + processorId;
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001264
Ed Tanous029573d2019-02-01 10:57:49 -08001265 auto asyncResp = std::make_shared<AsyncResp>(res);
1266
Alpana Kumari32bee762019-04-25 04:47:57 -05001267 getCpuData(asyncResp, processorId,
1268 {"xyz.openbmc_project.Inventory.Item.Cpu",
Zhikui Ren5e54a362020-07-13 15:31:38 -07001269 "xyz.openbmc_project.Inventory.Decorator.Asset",
Alpana Kumari32bee762019-04-25 04:47:57 -05001270 "xyz.openbmc_project.Inventory.Item.Accelerator"});
Ed Tanous029573d2019-02-01 10:57:49 -08001271 }
1272};
1273
1274class MemoryCollection : public Node
1275{
1276 public:
1277 /*
1278 * Default Constructor
1279 */
Ed Tanous52cc1122020-07-18 13:51:21 -07001280 MemoryCollection(App& app) : Node(app, "/redfish/v1/Systems/system/Memory/")
Ed Tanous029573d2019-02-01 10:57:49 -08001281 {
1282 entityPrivileges = {
1283 {boost::beast::http::verb::get, {{"Login"}}},
1284 {boost::beast::http::verb::head, {{"Login"}}},
1285 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
1286 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
1287 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
1288 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
1289 }
1290
1291 private:
1292 /**
1293 * Functions triggers appropriate requests on DBus
1294 */
Ed Tanouscb13a392020-07-25 19:02:03 +00001295 void doGet(crow::Response& res, const crow::Request&,
1296 const std::vector<std::string>&) override
Ed Tanous029573d2019-02-01 10:57:49 -08001297 {
Ed Tanous0f74e642018-11-12 15:17:05 -08001298 res.jsonValue["@odata.type"] = "#MemoryCollection.MemoryCollection";
1299 res.jsonValue["Name"] = "Memory Module Collection";
James Feistc50e7c62020-07-27 15:39:36 -07001300 res.jsonValue["@odata.id"] = "/redfish/v1/Systems/system/Memory";
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001301 auto asyncResp = std::make_shared<AsyncResp>(res);
1302
Ed Tanous029573d2019-02-01 10:57:49 -08001303 getResourceList(asyncResp, "Memory",
Alpana Kumari32bee762019-04-25 04:47:57 -05001304 {"xyz.openbmc_project.Inventory.Item.Dimm"});
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001305 }
1306};
1307
1308class Memory : public Node
1309{
1310 public:
1311 /*
1312 * Default Constructor
1313 */
Ed Tanous52cc1122020-07-18 13:51:21 -07001314 Memory(App& app) :
Ed Tanous029573d2019-02-01 10:57:49 -08001315 Node(app, "/redfish/v1/Systems/system/Memory/<str>/", std::string())
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001316 {
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001317 entityPrivileges = {
1318 {boost::beast::http::verb::get, {{"Login"}}},
1319 {boost::beast::http::verb::head, {{"Login"}}},
1320 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
1321 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
1322 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
1323 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
1324 }
1325
1326 private:
1327 /**
1328 * Functions triggers appropriate requests on DBus
1329 */
Ed Tanouscb13a392020-07-25 19:02:03 +00001330 void doGet(crow::Response& res, const crow::Request&,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001331 const std::vector<std::string>& params) override
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001332 {
1333 // Check if there is required param, truly entering this shall be
1334 // impossible
Ed Tanous029573d2019-02-01 10:57:49 -08001335 if (params.size() != 1)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001336 {
1337 messages::internalError(res);
1338 res.end();
1339 return;
1340 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001341 const std::string& dimmId = params[0];
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001342
James Feistc50e7c62020-07-27 15:39:36 -07001343 res.jsonValue["@odata.type"] = "#Memory.v1_7_0.Memory";
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001344 res.jsonValue["@odata.id"] =
Ed Tanous029573d2019-02-01 10:57:49 -08001345 "/redfish/v1/Systems/system/Memory/" + dimmId;
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001346 auto asyncResp = std::make_shared<AsyncResp>(res);
1347
Ed Tanous029573d2019-02-01 10:57:49 -08001348 getDimmData(asyncResp, dimmId);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001349 }
1350};
1351
1352} // namespace redfish