blob: e670037f51af7536714050f9919c160ca0aec57b [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 }
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700106 else
107 {
108 aResp->res.jsonValue["Status"]["State"] = "Enabled";
109 present = true;
110 }
Ed Tanous883b3112018-12-06 16:13:35 -0800111 aResp->res.jsonValue["TotalCores"] = *coresCount;
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200112 }
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700113 else if (property.first == "Socket")
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -0600114 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500115 const std::string* value =
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -0600116 std::get_if<std::string>(&property.second);
117 if (value != nullptr)
118 {
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700119 aResp->res.jsonValue["Socket"] = *value;
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -0600120 }
121 }
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700122 else if (property.first == "ThreadCount")
Gunnar Millsf9dcc112020-02-13 13:19:43 -0600123 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700124 const int64_t* value = std::get_if<int64_t>(&property.second);
125 if (value != nullptr)
126 {
127 aResp->res.jsonValue["TotalThreads"] = *value;
128 }
Gunnar Millsf9dcc112020-02-13 13:19:43 -0600129 }
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700130 else if (property.first == "Family")
Gunnar Millsf9dcc112020-02-13 13:19:43 -0600131 {
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700132 const std::string* value =
133 std::get_if<std::string>(&property.second);
134 if (value != nullptr)
135 {
136 aResp->res.jsonValue["ProcessorId"]["EffectiveFamily"] =
137 *value;
138 }
Gunnar Millsf9dcc112020-02-13 13:19:43 -0600139 }
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700140 else if (property.first == "Id")
Gunnar Millsf9dcc112020-02-13 13:19:43 -0600141 {
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700142 const uint64_t* value = std::get_if<uint64_t>(&property.second);
143 if (value != nullptr && *value != 0)
144 {
145 present = true;
146 aResp->res
147 .jsonValue["ProcessorId"]["IdentificationRegisters"] =
148 boost::lexical_cast<std::string>(*value);
149 }
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -0600150 }
151 }
152 }
153
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700154 if (present == false)
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -0600155 {
156 aResp->res.jsonValue["Status"]["State"] = "Absent";
157 aResp->res.jsonValue["Status"]["Health"] = "OK";
158 }
159 else
160 {
161 aResp->res.jsonValue["Status"]["State"] = "Enabled";
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700162 if (functional)
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -0600163 {
164 aResp->res.jsonValue["Status"]["Health"] = "OK";
165 }
166 else
167 {
168 aResp->res.jsonValue["Status"]["Health"] = "Critical";
169 }
170 }
171
172 return;
173}
174
Ed Tanous23a21a12020-07-25 04:45:05 +0000175inline void getCpuDataByService(std::shared_ptr<AsyncResp> aResp,
176 const std::string& cpuId,
177 const std::string& service,
178 const std::string& objPath)
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -0600179{
180 BMCWEB_LOG_DEBUG << "Get available system cpu resources by service.";
181
182 crow::connections::systemBus->async_method_call(
183 [cpuId, service, objPath, aResp{std::move(aResp)}](
184 const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500185 const dbus::utility::ManagedObjectType& dbusData) {
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -0600186 if (ec)
187 {
188 BMCWEB_LOG_DEBUG << "DBUS response error";
189 messages::internalError(aResp->res);
190 return;
191 }
192 aResp->res.jsonValue["Id"] = cpuId;
193 aResp->res.jsonValue["Name"] = "Processor";
194 aResp->res.jsonValue["ProcessorType"] = "CPU";
195
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700196 bool slotPresent = false;
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -0600197 std::string corePath = objPath + "/core";
198 size_t totalCores = 0;
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500199 for (const auto& object : dbusData)
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -0600200 {
201 if (object.first.str == objPath)
202 {
203 getCpuDataByInterface(aResp, object.second);
204 }
205 else if (boost::starts_with(object.first.str, corePath))
206 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500207 for (const auto& interface : object.second)
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -0600208 {
209 if (interface.first ==
210 "xyz.openbmc_project.Inventory.Item")
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200211 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500212 for (const auto& property : interface.second)
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -0600213 {
214 if (property.first == "Present")
215 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500216 const bool* present =
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -0600217 std::get_if<bool>(&property.second);
218 if (present != nullptr)
219 {
220 if (*present == true)
221 {
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700222 slotPresent = true;
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -0600223 totalCores++;
224 }
225 }
226 }
227 }
Gunnar Millsb957ba52019-01-31 15:58:15 -0600228 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200229 }
230 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200231 }
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -0600232 // In getCpuDataByInterface(), state and health are set
233 // based on the present and functional status. If core
234 // count is zero, then it has a higher precedence.
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700235 if (slotPresent)
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -0600236 {
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700237 if (totalCores == 0)
238 {
239 // Slot is not populated, set status end return
240 aResp->res.jsonValue["Status"]["State"] = "Absent";
241 aResp->res.jsonValue["Status"]["Health"] = "OK";
242 }
243 aResp->res.jsonValue["TotalCores"] = totalCores;
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -0600244 }
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -0600245 return;
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200246 },
RAJESWARAN THILLAIGOVINDANec8faf92019-02-21 10:59:03 -0600247 service, "/xyz/openbmc_project/inventory",
248 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200249}
250
Ed Tanous23a21a12020-07-25 04:45:05 +0000251inline void getCpuAssetData(std::shared_ptr<AsyncResp> aResp,
252 const std::string& service,
253 const std::string& objPath)
Zhikui Ren5e54a362020-07-13 15:31:38 -0700254{
255 BMCWEB_LOG_DEBUG << "Get Cpu Asset Data";
256 crow::connections::systemBus->async_method_call(
257 [objPath, aResp{std::move(aResp)}](
258 const boost::system::error_code ec,
259 const boost::container::flat_map<
260 std::string, std::variant<std::string, uint32_t, uint16_t,
261 bool>>& properties) {
262 if (ec)
263 {
264 BMCWEB_LOG_DEBUG << "DBUS response error";
265 messages::internalError(aResp->res);
266 return;
267 }
268
269 for (const auto& property : properties)
270 {
271 if (property.first == "SerialNumber")
272 {
273 const std::string* sn =
274 std::get_if<std::string>(&property.second);
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700275 if (sn != nullptr && !sn->empty())
Zhikui Ren5e54a362020-07-13 15:31:38 -0700276 {
277 aResp->res.jsonValue["SerialNumber"] = *sn;
278 }
279 }
280 else if (property.first == "Model")
281 {
282 const std::string* model =
283 std::get_if<std::string>(&property.second);
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700284 if (model != nullptr && !model->empty())
Zhikui Ren5e54a362020-07-13 15:31:38 -0700285 {
286 aResp->res.jsonValue["Model"] = *model;
287 }
288 }
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700289 else if (property.first == "Manufacturer")
290 {
291
292 const std::string* mfg =
293 std::get_if<std::string>(&property.second);
294 if (mfg != nullptr)
295 {
296 aResp->res.jsonValue["Manufacturer"] = *mfg;
297
298 // Otherwise would be unexpected.
299 if (mfg->find("Intel") != std::string::npos)
300 {
301 aResp->res.jsonValue["ProcessorArchitecture"] =
302 "x86";
303 aResp->res.jsonValue["InstructionSet"] = "x86-64";
304 }
305 else if (mfg->find("IBM") != std::string::npos)
306 {
307 aResp->res.jsonValue["ProcessorArchitecture"] =
308 "Power";
309 aResp->res.jsonValue["InstructionSet"] = "PowerISA";
310 }
311 }
312 }
Zhikui Ren5e54a362020-07-13 15:31:38 -0700313 }
314 },
315 service, objPath, "org.freedesktop.DBus.Properties", "GetAll",
316 "xyz.openbmc_project.Inventory.Decorator.Asset");
317}
318
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700319inline void getCpuRevisionData(std::shared_ptr<AsyncResp> aResp,
320 const std::string& service,
321 const std::string& objPath)
322{
323 BMCWEB_LOG_DEBUG << "Get Cpu Revision Data";
324 crow::connections::systemBus->async_method_call(
325 [objPath, aResp{std::move(aResp)}](
326 const boost::system::error_code ec,
327 const boost::container::flat_map<
328 std::string, std::variant<std::string, uint32_t, uint16_t,
329 bool>>& properties) {
330 if (ec)
331 {
332 BMCWEB_LOG_DEBUG << "DBUS response error";
333 messages::internalError(aResp->res);
334 return;
335 }
336
337 for (const auto& property : properties)
338 {
339 if (property.first == "Version")
340 {
341 const std::string* ver =
342 std::get_if<std::string>(&property.second);
343 if (ver != nullptr)
344 {
345 aResp->res.jsonValue["Version"] = *ver;
346 }
347 break;
348 }
349 }
350 },
351 service, objPath, "org.freedesktop.DBus.Properties", "GetAll",
352 "xyz.openbmc_project.Inventory.Decorator.Revision");
353}
354
Ed Tanous23a21a12020-07-25 04:45:05 +0000355inline void getAcceleratorDataByService(std::shared_ptr<AsyncResp> aResp,
356 const std::string& acclrtrId,
357 const std::string& service,
358 const std::string& objPath)
Alpana Kumari32bee762019-04-25 04:47:57 -0500359{
360 BMCWEB_LOG_DEBUG
361 << "Get available system Accelerator resources by service.";
362 crow::connections::systemBus->async_method_call(
363 [acclrtrId, aResp{std::move(aResp)}](
364 const boost::system::error_code ec,
365 const boost::container::flat_map<
Santosh Puranik94e1b822019-07-24 04:48:32 -0500366 std::string, std::variant<std::string, uint32_t, uint16_t,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500367 bool>>& properties) {
Alpana Kumari32bee762019-04-25 04:47:57 -0500368 if (ec)
369 {
370 BMCWEB_LOG_DEBUG << "DBUS response error";
371 messages::internalError(aResp->res);
372 return;
373 }
374 aResp->res.jsonValue["Id"] = acclrtrId;
375 aResp->res.jsonValue["Name"] = "Processor";
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500376 const bool* accPresent = nullptr;
377 const bool* accFunctional = nullptr;
Alpana Kumari32bee762019-04-25 04:47:57 -0500378
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500379 for (const auto& property : properties)
Alpana Kumari32bee762019-04-25 04:47:57 -0500380 {
381 if (property.first == "Functional")
382 {
Santosh Puranik94e1b822019-07-24 04:48:32 -0500383 accFunctional = std::get_if<bool>(&property.second);
Alpana Kumari32bee762019-04-25 04:47:57 -0500384 }
385 else if (property.first == "Present")
386 {
Santosh Puranik94e1b822019-07-24 04:48:32 -0500387 accPresent = std::get_if<bool>(&property.second);
Alpana Kumari32bee762019-04-25 04:47:57 -0500388 }
389 }
390
Alpana Kumaric24e6b82020-10-01 06:58:46 -0500391 std::string state = "Enabled";
392 std::string health = "OK";
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700393
Alpana Kumaric24e6b82020-10-01 06:58:46 -0500394 if (accPresent != nullptr && *accPresent == false)
Alpana Kumari32bee762019-04-25 04:47:57 -0500395 {
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700396 state = "Absent";
Alpana Kumari32bee762019-04-25 04:47:57 -0500397 }
Alpana Kumaric24e6b82020-10-01 06:58:46 -0500398
399 if ((accFunctional != nullptr) && (*accFunctional == false))
400 {
401 if (state == "Enabled")
402 {
403 health = "Critical";
404 }
Alpana Kumaric24e6b82020-10-01 06:58:46 -0500405 }
406
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700407 aResp->res.jsonValue["Status"]["State"] = state;
Alpana Kumaric24e6b82020-10-01 06:58:46 -0500408 aResp->res.jsonValue["Status"]["Health"] = health;
Alpana Kumari32bee762019-04-25 04:47:57 -0500409 aResp->res.jsonValue["ProcessorType"] = "Accelerator";
410 },
411 service, objPath, "org.freedesktop.DBus.Properties", "GetAll", "");
412}
413
Ed Tanous23a21a12020-07-25 04:45:05 +0000414inline void getCpuData(std::shared_ptr<AsyncResp> aResp,
415 const std::string& cpuId,
416 const std::vector<const char*> inventoryItems)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200417{
418 BMCWEB_LOG_DEBUG << "Get available system cpu resources.";
Alpana Kumari32bee762019-04-25 04:47:57 -0500419
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200420 crow::connections::systemBus->async_method_call(
Ed Tanous029573d2019-02-01 10:57:49 -0800421 [cpuId, aResp{std::move(aResp)}](
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200422 const boost::system::error_code ec,
423 const boost::container::flat_map<
424 std::string, boost::container::flat_map<
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500425 std::string, std::vector<std::string>>>&
426 subtree) {
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200427 if (ec)
428 {
429 BMCWEB_LOG_DEBUG << "DBUS response error";
430 messages::internalError(aResp->res);
431 return;
432 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500433 for (const auto& object : subtree)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200434 {
435 if (boost::ends_with(object.first, cpuId))
436 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500437 for (const auto& service : object.second)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200438 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500439 for (const auto& inventory : service.second)
Zhikui Ren5e54a362020-07-13 15:31:38 -0700440 {
441 if (inventory == "xyz.openbmc_project."
442 "Inventory.Decorator.Asset")
443 {
444 getCpuAssetData(aResp, service.first,
445 object.first);
446 }
447 else if (inventory ==
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700448 "xyz.openbmc_project."
449 "Inventory.Decorator.Revision")
450 {
451 getCpuRevisionData(aResp, service.first,
452 object.first);
453 }
454 else if (inventory == "xyz.openbmc_project."
455 "Inventory.Item.Cpu")
Alpana Kumari32bee762019-04-25 04:47:57 -0500456 {
457 getCpuDataByService(aResp, cpuId, service.first,
458 object.first);
459 }
460 else if (inventory == "xyz.openbmc_project."
461 "Inventory.Item.Accelerator")
462 {
463 getAcceleratorDataByService(
464 aResp, cpuId, service.first, object.first);
465 }
Zhikui Ren5e54a362020-07-13 15:31:38 -0700466 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200467 }
Zhikui Ren5e54a362020-07-13 15:31:38 -0700468 return;
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200469 }
470 }
471 // Object not found
472 messages::resourceNotFound(aResp->res, "Processor", cpuId);
473 return;
474 },
475 "xyz.openbmc_project.ObjectMapper",
476 "/xyz/openbmc_project/object_mapper",
477 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous271584a2019-07-09 16:24:22 -0700478 "/xyz/openbmc_project/inventory", 0, inventoryItems);
479}
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200480
James Feistc50e7c62020-07-27 15:39:36 -0700481using DimmProperty =
482 std::variant<std::string, std::vector<uint32_t>, std::vector<uint16_t>,
483 uint64_t, uint32_t, uint16_t, uint8_t, bool>;
484
485using DimmProperties = boost::container::flat_map<std::string, DimmProperty>;
486
Ed Tanous80789c82020-08-19 09:19:09 -0700487inline void dimmPropToHex(std::shared_ptr<AsyncResp> aResp, const char* key,
488 const std::pair<std::string, DimmProperty>& property)
James Feistc50e7c62020-07-27 15:39:36 -0700489{
490 const uint16_t* value = std::get_if<uint16_t>(&property.second);
491 if (value == nullptr)
492 {
493 messages::internalError(aResp->res);
494 BMCWEB_LOG_DEBUG << "Invalid property type for " << property.first;
495 return;
496 }
497
498 aResp->res.jsonValue[key] = (boost::format("0x%04x") % *value).str();
499}
500
Ed Tanous80789c82020-08-19 09:19:09 -0700501inline void getPersistentMemoryProperties(std::shared_ptr<AsyncResp> aResp,
502 const DimmProperties& properties)
James Feistc50e7c62020-07-27 15:39:36 -0700503{
504 for (const auto& property : properties)
505 {
506 if (property.first == "ModuleManufacturerID")
507 {
508 dimmPropToHex(aResp, "ModuleManufacturerID", property);
509 }
510 else if (property.first == "ModuleProductID")
511 {
512 dimmPropToHex(aResp, "ModuleProductID", property);
513 }
514 else if (property.first == "SubsystemVendorID")
515 {
516 dimmPropToHex(aResp, "MemorySubsystemControllerManufacturerID",
517 property);
518 }
519 else if (property.first == "SubsystemDeviceID")
520 {
521 dimmPropToHex(aResp, "MemorySubsystemControllerProductID",
522 property);
523 }
524 else if (property.first == "VolatileRegionSizeLimitInKiB")
525 {
526 const uint64_t* value = std::get_if<uint64_t>(&property.second);
527
528 if (value == nullptr)
529 {
530 messages::internalError(aResp->res);
531 BMCWEB_LOG_DEBUG << "Invalid property type for "
532 "VolatileRegionSizeLimitKiB";
533 continue;
534 }
535 aResp->res.jsonValue["VolatileRegionSizeLimitMiB"] = (*value) >> 10;
536 }
537 else if (property.first == "PmRegionSizeLimitInKiB")
538 {
539 const uint64_t* value = std::get_if<uint64_t>(&property.second);
540
541 if (value == nullptr)
542 {
543 messages::internalError(aResp->res);
544 BMCWEB_LOG_DEBUG
545 << "Invalid property type for PmRegioSizeLimitKiB";
546 continue;
547 }
548 aResp->res.jsonValue["PersistentRegionSizeLimitMiB"] =
549 (*value) >> 10;
550 }
551 else if (property.first == "VolatileSizeInKiB")
552 {
553 const uint64_t* value = std::get_if<uint64_t>(&property.second);
554
555 if (value == nullptr)
556 {
557 messages::internalError(aResp->res);
558 BMCWEB_LOG_DEBUG
559 << "Invalid property type for VolatileSizeInKiB";
560 continue;
561 }
562 aResp->res.jsonValue["VolatileSizeMiB"] = (*value) >> 10;
563 }
564 else if (property.first == "PmSizeInKiB")
565 {
566 const uint64_t* value = std::get_if<uint64_t>(&property.second);
567 if (value == nullptr)
568 {
569 messages::internalError(aResp->res);
570 BMCWEB_LOG_DEBUG << "Invalid property type for PmSizeInKiB";
571 continue;
572 }
573 aResp->res.jsonValue["NonVolatileSizeMiB"] = (*value) >> 10;
574 }
575 else if (property.first == "CacheSizeInKB")
576 {
577 const uint64_t* value = std::get_if<uint64_t>(&property.second);
578 if (value == nullptr)
579 {
580 messages::internalError(aResp->res);
581 BMCWEB_LOG_DEBUG << "Invalid property type for CacheSizeInKB";
582 continue;
583 }
584 aResp->res.jsonValue["CacheSizeMiB"] = (*value >> 10);
585 }
586
587 else if (property.first == "VoltaileRegionMaxSizeInKib")
588 {
589 const uint64_t* value = std::get_if<uint64_t>(&property.second);
590
591 if (value == nullptr)
592 {
593 messages::internalError(aResp->res);
594 BMCWEB_LOG_DEBUG << "Invalid property type for "
595 "VolatileRegionMaxSizeInKib";
596 continue;
597 }
598 aResp->res.jsonValue["VolatileRegionSizeMaxMiB"] = (*value) >> 10;
599 }
600 else if (property.first == "PmRegionMaxSizeInKiB")
601 {
602 const uint64_t* value = std::get_if<uint64_t>(&property.second);
603
604 if (value == nullptr)
605 {
606 messages::internalError(aResp->res);
607 BMCWEB_LOG_DEBUG
608 << "Invalid property type for PmRegionMaxSizeInKiB";
609 continue;
610 }
611 aResp->res.jsonValue["PersistentRegionSizeMaxMiB"] = (*value) >> 10;
612 }
613 else if (property.first == "AllocationIncrementInKiB")
614 {
615 const uint64_t* value = std::get_if<uint64_t>(&property.second);
616
617 if (value == nullptr)
618 {
619 messages::internalError(aResp->res);
620 BMCWEB_LOG_DEBUG << "Invalid property type for "
621 "AllocationIncrementInKiB";
622 continue;
623 }
624 aResp->res.jsonValue["AllocationIncrementMiB"] = (*value) >> 10;
625 }
626 else if (property.first == "AllocationAlignmentInKiB")
627 {
628 const uint64_t* value = std::get_if<uint64_t>(&property.second);
629
630 if (value == nullptr)
631 {
632 messages::internalError(aResp->res);
633 BMCWEB_LOG_DEBUG << "Invalid property type for "
634 "AllocationAlignmentInKiB";
635 continue;
636 }
637 aResp->res.jsonValue["AllocationAlignmentMiB"] = (*value) >> 10;
638 }
639 else if (property.first == "VolatileRegionNumberLimit")
640 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700641 const uint64_t* value = std::get_if<uint64_t>(&property.second);
642 if (value == nullptr)
643 {
644 messages::internalError(aResp->res);
645 continue;
646 }
647 aResp->res.jsonValue["VolatileRegionNumberLimit"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700648 }
649 else if (property.first == "PmRegionNumberLimit")
650 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700651 const uint64_t* value = std::get_if<uint64_t>(&property.second);
652 if (value == nullptr)
653 {
654 messages::internalError(aResp->res);
655 continue;
656 }
657 aResp->res.jsonValue["PersistentRegionNumberLimit"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700658 }
659 else if (property.first == "SpareDeviceCount")
660 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700661 const uint64_t* value = std::get_if<uint64_t>(&property.second);
662 if (value == nullptr)
663 {
664 messages::internalError(aResp->res);
665 continue;
666 }
667 aResp->res.jsonValue["SpareDeviceCount"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700668 }
669 else if (property.first == "IsSpareDeviceInUse")
670 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700671 const bool* value = std::get_if<bool>(&property.second);
672 if (value == nullptr)
673 {
674 messages::internalError(aResp->res);
675 continue;
676 }
677 aResp->res.jsonValue["IsSpareDeviceEnabled"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700678 }
679 else if (property.first == "IsRankSpareEnabled")
680 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700681 const bool* value = std::get_if<bool>(&property.second);
682 if (value == nullptr)
683 {
684 messages::internalError(aResp->res);
685 continue;
686 }
687 aResp->res.jsonValue["IsRankSpareEnabled"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700688 }
689 else if (property.first == "MaxAveragePowerLimitmW")
690 {
691 const auto* value =
692 std::get_if<std::vector<uint32_t>>(&property.second);
693 if (value == nullptr)
694 {
695 messages::internalError(aResp->res);
696 BMCWEB_LOG_DEBUG << "Invalid property type for "
697 "MaxAveragePowerLimitmW";
698 continue;
699 }
700 aResp->res.jsonValue["MaxTDPMilliWatts"] = *value;
701 }
James Feistc50e7c62020-07-27 15:39:36 -0700702 else if (property.first == "ConfigurationLocked")
703 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700704 const bool* value = std::get_if<bool>(&property.second);
705 if (value == nullptr)
706 {
707 messages::internalError(aResp->res);
708 continue;
709 }
710 aResp->res.jsonValue["ConfigurationLocked"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700711 }
712 else if (property.first == "AllowedMemoryModes")
713 {
714 const std::string* value =
715 std::get_if<std::string>(&property.second);
716 if (value == nullptr)
717 {
718 messages::internalError(aResp->res);
719 BMCWEB_LOG_DEBUG << "Invalid property type for FormFactor";
720 continue;
721 }
722 constexpr const std::array<const char*, 3> values{"Volatile",
723 "PMEM", "Block"};
724
725 for (const char* v : values)
726 {
727 if (boost::ends_with(*value, v))
728 {
729 aResp->res.jsonValue["OperatingMemoryModes "] = v;
730 break;
731 }
732 }
733 }
734 else if (property.first == "MemoryMedia")
735 {
736 const std::string* value =
737 std::get_if<std::string>(&property.second);
738 if (value == nullptr)
739 {
740 messages::internalError(aResp->res);
741 BMCWEB_LOG_DEBUG << "Invalid property type for MemoryMedia";
742 continue;
743 }
744 constexpr const std::array<const char*, 3> values{"DRAM", "NAND",
745 "Intel3DXPoint"};
746
747 for (const char* v : values)
748 {
749 if (boost::ends_with(*value, v))
750 {
751 aResp->res.jsonValue["MemoryMedia"] = v;
752 break;
753 }
754 }
755 }
James Feistc50e7c62020-07-27 15:39:36 -0700756 // PersistantMemory.SecurityCapabilites interface
757 else if (property.first == "ConfigurationLockCapable" ||
758 property.first == "DataLockCapable" ||
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700759 property.first == "PassphraseCapable")
760 {
761 const bool* value = std::get_if<bool>(&property.second);
762 if (value == nullptr)
763 {
764 messages::internalError(aResp->res);
765 continue;
766 }
767 aResp->res.jsonValue["SecurityCapabilities"][property.first] =
768 *value;
769 }
770 else if (property.first == "MaxPassphraseCount" ||
James Feistc50e7c62020-07-27 15:39:36 -0700771 property.first == "PassphraseLockLimit")
772 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700773 const uint64_t* value = std::get_if<uint64_t>(&property.second);
774 if (value == nullptr)
775 {
776 messages::internalError(aResp->res);
777 continue;
778 }
James Feistc50e7c62020-07-27 15:39:36 -0700779 aResp->res.jsonValue["SecurityCapabilities"][property.first] =
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700780 *value;
James Feistc50e7c62020-07-27 15:39:36 -0700781 }
782 }
783}
784
Ed Tanous80789c82020-08-19 09:19:09 -0700785inline void getDimmDataByService(std::shared_ptr<AsyncResp> aResp,
786 const std::string& dimmId,
787 const std::string& service,
788 const std::string& objPath)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200789{
James Feist35e257a2020-06-05 13:30:51 -0700790 auto health = std::make_shared<HealthPopulate>(aResp);
791 health->selfPath = objPath;
792 health->populate();
793
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200794 BMCWEB_LOG_DEBUG << "Get available system components.";
795 crow::connections::systemBus->async_method_call(
James Feistc50e7c62020-07-27 15:39:36 -0700796 [dimmId, aResp{std::move(aResp)}](const boost::system::error_code ec,
797 const DimmProperties& properties) {
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200798 if (ec)
799 {
800 BMCWEB_LOG_DEBUG << "DBUS response error";
801 messages::internalError(aResp->res);
802
803 return;
804 }
805 aResp->res.jsonValue["Id"] = dimmId;
806 aResp->res.jsonValue["Name"] = "DIMM Slot";
807
808 const auto memorySizeProperty = properties.find("MemorySizeInKB");
Gunnar Millsaceb7fc2018-12-10 15:17:20 -0600809 if (memorySizeProperty != properties.end())
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200810 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500811 const uint32_t* memorySize =
Ed Tanousabf2add2019-01-22 16:40:12 -0800812 std::get_if<uint32_t>(&memorySizeProperty->second);
Gunnar Millsaceb7fc2018-12-10 15:17:20 -0600813 if (memorySize == nullptr)
814 {
815 // Important property not in desired type
816 messages::internalError(aResp->res);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200817
Gunnar Millsaceb7fc2018-12-10 15:17:20 -0600818 return;
819 }
820 if (*memorySize == 0)
821 {
822 // Slot is not populated, set status end return
823 aResp->res.jsonValue["Status"]["State"] = "Absent";
824 aResp->res.jsonValue["Status"]["Health"] = "OK";
825 // HTTP Code will be set up automatically, just return
826 return;
827 }
828 aResp->res.jsonValue["CapacityMiB"] = (*memorySize >> 10);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200829 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200830 aResp->res.jsonValue["Status"]["State"] = "Enabled";
831 aResp->res.jsonValue["Status"]["Health"] = "OK";
832
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500833 for (const auto& property : properties)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200834 {
835 if (property.first == "MemoryDataWidth")
836 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700837 const uint16_t* value =
838 std::get_if<uint16_t>(&property.second);
839 if (value == nullptr)
840 {
841 continue;
842 }
843 aResp->res.jsonValue["DataWidthBits"] = *value;
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200844 }
Manojkiran Eda7e236ca2019-06-25 23:06:32 +0530845 else if (property.first == "PartNumber")
846 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700847 const std::string* value =
848 std::get_if<std::string>(&property.second);
849 if (value == nullptr)
850 {
851 continue;
852 }
853 aResp->res.jsonValue["PartNumber"] = *value;
Manojkiran Eda7e236ca2019-06-25 23:06:32 +0530854 }
855 else if (property.first == "SerialNumber")
856 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700857 const std::string* value =
858 std::get_if<std::string>(&property.second);
859 if (value == nullptr)
860 {
861 continue;
862 }
863 aResp->res.jsonValue["SerialNumber"] = *value;
Manojkiran Eda7e236ca2019-06-25 23:06:32 +0530864 }
865 else if (property.first == "Manufacturer")
866 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700867 const std::string* value =
868 std::get_if<std::string>(&property.second);
869 if (value == nullptr)
870 {
871 continue;
872 }
873 aResp->res.jsonValue["Manufacturer"] = *value;
Manojkiran Eda7e236ca2019-06-25 23:06:32 +0530874 }
James Feistc50e7c62020-07-27 15:39:36 -0700875 else if (property.first == "RevisionCode")
876 {
877 const uint16_t* value =
878 std::get_if<uint16_t>(&property.second);
879
880 if (value == nullptr)
881 {
882 messages::internalError(aResp->res);
883 BMCWEB_LOG_DEBUG
884 << "Invalid property type for RevisionCode";
885 continue;
886 }
887 aResp->res.jsonValue["FirmwareRevision"] =
888 std::to_string(*value);
889 }
890 else if (property.first == "MemoryTotalWidth")
891 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700892 const uint16_t* value =
893 std::get_if<uint16_t>(&property.second);
894 if (value == nullptr)
895 {
896 continue;
897 }
898 aResp->res.jsonValue["BusWidthBits"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700899 }
900 else if (property.first == "ECC")
901 {
902 const std::string* value =
903 std::get_if<std::string>(&property.second);
904 if (value == nullptr)
905 {
906 messages::internalError(aResp->res);
907 BMCWEB_LOG_DEBUG << "Invalid property type for ECC";
908 continue;
909 }
910 constexpr const std::array<const char*, 4> values{
911 "NoECC", "SingleBitECC", "MultiBitECC",
912 "AddressParity"};
913
914 for (const char* v : values)
915 {
916 if (boost::ends_with(*value, v))
917 {
918 aResp->res.jsonValue["ErrorCorrection"] = v;
919 break;
920 }
921 }
922 }
923 else if (property.first == "FormFactor")
924 {
925 const std::string* value =
926 std::get_if<std::string>(&property.second);
927 if (value == nullptr)
928 {
929 messages::internalError(aResp->res);
930 BMCWEB_LOG_DEBUG
931 << "Invalid property type for FormFactor";
932 continue;
933 }
934 constexpr const std::array<const char*, 11> values{
935 "RDIMM", "UDIMM", "SO_DIMM",
936 "LRDIMM", "Mini_RDIMM", "Mini_UDIMM",
937 "SO_RDIMM_72b", "SO_UDIMM_72b", "SO_DIMM_16b",
938 "SO_DIMM_32b", "Die"};
939
940 for (const char* v : values)
941 {
942 if (boost::ends_with(*value, v))
943 {
944 aResp->res.jsonValue["BaseModuleType"] = v;
945 break;
946 }
947 }
948 }
949 else if (property.first == "AllowedSpeedsMT")
950 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700951 const std::vector<uint16_t>* value =
952 std::get_if<std::vector<uint16_t>>(&property.second);
953 if (value == nullptr)
954 {
955 continue;
956 }
957 nlohmann::json& jValue =
958 aResp->res.jsonValue["AllowedSpeedsMHz"];
959 jValue = nlohmann::json::array();
960 for (uint16_t subVal : *value)
961 {
962 jValue.push_back(subVal);
963 }
James Feistc50e7c62020-07-27 15:39:36 -0700964 }
965 else if (property.first == "MemoryAttributes")
966 {
967 const uint8_t* value =
968 std::get_if<uint8_t>(&property.second);
969
970 if (value == nullptr)
971 {
972 messages::internalError(aResp->res);
973 BMCWEB_LOG_DEBUG
974 << "Invalid property type for MemoryAttributes";
975 continue;
976 }
977 aResp->res.jsonValue["RankCount"] =
978 static_cast<uint64_t>(*value);
979 }
980 else if (property.first == "MemoryConfiguredSpeedInMhz")
981 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700982 const uint16_t* value =
983 std::get_if<uint16_t>(&property.second);
984 if (value == nullptr)
985 {
986 continue;
987 }
988 aResp->res.jsonValue["OperatingSpeedMhz"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700989 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200990 else if (property.first == "MemoryType")
991 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500992 const auto* value =
Ed Tanousabf2add2019-01-22 16:40:12 -0800993 std::get_if<std::string>(&property.second);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200994 if (value != nullptr)
995 {
James Feistc50e7c62020-07-27 15:39:36 -0700996 size_t idx = value->rfind(".");
997 if (idx == std::string::npos ||
998 idx + 1 >= value->size())
999 {
1000 messages::internalError(aResp->res);
1001 BMCWEB_LOG_DEBUG << "Invalid property type for "
1002 "MemoryType";
1003 }
1004 std::string result = value->substr(idx + 1);
1005 aResp->res.jsonValue["MemoryDeviceType"] = result;
1006 if (value->find("DDR") != std::string::npos)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001007 {
1008 aResp->res.jsonValue["MemoryType"] = "DRAM";
1009 }
James Feistc50e7c62020-07-27 15:39:36 -07001010 else if (boost::ends_with(*value, "Logical"))
1011 {
1012 aResp->res.jsonValue["MemoryType"] = "IntelOptane";
1013 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001014 }
1015 }
James Feistc50e7c62020-07-27 15:39:36 -07001016 // memory location interface
1017 else if (property.first == "Channel" ||
1018 property.first == "MemoryController" ||
1019 property.first == "Slot" || property.first == "Socket")
1020 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -07001021 const std::string* value =
1022 std::get_if<std::string>(&property.second);
1023 if (value == nullptr)
1024 {
1025 messages::internalError(aResp->res);
1026 continue;
1027 }
James Feistc50e7c62020-07-27 15:39:36 -07001028 aResp->res.jsonValue["MemoryLocation"][property.first] =
Ed Tanous5fb91ba2020-09-28 15:41:28 -07001029 *value;
James Feistc50e7c62020-07-27 15:39:36 -07001030 }
1031 else
1032 {
1033 getPersistentMemoryProperties(aResp, properties);
1034 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001035 }
1036 },
1037 service, objPath, "org.freedesktop.DBus.Properties", "GetAll", "");
1038}
1039
Ed Tanous23a21a12020-07-25 04:45:05 +00001040inline void getDimmPartitionData(std::shared_ptr<AsyncResp> aResp,
1041 const std::string& service,
1042 const std::string& path)
James Feist45094ad2020-04-29 14:02:30 -07001043{
1044 crow::connections::systemBus->async_method_call(
1045 [aResp{std::move(aResp)}](
1046 const boost::system::error_code ec,
1047 const boost::container::flat_map<
1048 std::string, std::variant<std::string, uint64_t, uint32_t,
1049 bool>>& properties) {
1050 if (ec)
1051 {
1052 BMCWEB_LOG_DEBUG << "DBUS response error";
1053 messages::internalError(aResp->res);
1054
1055 return;
1056 }
1057
1058 nlohmann::json& partition =
1059 aResp->res.jsonValue["Regions"].emplace_back(
1060 nlohmann::json::object());
1061 for (const auto& [key, val] : properties)
1062 {
1063 if (key == "MemoryClassification")
1064 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -07001065 const std::string* value = std::get_if<std::string>(&val);
1066 if (value == nullptr)
1067 {
1068 messages::internalError(aResp->res);
1069 continue;
1070 }
1071 partition[key] = *value;
James Feist45094ad2020-04-29 14:02:30 -07001072 }
1073 else if (key == "OffsetInKiB")
1074 {
1075 const uint64_t* value = std::get_if<uint64_t>(&val);
1076 if (value == nullptr)
1077 {
1078 messages::internalError(aResp->res);
James Feist45094ad2020-04-29 14:02:30 -07001079 continue;
1080 }
1081
1082 partition["OffsetMiB"] = (*value >> 10);
1083 }
1084 else if (key == "PartitionId")
1085 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -07001086 const std::string* value = std::get_if<std::string>(&val);
1087 if (value == nullptr)
1088 {
1089 messages::internalError(aResp->res);
1090 continue;
1091 }
1092 partition["RegionId"] = *value;
James Feist45094ad2020-04-29 14:02:30 -07001093 }
1094
1095 else if (key == "PassphraseState")
1096 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -07001097 const bool* value = std::get_if<bool>(&val);
1098 if (value == nullptr)
1099 {
1100 messages::internalError(aResp->res);
1101 continue;
1102 }
1103 partition["PassphraseEnabled"] = *value;
James Feist45094ad2020-04-29 14:02:30 -07001104 }
1105 else if (key == "SizeInKiB")
1106 {
1107 const uint64_t* value = std::get_if<uint64_t>(&val);
1108 if (value == nullptr)
1109 {
1110 messages::internalError(aResp->res);
1111 BMCWEB_LOG_DEBUG
1112 << "Invalid property type for SizeInKiB";
1113 continue;
1114 }
1115 partition["SizeMiB"] = (*value >> 10);
1116 }
1117 }
1118 },
1119
1120 service, path, "org.freedesktop.DBus.Properties", "GetAll",
1121 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition");
1122}
1123
Ed Tanous23a21a12020-07-25 04:45:05 +00001124inline void getDimmData(std::shared_ptr<AsyncResp> aResp,
1125 const std::string& dimmId)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001126{
1127 BMCWEB_LOG_DEBUG << "Get available system dimm resources.";
1128 crow::connections::systemBus->async_method_call(
Ed Tanous029573d2019-02-01 10:57:49 -08001129 [dimmId, aResp{std::move(aResp)}](
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001130 const boost::system::error_code ec,
1131 const boost::container::flat_map<
1132 std::string, boost::container::flat_map<
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001133 std::string, std::vector<std::string>>>&
1134 subtree) {
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001135 if (ec)
1136 {
1137 BMCWEB_LOG_DEBUG << "DBUS response error";
1138 messages::internalError(aResp->res);
1139
1140 return;
1141 }
James Feist45094ad2020-04-29 14:02:30 -07001142 bool found = false;
1143 for (const auto& [path, object] : subtree)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001144 {
James Feist45094ad2020-04-29 14:02:30 -07001145 if (path.find(dimmId) != std::string::npos)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001146 {
James Feist45094ad2020-04-29 14:02:30 -07001147 for (const auto& [service, interfaces] : object)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001148 {
James Feist45094ad2020-04-29 14:02:30 -07001149 if (!found &&
1150 (std::find(
1151 interfaces.begin(), interfaces.end(),
1152 "xyz.openbmc_project.Inventory.Item.Dimm") !=
1153 interfaces.end()))
1154 {
1155 getDimmDataByService(aResp, dimmId, service, path);
1156 found = true;
1157 }
1158
1159 // partitions are separate as there can be multiple per
1160 // device, i.e.
1161 // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition1
1162 // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition2
1163 if (std::find(interfaces.begin(), interfaces.end(),
1164 "xyz.openbmc_project.Inventory.Item."
1165 "PersistentMemory.Partition") !=
1166 interfaces.end())
1167 {
1168 getDimmPartitionData(aResp, service, path);
1169 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001170 }
1171 }
1172 }
1173 // Object not found
James Feist45094ad2020-04-29 14:02:30 -07001174 if (!found)
1175 {
1176 messages::resourceNotFound(aResp->res, "Memory", dimmId);
1177 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001178 return;
1179 },
1180 "xyz.openbmc_project.ObjectMapper",
1181 "/xyz/openbmc_project/object_mapper",
1182 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous271584a2019-07-09 16:24:22 -07001183 "/xyz/openbmc_project/inventory", 0,
James Feist45094ad2020-04-29 14:02:30 -07001184 std::array<const char*, 2>{
1185 "xyz.openbmc_project.Inventory.Item.Dimm",
1186 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition"});
Ed Tanous271584a2019-07-09 16:24:22 -07001187}
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001188
1189class ProcessorCollection : public Node
1190{
1191 public:
1192 /*
1193 * Default Constructor
1194 */
Ed Tanous52cc1122020-07-18 13:51:21 -07001195 ProcessorCollection(App& app) :
Ed Tanous029573d2019-02-01 10:57:49 -08001196 Node(app, "/redfish/v1/Systems/system/Processors/")
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001197 {
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001198 entityPrivileges = {
1199 {boost::beast::http::verb::get, {{"Login"}}},
1200 {boost::beast::http::verb::head, {{"Login"}}},
1201 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
1202 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
1203 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
1204 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
1205 }
1206
1207 private:
1208 /**
1209 * Functions triggers appropriate requests on DBus
1210 */
Ed Tanouscb13a392020-07-25 19:02:03 +00001211 void doGet(crow::Response& res, const crow::Request&,
1212 const std::vector<std::string>&) override
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001213 {
Ed Tanous0f74e642018-11-12 15:17:05 -08001214 res.jsonValue["@odata.type"] =
1215 "#ProcessorCollection.ProcessorCollection";
1216 res.jsonValue["Name"] = "Processor Collection";
Ed Tanous0f74e642018-11-12 15:17:05 -08001217
Ed Tanous029573d2019-02-01 10:57:49 -08001218 res.jsonValue["@odata.id"] = "/redfish/v1/Systems/system/Processors/";
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001219 auto asyncResp = std::make_shared<AsyncResp>(res);
1220
Ed Tanous029573d2019-02-01 10:57:49 -08001221 getResourceList(asyncResp, "Processors",
Alpana Kumari32bee762019-04-25 04:47:57 -05001222 {"xyz.openbmc_project.Inventory.Item.Cpu",
1223 "xyz.openbmc_project.Inventory.Item.Accelerator"});
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001224 }
1225};
1226
1227class Processor : public Node
1228{
1229 public:
1230 /*
1231 * Default Constructor
1232 */
Ed Tanous52cc1122020-07-18 13:51:21 -07001233 Processor(App& app) :
Ed Tanous029573d2019-02-01 10:57:49 -08001234 Node(app, "/redfish/v1/Systems/system/Processors/<str>/", std::string())
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001235 {
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001236 entityPrivileges = {
1237 {boost::beast::http::verb::get, {{"Login"}}},
1238 {boost::beast::http::verb::head, {{"Login"}}},
1239 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
1240 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
1241 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
1242 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
1243 }
1244
1245 private:
1246 /**
1247 * Functions triggers appropriate requests on DBus
1248 */
Ed Tanouscb13a392020-07-25 19:02:03 +00001249 void doGet(crow::Response& res, const crow::Request&,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001250 const std::vector<std::string>& params) override
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001251 {
1252 // Check if there is required param, truly entering this shall be
1253 // impossible
1254 if (params.size() != 1)
1255 {
1256 messages::internalError(res);
1257
1258 res.end();
1259 return;
1260 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001261 const std::string& processorId = params[0];
Zhikui Ren029cc1f2020-08-25 15:21:41 -07001262 res.jsonValue["@odata.type"] = "#Processor.v1_9_0.Processor";
Ed Tanous029573d2019-02-01 10:57:49 -08001263 res.jsonValue["@odata.id"] =
Alpana Kumari32bee762019-04-25 04:47:57 -05001264 "/redfish/v1/Systems/system/Processors/" + processorId;
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001265
Ed Tanous029573d2019-02-01 10:57:49 -08001266 auto asyncResp = std::make_shared<AsyncResp>(res);
1267
Alpana Kumari32bee762019-04-25 04:47:57 -05001268 getCpuData(asyncResp, processorId,
1269 {"xyz.openbmc_project.Inventory.Item.Cpu",
Zhikui Ren5e54a362020-07-13 15:31:38 -07001270 "xyz.openbmc_project.Inventory.Decorator.Asset",
Alpana Kumari32bee762019-04-25 04:47:57 -05001271 "xyz.openbmc_project.Inventory.Item.Accelerator"});
Ed Tanous029573d2019-02-01 10:57:49 -08001272 }
1273};
1274
1275class MemoryCollection : public Node
1276{
1277 public:
1278 /*
1279 * Default Constructor
1280 */
Ed Tanous52cc1122020-07-18 13:51:21 -07001281 MemoryCollection(App& app) : Node(app, "/redfish/v1/Systems/system/Memory/")
Ed Tanous029573d2019-02-01 10:57:49 -08001282 {
1283 entityPrivileges = {
1284 {boost::beast::http::verb::get, {{"Login"}}},
1285 {boost::beast::http::verb::head, {{"Login"}}},
1286 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
1287 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
1288 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
1289 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
1290 }
1291
1292 private:
1293 /**
1294 * Functions triggers appropriate requests on DBus
1295 */
Ed Tanouscb13a392020-07-25 19:02:03 +00001296 void doGet(crow::Response& res, const crow::Request&,
1297 const std::vector<std::string>&) override
Ed Tanous029573d2019-02-01 10:57:49 -08001298 {
Ed Tanous0f74e642018-11-12 15:17:05 -08001299 res.jsonValue["@odata.type"] = "#MemoryCollection.MemoryCollection";
1300 res.jsonValue["Name"] = "Memory Module Collection";
James Feistc50e7c62020-07-27 15:39:36 -07001301 res.jsonValue["@odata.id"] = "/redfish/v1/Systems/system/Memory";
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001302 auto asyncResp = std::make_shared<AsyncResp>(res);
1303
Ed Tanous029573d2019-02-01 10:57:49 -08001304 getResourceList(asyncResp, "Memory",
Alpana Kumari32bee762019-04-25 04:47:57 -05001305 {"xyz.openbmc_project.Inventory.Item.Dimm"});
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001306 }
1307};
1308
1309class Memory : public Node
1310{
1311 public:
1312 /*
1313 * Default Constructor
1314 */
Ed Tanous52cc1122020-07-18 13:51:21 -07001315 Memory(App& app) :
Ed Tanous029573d2019-02-01 10:57:49 -08001316 Node(app, "/redfish/v1/Systems/system/Memory/<str>/", std::string())
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001317 {
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001318 entityPrivileges = {
1319 {boost::beast::http::verb::get, {{"Login"}}},
1320 {boost::beast::http::verb::head, {{"Login"}}},
1321 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
1322 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
1323 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
1324 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
1325 }
1326
1327 private:
1328 /**
1329 * Functions triggers appropriate requests on DBus
1330 */
Ed Tanouscb13a392020-07-25 19:02:03 +00001331 void doGet(crow::Response& res, const crow::Request&,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001332 const std::vector<std::string>& params) override
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001333 {
1334 // Check if there is required param, truly entering this shall be
1335 // impossible
Ed Tanous029573d2019-02-01 10:57:49 -08001336 if (params.size() != 1)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001337 {
1338 messages::internalError(res);
1339 res.end();
1340 return;
1341 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001342 const std::string& dimmId = params[0];
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001343
James Feistc50e7c62020-07-27 15:39:36 -07001344 res.jsonValue["@odata.type"] = "#Memory.v1_7_0.Memory";
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001345 res.jsonValue["@odata.id"] =
Ed Tanous029573d2019-02-01 10:57:49 -08001346 "/redfish/v1/Systems/system/Memory/" + dimmId;
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001347 auto asyncResp = std::make_shared<AsyncResp>(res);
1348
Ed Tanous029573d2019-02-01 10:57:49 -08001349 getDimmData(asyncResp, dimmId);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001350 }
1351};
1352
1353} // namespace redfish