blob: e4b7a9db385d825a89a7febb8daa27ebf28a0d36 [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
73 getCpuDataByInterface(std::shared_ptr<AsyncResp> aResp,
74 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,
413 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 Tanous80789c82020-08-19 09:19:09 -0700484inline void dimmPropToHex(std::shared_ptr<AsyncResp> aResp, const char* key,
485 const std::pair<std::string, DimmProperty>& property)
James Feistc50e7c62020-07-27 15:39:36 -0700486{
487 const uint16_t* value = std::get_if<uint16_t>(&property.second);
488 if (value == nullptr)
489 {
490 messages::internalError(aResp->res);
491 BMCWEB_LOG_DEBUG << "Invalid property type for " << property.first;
492 return;
493 }
494
495 aResp->res.jsonValue[key] = (boost::format("0x%04x") % *value).str();
496}
497
Ed Tanous80789c82020-08-19 09:19:09 -0700498inline void getPersistentMemoryProperties(std::shared_ptr<AsyncResp> aResp,
499 const DimmProperties& properties)
James Feistc50e7c62020-07-27 15:39:36 -0700500{
501 for (const auto& property : properties)
502 {
503 if (property.first == "ModuleManufacturerID")
504 {
505 dimmPropToHex(aResp, "ModuleManufacturerID", property);
506 }
507 else if (property.first == "ModuleProductID")
508 {
509 dimmPropToHex(aResp, "ModuleProductID", property);
510 }
511 else if (property.first == "SubsystemVendorID")
512 {
513 dimmPropToHex(aResp, "MemorySubsystemControllerManufacturerID",
514 property);
515 }
516 else if (property.first == "SubsystemDeviceID")
517 {
518 dimmPropToHex(aResp, "MemorySubsystemControllerProductID",
519 property);
520 }
521 else if (property.first == "VolatileRegionSizeLimitInKiB")
522 {
523 const uint64_t* value = std::get_if<uint64_t>(&property.second);
524
525 if (value == nullptr)
526 {
527 messages::internalError(aResp->res);
528 BMCWEB_LOG_DEBUG << "Invalid property type for "
529 "VolatileRegionSizeLimitKiB";
530 continue;
531 }
532 aResp->res.jsonValue["VolatileRegionSizeLimitMiB"] = (*value) >> 10;
533 }
534 else if (property.first == "PmRegionSizeLimitInKiB")
535 {
536 const uint64_t* value = std::get_if<uint64_t>(&property.second);
537
538 if (value == nullptr)
539 {
540 messages::internalError(aResp->res);
541 BMCWEB_LOG_DEBUG
542 << "Invalid property type for PmRegioSizeLimitKiB";
543 continue;
544 }
545 aResp->res.jsonValue["PersistentRegionSizeLimitMiB"] =
546 (*value) >> 10;
547 }
548 else if (property.first == "VolatileSizeInKiB")
549 {
550 const uint64_t* value = std::get_if<uint64_t>(&property.second);
551
552 if (value == nullptr)
553 {
554 messages::internalError(aResp->res);
555 BMCWEB_LOG_DEBUG
556 << "Invalid property type for VolatileSizeInKiB";
557 continue;
558 }
559 aResp->res.jsonValue["VolatileSizeMiB"] = (*value) >> 10;
560 }
561 else if (property.first == "PmSizeInKiB")
562 {
563 const uint64_t* value = std::get_if<uint64_t>(&property.second);
564 if (value == nullptr)
565 {
566 messages::internalError(aResp->res);
567 BMCWEB_LOG_DEBUG << "Invalid property type for PmSizeInKiB";
568 continue;
569 }
570 aResp->res.jsonValue["NonVolatileSizeMiB"] = (*value) >> 10;
571 }
572 else if (property.first == "CacheSizeInKB")
573 {
574 const uint64_t* value = std::get_if<uint64_t>(&property.second);
575 if (value == nullptr)
576 {
577 messages::internalError(aResp->res);
578 BMCWEB_LOG_DEBUG << "Invalid property type for CacheSizeInKB";
579 continue;
580 }
581 aResp->res.jsonValue["CacheSizeMiB"] = (*value >> 10);
582 }
583
584 else if (property.first == "VoltaileRegionMaxSizeInKib")
585 {
586 const uint64_t* value = std::get_if<uint64_t>(&property.second);
587
588 if (value == nullptr)
589 {
590 messages::internalError(aResp->res);
591 BMCWEB_LOG_DEBUG << "Invalid property type for "
592 "VolatileRegionMaxSizeInKib";
593 continue;
594 }
595 aResp->res.jsonValue["VolatileRegionSizeMaxMiB"] = (*value) >> 10;
596 }
597 else if (property.first == "PmRegionMaxSizeInKiB")
598 {
599 const uint64_t* value = std::get_if<uint64_t>(&property.second);
600
601 if (value == nullptr)
602 {
603 messages::internalError(aResp->res);
604 BMCWEB_LOG_DEBUG
605 << "Invalid property type for PmRegionMaxSizeInKiB";
606 continue;
607 }
608 aResp->res.jsonValue["PersistentRegionSizeMaxMiB"] = (*value) >> 10;
609 }
610 else if (property.first == "AllocationIncrementInKiB")
611 {
612 const uint64_t* value = std::get_if<uint64_t>(&property.second);
613
614 if (value == nullptr)
615 {
616 messages::internalError(aResp->res);
617 BMCWEB_LOG_DEBUG << "Invalid property type for "
618 "AllocationIncrementInKiB";
619 continue;
620 }
621 aResp->res.jsonValue["AllocationIncrementMiB"] = (*value) >> 10;
622 }
623 else if (property.first == "AllocationAlignmentInKiB")
624 {
625 const uint64_t* value = std::get_if<uint64_t>(&property.second);
626
627 if (value == nullptr)
628 {
629 messages::internalError(aResp->res);
630 BMCWEB_LOG_DEBUG << "Invalid property type for "
631 "AllocationAlignmentInKiB";
632 continue;
633 }
634 aResp->res.jsonValue["AllocationAlignmentMiB"] = (*value) >> 10;
635 }
636 else if (property.first == "VolatileRegionNumberLimit")
637 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700638 const uint64_t* value = std::get_if<uint64_t>(&property.second);
639 if (value == nullptr)
640 {
641 messages::internalError(aResp->res);
642 continue;
643 }
644 aResp->res.jsonValue["VolatileRegionNumberLimit"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700645 }
646 else if (property.first == "PmRegionNumberLimit")
647 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700648 const uint64_t* value = std::get_if<uint64_t>(&property.second);
649 if (value == nullptr)
650 {
651 messages::internalError(aResp->res);
652 continue;
653 }
654 aResp->res.jsonValue["PersistentRegionNumberLimit"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700655 }
656 else if (property.first == "SpareDeviceCount")
657 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700658 const uint64_t* value = std::get_if<uint64_t>(&property.second);
659 if (value == nullptr)
660 {
661 messages::internalError(aResp->res);
662 continue;
663 }
664 aResp->res.jsonValue["SpareDeviceCount"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700665 }
666 else if (property.first == "IsSpareDeviceInUse")
667 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700668 const bool* value = std::get_if<bool>(&property.second);
669 if (value == nullptr)
670 {
671 messages::internalError(aResp->res);
672 continue;
673 }
674 aResp->res.jsonValue["IsSpareDeviceEnabled"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700675 }
676 else if (property.first == "IsRankSpareEnabled")
677 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700678 const bool* value = std::get_if<bool>(&property.second);
679 if (value == nullptr)
680 {
681 messages::internalError(aResp->res);
682 continue;
683 }
684 aResp->res.jsonValue["IsRankSpareEnabled"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700685 }
686 else if (property.first == "MaxAveragePowerLimitmW")
687 {
688 const auto* value =
689 std::get_if<std::vector<uint32_t>>(&property.second);
690 if (value == nullptr)
691 {
692 messages::internalError(aResp->res);
693 BMCWEB_LOG_DEBUG << "Invalid property type for "
694 "MaxAveragePowerLimitmW";
695 continue;
696 }
697 aResp->res.jsonValue["MaxTDPMilliWatts"] = *value;
698 }
James Feistc50e7c62020-07-27 15:39:36 -0700699 else if (property.first == "ConfigurationLocked")
700 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700701 const bool* value = std::get_if<bool>(&property.second);
702 if (value == nullptr)
703 {
704 messages::internalError(aResp->res);
705 continue;
706 }
707 aResp->res.jsonValue["ConfigurationLocked"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700708 }
709 else if (property.first == "AllowedMemoryModes")
710 {
711 const std::string* value =
712 std::get_if<std::string>(&property.second);
713 if (value == nullptr)
714 {
715 messages::internalError(aResp->res);
716 BMCWEB_LOG_DEBUG << "Invalid property type for FormFactor";
717 continue;
718 }
719 constexpr const std::array<const char*, 3> values{"Volatile",
720 "PMEM", "Block"};
721
722 for (const char* v : values)
723 {
724 if (boost::ends_with(*value, v))
725 {
726 aResp->res.jsonValue["OperatingMemoryModes "] = v;
727 break;
728 }
729 }
730 }
731 else if (property.first == "MemoryMedia")
732 {
733 const std::string* value =
734 std::get_if<std::string>(&property.second);
735 if (value == nullptr)
736 {
737 messages::internalError(aResp->res);
738 BMCWEB_LOG_DEBUG << "Invalid property type for MemoryMedia";
739 continue;
740 }
741 constexpr const std::array<const char*, 3> values{"DRAM", "NAND",
742 "Intel3DXPoint"};
743
744 for (const char* v : values)
745 {
746 if (boost::ends_with(*value, v))
747 {
748 aResp->res.jsonValue["MemoryMedia"] = v;
749 break;
750 }
751 }
752 }
James Feistc50e7c62020-07-27 15:39:36 -0700753 // PersistantMemory.SecurityCapabilites interface
754 else if (property.first == "ConfigurationLockCapable" ||
755 property.first == "DataLockCapable" ||
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700756 property.first == "PassphraseCapable")
757 {
758 const bool* value = std::get_if<bool>(&property.second);
759 if (value == nullptr)
760 {
761 messages::internalError(aResp->res);
762 continue;
763 }
764 aResp->res.jsonValue["SecurityCapabilities"][property.first] =
765 *value;
766 }
767 else if (property.first == "MaxPassphraseCount" ||
James Feistc50e7c62020-07-27 15:39:36 -0700768 property.first == "PassphraseLockLimit")
769 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700770 const uint64_t* value = std::get_if<uint64_t>(&property.second);
771 if (value == nullptr)
772 {
773 messages::internalError(aResp->res);
774 continue;
775 }
James Feistc50e7c62020-07-27 15:39:36 -0700776 aResp->res.jsonValue["SecurityCapabilities"][property.first] =
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700777 *value;
James Feistc50e7c62020-07-27 15:39:36 -0700778 }
779 }
780}
781
Ed Tanous80789c82020-08-19 09:19:09 -0700782inline void getDimmDataByService(std::shared_ptr<AsyncResp> aResp,
783 const std::string& dimmId,
784 const std::string& service,
785 const std::string& objPath)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200786{
James Feist35e257a2020-06-05 13:30:51 -0700787 auto health = std::make_shared<HealthPopulate>(aResp);
788 health->selfPath = objPath;
789 health->populate();
790
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200791 BMCWEB_LOG_DEBUG << "Get available system components.";
792 crow::connections::systemBus->async_method_call(
James Feistc50e7c62020-07-27 15:39:36 -0700793 [dimmId, aResp{std::move(aResp)}](const boost::system::error_code ec,
794 const DimmProperties& properties) {
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200795 if (ec)
796 {
797 BMCWEB_LOG_DEBUG << "DBUS response error";
798 messages::internalError(aResp->res);
799
800 return;
801 }
802 aResp->res.jsonValue["Id"] = dimmId;
803 aResp->res.jsonValue["Name"] = "DIMM Slot";
804
805 const auto memorySizeProperty = properties.find("MemorySizeInKB");
Gunnar Millsaceb7fc2018-12-10 15:17:20 -0600806 if (memorySizeProperty != properties.end())
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200807 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500808 const uint32_t* memorySize =
Ed Tanousabf2add2019-01-22 16:40:12 -0800809 std::get_if<uint32_t>(&memorySizeProperty->second);
Gunnar Millsaceb7fc2018-12-10 15:17:20 -0600810 if (memorySize == nullptr)
811 {
812 // Important property not in desired type
813 messages::internalError(aResp->res);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200814
Gunnar Millsaceb7fc2018-12-10 15:17:20 -0600815 return;
816 }
817 if (*memorySize == 0)
818 {
819 // Slot is not populated, set status end return
820 aResp->res.jsonValue["Status"]["State"] = "Absent";
821 aResp->res.jsonValue["Status"]["Health"] = "OK";
822 // HTTP Code will be set up automatically, just return
823 return;
824 }
825 aResp->res.jsonValue["CapacityMiB"] = (*memorySize >> 10);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200826 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200827 aResp->res.jsonValue["Status"]["State"] = "Enabled";
828 aResp->res.jsonValue["Status"]["Health"] = "OK";
829
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500830 for (const auto& property : properties)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200831 {
832 if (property.first == "MemoryDataWidth")
833 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700834 const uint16_t* value =
835 std::get_if<uint16_t>(&property.second);
836 if (value == nullptr)
837 {
838 continue;
839 }
840 aResp->res.jsonValue["DataWidthBits"] = *value;
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200841 }
Manojkiran Eda7e236ca2019-06-25 23:06:32 +0530842 else if (property.first == "PartNumber")
843 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700844 const std::string* value =
845 std::get_if<std::string>(&property.second);
846 if (value == nullptr)
847 {
848 continue;
849 }
850 aResp->res.jsonValue["PartNumber"] = *value;
Manojkiran Eda7e236ca2019-06-25 23:06:32 +0530851 }
852 else if (property.first == "SerialNumber")
853 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700854 const std::string* value =
855 std::get_if<std::string>(&property.second);
856 if (value == nullptr)
857 {
858 continue;
859 }
860 aResp->res.jsonValue["SerialNumber"] = *value;
Manojkiran Eda7e236ca2019-06-25 23:06:32 +0530861 }
862 else if (property.first == "Manufacturer")
863 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700864 const std::string* value =
865 std::get_if<std::string>(&property.second);
866 if (value == nullptr)
867 {
868 continue;
869 }
870 aResp->res.jsonValue["Manufacturer"] = *value;
Manojkiran Eda7e236ca2019-06-25 23:06:32 +0530871 }
James Feistc50e7c62020-07-27 15:39:36 -0700872 else if (property.first == "RevisionCode")
873 {
874 const uint16_t* value =
875 std::get_if<uint16_t>(&property.second);
876
877 if (value == nullptr)
878 {
879 messages::internalError(aResp->res);
880 BMCWEB_LOG_DEBUG
881 << "Invalid property type for RevisionCode";
882 continue;
883 }
884 aResp->res.jsonValue["FirmwareRevision"] =
885 std::to_string(*value);
886 }
887 else if (property.first == "MemoryTotalWidth")
888 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700889 const uint16_t* value =
890 std::get_if<uint16_t>(&property.second);
891 if (value == nullptr)
892 {
893 continue;
894 }
895 aResp->res.jsonValue["BusWidthBits"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700896 }
897 else if (property.first == "ECC")
898 {
899 const std::string* value =
900 std::get_if<std::string>(&property.second);
901 if (value == nullptr)
902 {
903 messages::internalError(aResp->res);
904 BMCWEB_LOG_DEBUG << "Invalid property type for ECC";
905 continue;
906 }
907 constexpr const std::array<const char*, 4> values{
908 "NoECC", "SingleBitECC", "MultiBitECC",
909 "AddressParity"};
910
911 for (const char* v : values)
912 {
913 if (boost::ends_with(*value, v))
914 {
915 aResp->res.jsonValue["ErrorCorrection"] = v;
916 break;
917 }
918 }
919 }
920 else if (property.first == "FormFactor")
921 {
922 const std::string* value =
923 std::get_if<std::string>(&property.second);
924 if (value == nullptr)
925 {
926 messages::internalError(aResp->res);
927 BMCWEB_LOG_DEBUG
928 << "Invalid property type for FormFactor";
929 continue;
930 }
931 constexpr const std::array<const char*, 11> values{
932 "RDIMM", "UDIMM", "SO_DIMM",
933 "LRDIMM", "Mini_RDIMM", "Mini_UDIMM",
934 "SO_RDIMM_72b", "SO_UDIMM_72b", "SO_DIMM_16b",
935 "SO_DIMM_32b", "Die"};
936
937 for (const char* v : values)
938 {
939 if (boost::ends_with(*value, v))
940 {
941 aResp->res.jsonValue["BaseModuleType"] = v;
942 break;
943 }
944 }
945 }
946 else if (property.first == "AllowedSpeedsMT")
947 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700948 const std::vector<uint16_t>* value =
949 std::get_if<std::vector<uint16_t>>(&property.second);
950 if (value == nullptr)
951 {
952 continue;
953 }
954 nlohmann::json& jValue =
955 aResp->res.jsonValue["AllowedSpeedsMHz"];
956 jValue = nlohmann::json::array();
957 for (uint16_t subVal : *value)
958 {
959 jValue.push_back(subVal);
960 }
James Feistc50e7c62020-07-27 15:39:36 -0700961 }
962 else if (property.first == "MemoryAttributes")
963 {
964 const uint8_t* value =
965 std::get_if<uint8_t>(&property.second);
966
967 if (value == nullptr)
968 {
969 messages::internalError(aResp->res);
970 BMCWEB_LOG_DEBUG
971 << "Invalid property type for MemoryAttributes";
972 continue;
973 }
974 aResp->res.jsonValue["RankCount"] =
975 static_cast<uint64_t>(*value);
976 }
977 else if (property.first == "MemoryConfiguredSpeedInMhz")
978 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700979 const uint16_t* value =
980 std::get_if<uint16_t>(&property.second);
981 if (value == nullptr)
982 {
983 continue;
984 }
985 aResp->res.jsonValue["OperatingSpeedMhz"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700986 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200987 else if (property.first == "MemoryType")
988 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500989 const auto* value =
Ed Tanousabf2add2019-01-22 16:40:12 -0800990 std::get_if<std::string>(&property.second);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200991 if (value != nullptr)
992 {
James Feistc50e7c62020-07-27 15:39:36 -0700993 size_t idx = value->rfind(".");
994 if (idx == std::string::npos ||
995 idx + 1 >= value->size())
996 {
997 messages::internalError(aResp->res);
998 BMCWEB_LOG_DEBUG << "Invalid property type for "
999 "MemoryType";
1000 }
1001 std::string result = value->substr(idx + 1);
1002 aResp->res.jsonValue["MemoryDeviceType"] = result;
1003 if (value->find("DDR") != std::string::npos)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001004 {
1005 aResp->res.jsonValue["MemoryType"] = "DRAM";
1006 }
James Feistc50e7c62020-07-27 15:39:36 -07001007 else if (boost::ends_with(*value, "Logical"))
1008 {
1009 aResp->res.jsonValue["MemoryType"] = "IntelOptane";
1010 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001011 }
1012 }
James Feistc50e7c62020-07-27 15:39:36 -07001013 // memory location interface
1014 else if (property.first == "Channel" ||
1015 property.first == "MemoryController" ||
1016 property.first == "Slot" || property.first == "Socket")
1017 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -07001018 const std::string* value =
1019 std::get_if<std::string>(&property.second);
1020 if (value == nullptr)
1021 {
1022 messages::internalError(aResp->res);
1023 continue;
1024 }
James Feistc50e7c62020-07-27 15:39:36 -07001025 aResp->res.jsonValue["MemoryLocation"][property.first] =
Ed Tanous5fb91ba2020-09-28 15:41:28 -07001026 *value;
James Feistc50e7c62020-07-27 15:39:36 -07001027 }
1028 else
1029 {
1030 getPersistentMemoryProperties(aResp, properties);
1031 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001032 }
1033 },
1034 service, objPath, "org.freedesktop.DBus.Properties", "GetAll", "");
1035}
1036
Ed Tanous23a21a12020-07-25 04:45:05 +00001037inline void getDimmPartitionData(std::shared_ptr<AsyncResp> aResp,
1038 const std::string& service,
1039 const std::string& path)
James Feist45094ad2020-04-29 14:02:30 -07001040{
1041 crow::connections::systemBus->async_method_call(
1042 [aResp{std::move(aResp)}](
1043 const boost::system::error_code ec,
1044 const boost::container::flat_map<
1045 std::string, std::variant<std::string, uint64_t, uint32_t,
1046 bool>>& properties) {
1047 if (ec)
1048 {
1049 BMCWEB_LOG_DEBUG << "DBUS response error";
1050 messages::internalError(aResp->res);
1051
1052 return;
1053 }
1054
1055 nlohmann::json& partition =
1056 aResp->res.jsonValue["Regions"].emplace_back(
1057 nlohmann::json::object());
1058 for (const auto& [key, val] : properties)
1059 {
1060 if (key == "MemoryClassification")
1061 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -07001062 const std::string* value = std::get_if<std::string>(&val);
1063 if (value == nullptr)
1064 {
1065 messages::internalError(aResp->res);
1066 continue;
1067 }
1068 partition[key] = *value;
James Feist45094ad2020-04-29 14:02:30 -07001069 }
1070 else if (key == "OffsetInKiB")
1071 {
1072 const uint64_t* value = std::get_if<uint64_t>(&val);
1073 if (value == nullptr)
1074 {
1075 messages::internalError(aResp->res);
James Feist45094ad2020-04-29 14:02:30 -07001076 continue;
1077 }
1078
1079 partition["OffsetMiB"] = (*value >> 10);
1080 }
1081 else if (key == "PartitionId")
1082 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -07001083 const std::string* value = std::get_if<std::string>(&val);
1084 if (value == nullptr)
1085 {
1086 messages::internalError(aResp->res);
1087 continue;
1088 }
1089 partition["RegionId"] = *value;
James Feist45094ad2020-04-29 14:02:30 -07001090 }
1091
1092 else if (key == "PassphraseState")
1093 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -07001094 const bool* value = std::get_if<bool>(&val);
1095 if (value == nullptr)
1096 {
1097 messages::internalError(aResp->res);
1098 continue;
1099 }
1100 partition["PassphraseEnabled"] = *value;
James Feist45094ad2020-04-29 14:02:30 -07001101 }
1102 else if (key == "SizeInKiB")
1103 {
1104 const uint64_t* value = std::get_if<uint64_t>(&val);
1105 if (value == nullptr)
1106 {
1107 messages::internalError(aResp->res);
1108 BMCWEB_LOG_DEBUG
1109 << "Invalid property type for SizeInKiB";
1110 continue;
1111 }
1112 partition["SizeMiB"] = (*value >> 10);
1113 }
1114 }
1115 },
1116
1117 service, path, "org.freedesktop.DBus.Properties", "GetAll",
1118 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition");
1119}
1120
Ed Tanous23a21a12020-07-25 04:45:05 +00001121inline void getDimmData(std::shared_ptr<AsyncResp> aResp,
1122 const std::string& dimmId)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001123{
1124 BMCWEB_LOG_DEBUG << "Get available system dimm resources.";
1125 crow::connections::systemBus->async_method_call(
Ed Tanous029573d2019-02-01 10:57:49 -08001126 [dimmId, aResp{std::move(aResp)}](
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001127 const boost::system::error_code ec,
1128 const boost::container::flat_map<
1129 std::string, boost::container::flat_map<
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001130 std::string, std::vector<std::string>>>&
1131 subtree) {
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001132 if (ec)
1133 {
1134 BMCWEB_LOG_DEBUG << "DBUS response error";
1135 messages::internalError(aResp->res);
1136
1137 return;
1138 }
James Feist45094ad2020-04-29 14:02:30 -07001139 bool found = false;
1140 for (const auto& [path, object] : subtree)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001141 {
James Feist45094ad2020-04-29 14:02:30 -07001142 if (path.find(dimmId) != std::string::npos)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001143 {
James Feist45094ad2020-04-29 14:02:30 -07001144 for (const auto& [service, interfaces] : object)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001145 {
James Feist45094ad2020-04-29 14:02:30 -07001146 if (!found &&
1147 (std::find(
1148 interfaces.begin(), interfaces.end(),
1149 "xyz.openbmc_project.Inventory.Item.Dimm") !=
1150 interfaces.end()))
1151 {
1152 getDimmDataByService(aResp, dimmId, service, path);
1153 found = true;
1154 }
1155
1156 // partitions are separate as there can be multiple per
1157 // device, i.e.
1158 // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition1
1159 // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition2
1160 if (std::find(interfaces.begin(), interfaces.end(),
1161 "xyz.openbmc_project.Inventory.Item."
1162 "PersistentMemory.Partition") !=
1163 interfaces.end())
1164 {
1165 getDimmPartitionData(aResp, service, path);
1166 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001167 }
1168 }
1169 }
1170 // Object not found
James Feist45094ad2020-04-29 14:02:30 -07001171 if (!found)
1172 {
1173 messages::resourceNotFound(aResp->res, "Memory", dimmId);
1174 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001175 return;
1176 },
1177 "xyz.openbmc_project.ObjectMapper",
1178 "/xyz/openbmc_project/object_mapper",
1179 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous271584a2019-07-09 16:24:22 -07001180 "/xyz/openbmc_project/inventory", 0,
James Feist45094ad2020-04-29 14:02:30 -07001181 std::array<const char*, 2>{
1182 "xyz.openbmc_project.Inventory.Item.Dimm",
1183 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition"});
Ed Tanous271584a2019-07-09 16:24:22 -07001184}
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001185
1186class ProcessorCollection : public Node
1187{
1188 public:
1189 /*
1190 * Default Constructor
1191 */
Ed Tanous52cc1122020-07-18 13:51:21 -07001192 ProcessorCollection(App& app) :
Ed Tanous029573d2019-02-01 10:57:49 -08001193 Node(app, "/redfish/v1/Systems/system/Processors/")
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001194 {
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001195 entityPrivileges = {
1196 {boost::beast::http::verb::get, {{"Login"}}},
1197 {boost::beast::http::verb::head, {{"Login"}}},
1198 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
1199 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
1200 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
1201 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
1202 }
1203
1204 private:
1205 /**
1206 * Functions triggers appropriate requests on DBus
1207 */
Ed Tanouscb13a392020-07-25 19:02:03 +00001208 void doGet(crow::Response& res, const crow::Request&,
1209 const std::vector<std::string>&) override
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001210 {
Ed Tanous0f74e642018-11-12 15:17:05 -08001211 res.jsonValue["@odata.type"] =
1212 "#ProcessorCollection.ProcessorCollection";
1213 res.jsonValue["Name"] = "Processor Collection";
Ed Tanous0f74e642018-11-12 15:17:05 -08001214
Ed Tanous029573d2019-02-01 10:57:49 -08001215 res.jsonValue["@odata.id"] = "/redfish/v1/Systems/system/Processors/";
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001216 auto asyncResp = std::make_shared<AsyncResp>(res);
1217
Ed Tanous029573d2019-02-01 10:57:49 -08001218 getResourceList(asyncResp, "Processors",
Alpana Kumari32bee762019-04-25 04:47:57 -05001219 {"xyz.openbmc_project.Inventory.Item.Cpu",
1220 "xyz.openbmc_project.Inventory.Item.Accelerator"});
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001221 }
1222};
1223
1224class Processor : public Node
1225{
1226 public:
1227 /*
1228 * Default Constructor
1229 */
Ed Tanous52cc1122020-07-18 13:51:21 -07001230 Processor(App& app) :
Ed Tanous029573d2019-02-01 10:57:49 -08001231 Node(app, "/redfish/v1/Systems/system/Processors/<str>/", std::string())
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001232 {
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001233 entityPrivileges = {
1234 {boost::beast::http::verb::get, {{"Login"}}},
1235 {boost::beast::http::verb::head, {{"Login"}}},
1236 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
1237 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
1238 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
1239 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
1240 }
1241
1242 private:
1243 /**
1244 * Functions triggers appropriate requests on DBus
1245 */
Ed Tanouscb13a392020-07-25 19:02:03 +00001246 void doGet(crow::Response& res, const crow::Request&,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001247 const std::vector<std::string>& params) override
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001248 {
1249 // Check if there is required param, truly entering this shall be
1250 // impossible
1251 if (params.size() != 1)
1252 {
1253 messages::internalError(res);
1254
1255 res.end();
1256 return;
1257 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001258 const std::string& processorId = params[0];
Zhikui Ren029cc1f2020-08-25 15:21:41 -07001259 res.jsonValue["@odata.type"] = "#Processor.v1_9_0.Processor";
Ed Tanous029573d2019-02-01 10:57:49 -08001260 res.jsonValue["@odata.id"] =
Alpana Kumari32bee762019-04-25 04:47:57 -05001261 "/redfish/v1/Systems/system/Processors/" + processorId;
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001262
Ed Tanous029573d2019-02-01 10:57:49 -08001263 auto asyncResp = std::make_shared<AsyncResp>(res);
1264
Alpana Kumari32bee762019-04-25 04:47:57 -05001265 getCpuData(asyncResp, processorId,
1266 {"xyz.openbmc_project.Inventory.Item.Cpu",
Zhikui Ren5e54a362020-07-13 15:31:38 -07001267 "xyz.openbmc_project.Inventory.Decorator.Asset",
Alpana Kumari32bee762019-04-25 04:47:57 -05001268 "xyz.openbmc_project.Inventory.Item.Accelerator"});
Ed Tanous029573d2019-02-01 10:57:49 -08001269 }
1270};
1271
1272class MemoryCollection : public Node
1273{
1274 public:
1275 /*
1276 * Default Constructor
1277 */
Ed Tanous52cc1122020-07-18 13:51:21 -07001278 MemoryCollection(App& app) : Node(app, "/redfish/v1/Systems/system/Memory/")
Ed Tanous029573d2019-02-01 10:57:49 -08001279 {
1280 entityPrivileges = {
1281 {boost::beast::http::verb::get, {{"Login"}}},
1282 {boost::beast::http::verb::head, {{"Login"}}},
1283 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
1284 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
1285 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
1286 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
1287 }
1288
1289 private:
1290 /**
1291 * Functions triggers appropriate requests on DBus
1292 */
Ed Tanouscb13a392020-07-25 19:02:03 +00001293 void doGet(crow::Response& res, const crow::Request&,
1294 const std::vector<std::string>&) override
Ed Tanous029573d2019-02-01 10:57:49 -08001295 {
Ed Tanous0f74e642018-11-12 15:17:05 -08001296 res.jsonValue["@odata.type"] = "#MemoryCollection.MemoryCollection";
1297 res.jsonValue["Name"] = "Memory Module Collection";
James Feistc50e7c62020-07-27 15:39:36 -07001298 res.jsonValue["@odata.id"] = "/redfish/v1/Systems/system/Memory";
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001299 auto asyncResp = std::make_shared<AsyncResp>(res);
1300
Ed Tanous029573d2019-02-01 10:57:49 -08001301 getResourceList(asyncResp, "Memory",
Alpana Kumari32bee762019-04-25 04:47:57 -05001302 {"xyz.openbmc_project.Inventory.Item.Dimm"});
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001303 }
1304};
1305
1306class Memory : public Node
1307{
1308 public:
1309 /*
1310 * Default Constructor
1311 */
Ed Tanous52cc1122020-07-18 13:51:21 -07001312 Memory(App& app) :
Ed Tanous029573d2019-02-01 10:57:49 -08001313 Node(app, "/redfish/v1/Systems/system/Memory/<str>/", std::string())
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001314 {
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001315 entityPrivileges = {
1316 {boost::beast::http::verb::get, {{"Login"}}},
1317 {boost::beast::http::verb::head, {{"Login"}}},
1318 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
1319 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
1320 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
1321 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
1322 }
1323
1324 private:
1325 /**
1326 * Functions triggers appropriate requests on DBus
1327 */
Ed Tanouscb13a392020-07-25 19:02:03 +00001328 void doGet(crow::Response& res, const crow::Request&,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001329 const std::vector<std::string>& params) override
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001330 {
1331 // Check if there is required param, truly entering this shall be
1332 // impossible
Ed Tanous029573d2019-02-01 10:57:49 -08001333 if (params.size() != 1)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001334 {
1335 messages::internalError(res);
1336 res.end();
1337 return;
1338 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001339 const std::string& dimmId = params[0];
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001340
James Feistc50e7c62020-07-27 15:39:36 -07001341 res.jsonValue["@odata.type"] = "#Memory.v1_7_0.Memory";
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001342 res.jsonValue["@odata.id"] =
Ed Tanous029573d2019-02-01 10:57:49 -08001343 "/redfish/v1/Systems/system/Memory/" + dimmId;
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001344 auto asyncResp = std::make_shared<AsyncResp>(res);
1345
Ed Tanous029573d2019-02-01 10:57:49 -08001346 getDimmData(asyncResp, dimmId);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001347 }
1348};
1349
1350} // namespace redfish