blob: 31db74658862e627b3c3609821235b74c507d4fb [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 }
405 else
406 {
407 health = "UnavailableOffline";
408 }
409 }
410
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700411 aResp->res.jsonValue["Status"]["State"] = state;
Alpana Kumaric24e6b82020-10-01 06:58:46 -0500412 aResp->res.jsonValue["Status"]["Health"] = health;
Alpana Kumari32bee762019-04-25 04:47:57 -0500413 aResp->res.jsonValue["ProcessorType"] = "Accelerator";
414 },
415 service, objPath, "org.freedesktop.DBus.Properties", "GetAll", "");
416}
417
Ed Tanous23a21a12020-07-25 04:45:05 +0000418inline void getCpuData(std::shared_ptr<AsyncResp> aResp,
419 const std::string& cpuId,
420 const std::vector<const char*> inventoryItems)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200421{
422 BMCWEB_LOG_DEBUG << "Get available system cpu resources.";
Alpana Kumari32bee762019-04-25 04:47:57 -0500423
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200424 crow::connections::systemBus->async_method_call(
Ed Tanous029573d2019-02-01 10:57:49 -0800425 [cpuId, aResp{std::move(aResp)}](
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200426 const boost::system::error_code ec,
427 const boost::container::flat_map<
428 std::string, boost::container::flat_map<
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500429 std::string, std::vector<std::string>>>&
430 subtree) {
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200431 if (ec)
432 {
433 BMCWEB_LOG_DEBUG << "DBUS response error";
434 messages::internalError(aResp->res);
435 return;
436 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500437 for (const auto& object : subtree)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200438 {
439 if (boost::ends_with(object.first, cpuId))
440 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500441 for (const auto& service : object.second)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200442 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500443 for (const auto& inventory : service.second)
Zhikui Ren5e54a362020-07-13 15:31:38 -0700444 {
445 if (inventory == "xyz.openbmc_project."
446 "Inventory.Decorator.Asset")
447 {
448 getCpuAssetData(aResp, service.first,
449 object.first);
450 }
451 else if (inventory ==
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700452 "xyz.openbmc_project."
453 "Inventory.Decorator.Revision")
454 {
455 getCpuRevisionData(aResp, service.first,
456 object.first);
457 }
458 else if (inventory == "xyz.openbmc_project."
459 "Inventory.Item.Cpu")
Alpana Kumari32bee762019-04-25 04:47:57 -0500460 {
461 getCpuDataByService(aResp, cpuId, service.first,
462 object.first);
463 }
464 else if (inventory == "xyz.openbmc_project."
465 "Inventory.Item.Accelerator")
466 {
467 getAcceleratorDataByService(
468 aResp, cpuId, service.first, object.first);
469 }
Zhikui Ren5e54a362020-07-13 15:31:38 -0700470 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200471 }
Zhikui Ren5e54a362020-07-13 15:31:38 -0700472 return;
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200473 }
474 }
475 // Object not found
476 messages::resourceNotFound(aResp->res, "Processor", cpuId);
477 return;
478 },
479 "xyz.openbmc_project.ObjectMapper",
480 "/xyz/openbmc_project/object_mapper",
481 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous271584a2019-07-09 16:24:22 -0700482 "/xyz/openbmc_project/inventory", 0, inventoryItems);
483}
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200484
James Feistc50e7c62020-07-27 15:39:36 -0700485using DimmProperty =
486 std::variant<std::string, std::vector<uint32_t>, std::vector<uint16_t>,
487 uint64_t, uint32_t, uint16_t, uint8_t, bool>;
488
489using DimmProperties = boost::container::flat_map<std::string, DimmProperty>;
490
Ed Tanous80789c82020-08-19 09:19:09 -0700491inline void dimmPropToHex(std::shared_ptr<AsyncResp> aResp, const char* key,
492 const std::pair<std::string, DimmProperty>& property)
James Feistc50e7c62020-07-27 15:39:36 -0700493{
494 const uint16_t* value = std::get_if<uint16_t>(&property.second);
495 if (value == nullptr)
496 {
497 messages::internalError(aResp->res);
498 BMCWEB_LOG_DEBUG << "Invalid property type for " << property.first;
499 return;
500 }
501
502 aResp->res.jsonValue[key] = (boost::format("0x%04x") % *value).str();
503}
504
Ed Tanous80789c82020-08-19 09:19:09 -0700505inline void getPersistentMemoryProperties(std::shared_ptr<AsyncResp> aResp,
506 const DimmProperties& properties)
James Feistc50e7c62020-07-27 15:39:36 -0700507{
508 for (const auto& property : properties)
509 {
510 if (property.first == "ModuleManufacturerID")
511 {
512 dimmPropToHex(aResp, "ModuleManufacturerID", property);
513 }
514 else if (property.first == "ModuleProductID")
515 {
516 dimmPropToHex(aResp, "ModuleProductID", property);
517 }
518 else if (property.first == "SubsystemVendorID")
519 {
520 dimmPropToHex(aResp, "MemorySubsystemControllerManufacturerID",
521 property);
522 }
523 else if (property.first == "SubsystemDeviceID")
524 {
525 dimmPropToHex(aResp, "MemorySubsystemControllerProductID",
526 property);
527 }
528 else if (property.first == "VolatileRegionSizeLimitInKiB")
529 {
530 const uint64_t* value = std::get_if<uint64_t>(&property.second);
531
532 if (value == nullptr)
533 {
534 messages::internalError(aResp->res);
535 BMCWEB_LOG_DEBUG << "Invalid property type for "
536 "VolatileRegionSizeLimitKiB";
537 continue;
538 }
539 aResp->res.jsonValue["VolatileRegionSizeLimitMiB"] = (*value) >> 10;
540 }
541 else if (property.first == "PmRegionSizeLimitInKiB")
542 {
543 const uint64_t* value = std::get_if<uint64_t>(&property.second);
544
545 if (value == nullptr)
546 {
547 messages::internalError(aResp->res);
548 BMCWEB_LOG_DEBUG
549 << "Invalid property type for PmRegioSizeLimitKiB";
550 continue;
551 }
552 aResp->res.jsonValue["PersistentRegionSizeLimitMiB"] =
553 (*value) >> 10;
554 }
555 else if (property.first == "VolatileSizeInKiB")
556 {
557 const uint64_t* value = std::get_if<uint64_t>(&property.second);
558
559 if (value == nullptr)
560 {
561 messages::internalError(aResp->res);
562 BMCWEB_LOG_DEBUG
563 << "Invalid property type for VolatileSizeInKiB";
564 continue;
565 }
566 aResp->res.jsonValue["VolatileSizeMiB"] = (*value) >> 10;
567 }
568 else if (property.first == "PmSizeInKiB")
569 {
570 const uint64_t* value = std::get_if<uint64_t>(&property.second);
571 if (value == nullptr)
572 {
573 messages::internalError(aResp->res);
574 BMCWEB_LOG_DEBUG << "Invalid property type for PmSizeInKiB";
575 continue;
576 }
577 aResp->res.jsonValue["NonVolatileSizeMiB"] = (*value) >> 10;
578 }
579 else if (property.first == "CacheSizeInKB")
580 {
581 const uint64_t* value = std::get_if<uint64_t>(&property.second);
582 if (value == nullptr)
583 {
584 messages::internalError(aResp->res);
585 BMCWEB_LOG_DEBUG << "Invalid property type for CacheSizeInKB";
586 continue;
587 }
588 aResp->res.jsonValue["CacheSizeMiB"] = (*value >> 10);
589 }
590
591 else if (property.first == "VoltaileRegionMaxSizeInKib")
592 {
593 const uint64_t* value = std::get_if<uint64_t>(&property.second);
594
595 if (value == nullptr)
596 {
597 messages::internalError(aResp->res);
598 BMCWEB_LOG_DEBUG << "Invalid property type for "
599 "VolatileRegionMaxSizeInKib";
600 continue;
601 }
602 aResp->res.jsonValue["VolatileRegionSizeMaxMiB"] = (*value) >> 10;
603 }
604 else if (property.first == "PmRegionMaxSizeInKiB")
605 {
606 const uint64_t* value = std::get_if<uint64_t>(&property.second);
607
608 if (value == nullptr)
609 {
610 messages::internalError(aResp->res);
611 BMCWEB_LOG_DEBUG
612 << "Invalid property type for PmRegionMaxSizeInKiB";
613 continue;
614 }
615 aResp->res.jsonValue["PersistentRegionSizeMaxMiB"] = (*value) >> 10;
616 }
617 else if (property.first == "AllocationIncrementInKiB")
618 {
619 const uint64_t* value = std::get_if<uint64_t>(&property.second);
620
621 if (value == nullptr)
622 {
623 messages::internalError(aResp->res);
624 BMCWEB_LOG_DEBUG << "Invalid property type for "
625 "AllocationIncrementInKiB";
626 continue;
627 }
628 aResp->res.jsonValue["AllocationIncrementMiB"] = (*value) >> 10;
629 }
630 else if (property.first == "AllocationAlignmentInKiB")
631 {
632 const uint64_t* value = std::get_if<uint64_t>(&property.second);
633
634 if (value == nullptr)
635 {
636 messages::internalError(aResp->res);
637 BMCWEB_LOG_DEBUG << "Invalid property type for "
638 "AllocationAlignmentInKiB";
639 continue;
640 }
641 aResp->res.jsonValue["AllocationAlignmentMiB"] = (*value) >> 10;
642 }
643 else if (property.first == "VolatileRegionNumberLimit")
644 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700645 const uint64_t* value = std::get_if<uint64_t>(&property.second);
646 if (value == nullptr)
647 {
648 messages::internalError(aResp->res);
649 continue;
650 }
651 aResp->res.jsonValue["VolatileRegionNumberLimit"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700652 }
653 else if (property.first == "PmRegionNumberLimit")
654 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700655 const uint64_t* value = std::get_if<uint64_t>(&property.second);
656 if (value == nullptr)
657 {
658 messages::internalError(aResp->res);
659 continue;
660 }
661 aResp->res.jsonValue["PersistentRegionNumberLimit"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700662 }
663 else if (property.first == "SpareDeviceCount")
664 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700665 const uint64_t* value = std::get_if<uint64_t>(&property.second);
666 if (value == nullptr)
667 {
668 messages::internalError(aResp->res);
669 continue;
670 }
671 aResp->res.jsonValue["SpareDeviceCount"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700672 }
673 else if (property.first == "IsSpareDeviceInUse")
674 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700675 const bool* value = std::get_if<bool>(&property.second);
676 if (value == nullptr)
677 {
678 messages::internalError(aResp->res);
679 continue;
680 }
681 aResp->res.jsonValue["IsSpareDeviceEnabled"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700682 }
683 else if (property.first == "IsRankSpareEnabled")
684 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700685 const bool* value = std::get_if<bool>(&property.second);
686 if (value == nullptr)
687 {
688 messages::internalError(aResp->res);
689 continue;
690 }
691 aResp->res.jsonValue["IsRankSpareEnabled"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700692 }
693 else if (property.first == "MaxAveragePowerLimitmW")
694 {
695 const auto* value =
696 std::get_if<std::vector<uint32_t>>(&property.second);
697 if (value == nullptr)
698 {
699 messages::internalError(aResp->res);
700 BMCWEB_LOG_DEBUG << "Invalid property type for "
701 "MaxAveragePowerLimitmW";
702 continue;
703 }
704 aResp->res.jsonValue["MaxTDPMilliWatts"] = *value;
705 }
James Feistc50e7c62020-07-27 15:39:36 -0700706 else if (property.first == "ConfigurationLocked")
707 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700708 const bool* value = std::get_if<bool>(&property.second);
709 if (value == nullptr)
710 {
711 messages::internalError(aResp->res);
712 continue;
713 }
714 aResp->res.jsonValue["ConfigurationLocked"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700715 }
716 else if (property.first == "AllowedMemoryModes")
717 {
718 const std::string* value =
719 std::get_if<std::string>(&property.second);
720 if (value == nullptr)
721 {
722 messages::internalError(aResp->res);
723 BMCWEB_LOG_DEBUG << "Invalid property type for FormFactor";
724 continue;
725 }
726 constexpr const std::array<const char*, 3> values{"Volatile",
727 "PMEM", "Block"};
728
729 for (const char* v : values)
730 {
731 if (boost::ends_with(*value, v))
732 {
733 aResp->res.jsonValue["OperatingMemoryModes "] = v;
734 break;
735 }
736 }
737 }
738 else if (property.first == "MemoryMedia")
739 {
740 const std::string* value =
741 std::get_if<std::string>(&property.second);
742 if (value == nullptr)
743 {
744 messages::internalError(aResp->res);
745 BMCWEB_LOG_DEBUG << "Invalid property type for MemoryMedia";
746 continue;
747 }
748 constexpr const std::array<const char*, 3> values{"DRAM", "NAND",
749 "Intel3DXPoint"};
750
751 for (const char* v : values)
752 {
753 if (boost::ends_with(*value, v))
754 {
755 aResp->res.jsonValue["MemoryMedia"] = v;
756 break;
757 }
758 }
759 }
James Feistc50e7c62020-07-27 15:39:36 -0700760 // PersistantMemory.SecurityCapabilites interface
761 else if (property.first == "ConfigurationLockCapable" ||
762 property.first == "DataLockCapable" ||
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700763 property.first == "PassphraseCapable")
764 {
765 const bool* value = std::get_if<bool>(&property.second);
766 if (value == nullptr)
767 {
768 messages::internalError(aResp->res);
769 continue;
770 }
771 aResp->res.jsonValue["SecurityCapabilities"][property.first] =
772 *value;
773 }
774 else if (property.first == "MaxPassphraseCount" ||
James Feistc50e7c62020-07-27 15:39:36 -0700775 property.first == "PassphraseLockLimit")
776 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700777 const uint64_t* value = std::get_if<uint64_t>(&property.second);
778 if (value == nullptr)
779 {
780 messages::internalError(aResp->res);
781 continue;
782 }
James Feistc50e7c62020-07-27 15:39:36 -0700783 aResp->res.jsonValue["SecurityCapabilities"][property.first] =
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700784 *value;
James Feistc50e7c62020-07-27 15:39:36 -0700785 }
786 }
787}
788
Ed Tanous80789c82020-08-19 09:19:09 -0700789inline void getDimmDataByService(std::shared_ptr<AsyncResp> aResp,
790 const std::string& dimmId,
791 const std::string& service,
792 const std::string& objPath)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200793{
James Feist35e257a2020-06-05 13:30:51 -0700794 auto health = std::make_shared<HealthPopulate>(aResp);
795 health->selfPath = objPath;
796 health->populate();
797
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200798 BMCWEB_LOG_DEBUG << "Get available system components.";
799 crow::connections::systemBus->async_method_call(
James Feistc50e7c62020-07-27 15:39:36 -0700800 [dimmId, aResp{std::move(aResp)}](const boost::system::error_code ec,
801 const DimmProperties& properties) {
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200802 if (ec)
803 {
804 BMCWEB_LOG_DEBUG << "DBUS response error";
805 messages::internalError(aResp->res);
806
807 return;
808 }
809 aResp->res.jsonValue["Id"] = dimmId;
810 aResp->res.jsonValue["Name"] = "DIMM Slot";
811
812 const auto memorySizeProperty = properties.find("MemorySizeInKB");
Gunnar Millsaceb7fc2018-12-10 15:17:20 -0600813 if (memorySizeProperty != properties.end())
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200814 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500815 const uint32_t* memorySize =
Ed Tanousabf2add2019-01-22 16:40:12 -0800816 std::get_if<uint32_t>(&memorySizeProperty->second);
Gunnar Millsaceb7fc2018-12-10 15:17:20 -0600817 if (memorySize == nullptr)
818 {
819 // Important property not in desired type
820 messages::internalError(aResp->res);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200821
Gunnar Millsaceb7fc2018-12-10 15:17:20 -0600822 return;
823 }
824 if (*memorySize == 0)
825 {
826 // Slot is not populated, set status end return
827 aResp->res.jsonValue["Status"]["State"] = "Absent";
828 aResp->res.jsonValue["Status"]["Health"] = "OK";
829 // HTTP Code will be set up automatically, just return
830 return;
831 }
832 aResp->res.jsonValue["CapacityMiB"] = (*memorySize >> 10);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200833 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200834 aResp->res.jsonValue["Status"]["State"] = "Enabled";
835 aResp->res.jsonValue["Status"]["Health"] = "OK";
836
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500837 for (const auto& property : properties)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200838 {
839 if (property.first == "MemoryDataWidth")
840 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700841 const uint16_t* value =
842 std::get_if<uint16_t>(&property.second);
843 if (value == nullptr)
844 {
845 continue;
846 }
847 aResp->res.jsonValue["DataWidthBits"] = *value;
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200848 }
Manojkiran Eda7e236ca2019-06-25 23:06:32 +0530849 else if (property.first == "PartNumber")
850 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700851 const std::string* value =
852 std::get_if<std::string>(&property.second);
853 if (value == nullptr)
854 {
855 continue;
856 }
857 aResp->res.jsonValue["PartNumber"] = *value;
Manojkiran Eda7e236ca2019-06-25 23:06:32 +0530858 }
859 else if (property.first == "SerialNumber")
860 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700861 const std::string* value =
862 std::get_if<std::string>(&property.second);
863 if (value == nullptr)
864 {
865 continue;
866 }
867 aResp->res.jsonValue["SerialNumber"] = *value;
Manojkiran Eda7e236ca2019-06-25 23:06:32 +0530868 }
869 else if (property.first == "Manufacturer")
870 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700871 const std::string* value =
872 std::get_if<std::string>(&property.second);
873 if (value == nullptr)
874 {
875 continue;
876 }
877 aResp->res.jsonValue["Manufacturer"] = *value;
Manojkiran Eda7e236ca2019-06-25 23:06:32 +0530878 }
James Feistc50e7c62020-07-27 15:39:36 -0700879 else if (property.first == "RevisionCode")
880 {
881 const uint16_t* value =
882 std::get_if<uint16_t>(&property.second);
883
884 if (value == nullptr)
885 {
886 messages::internalError(aResp->res);
887 BMCWEB_LOG_DEBUG
888 << "Invalid property type for RevisionCode";
889 continue;
890 }
891 aResp->res.jsonValue["FirmwareRevision"] =
892 std::to_string(*value);
893 }
894 else if (property.first == "MemoryTotalWidth")
895 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700896 const uint16_t* value =
897 std::get_if<uint16_t>(&property.second);
898 if (value == nullptr)
899 {
900 continue;
901 }
902 aResp->res.jsonValue["BusWidthBits"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700903 }
904 else if (property.first == "ECC")
905 {
906 const std::string* value =
907 std::get_if<std::string>(&property.second);
908 if (value == nullptr)
909 {
910 messages::internalError(aResp->res);
911 BMCWEB_LOG_DEBUG << "Invalid property type for ECC";
912 continue;
913 }
914 constexpr const std::array<const char*, 4> values{
915 "NoECC", "SingleBitECC", "MultiBitECC",
916 "AddressParity"};
917
918 for (const char* v : values)
919 {
920 if (boost::ends_with(*value, v))
921 {
922 aResp->res.jsonValue["ErrorCorrection"] = v;
923 break;
924 }
925 }
926 }
927 else if (property.first == "FormFactor")
928 {
929 const std::string* value =
930 std::get_if<std::string>(&property.second);
931 if (value == nullptr)
932 {
933 messages::internalError(aResp->res);
934 BMCWEB_LOG_DEBUG
935 << "Invalid property type for FormFactor";
936 continue;
937 }
938 constexpr const std::array<const char*, 11> values{
939 "RDIMM", "UDIMM", "SO_DIMM",
940 "LRDIMM", "Mini_RDIMM", "Mini_UDIMM",
941 "SO_RDIMM_72b", "SO_UDIMM_72b", "SO_DIMM_16b",
942 "SO_DIMM_32b", "Die"};
943
944 for (const char* v : values)
945 {
946 if (boost::ends_with(*value, v))
947 {
948 aResp->res.jsonValue["BaseModuleType"] = v;
949 break;
950 }
951 }
952 }
953 else if (property.first == "AllowedSpeedsMT")
954 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700955 const std::vector<uint16_t>* value =
956 std::get_if<std::vector<uint16_t>>(&property.second);
957 if (value == nullptr)
958 {
959 continue;
960 }
961 nlohmann::json& jValue =
962 aResp->res.jsonValue["AllowedSpeedsMHz"];
963 jValue = nlohmann::json::array();
964 for (uint16_t subVal : *value)
965 {
966 jValue.push_back(subVal);
967 }
James Feistc50e7c62020-07-27 15:39:36 -0700968 }
969 else if (property.first == "MemoryAttributes")
970 {
971 const uint8_t* value =
972 std::get_if<uint8_t>(&property.second);
973
974 if (value == nullptr)
975 {
976 messages::internalError(aResp->res);
977 BMCWEB_LOG_DEBUG
978 << "Invalid property type for MemoryAttributes";
979 continue;
980 }
981 aResp->res.jsonValue["RankCount"] =
982 static_cast<uint64_t>(*value);
983 }
984 else if (property.first == "MemoryConfiguredSpeedInMhz")
985 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700986 const uint16_t* value =
987 std::get_if<uint16_t>(&property.second);
988 if (value == nullptr)
989 {
990 continue;
991 }
992 aResp->res.jsonValue["OperatingSpeedMhz"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700993 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200994 else if (property.first == "MemoryType")
995 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500996 const auto* value =
Ed Tanousabf2add2019-01-22 16:40:12 -0800997 std::get_if<std::string>(&property.second);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200998 if (value != nullptr)
999 {
James Feistc50e7c62020-07-27 15:39:36 -07001000 size_t idx = value->rfind(".");
1001 if (idx == std::string::npos ||
1002 idx + 1 >= value->size())
1003 {
1004 messages::internalError(aResp->res);
1005 BMCWEB_LOG_DEBUG << "Invalid property type for "
1006 "MemoryType";
1007 }
1008 std::string result = value->substr(idx + 1);
1009 aResp->res.jsonValue["MemoryDeviceType"] = result;
1010 if (value->find("DDR") != std::string::npos)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001011 {
1012 aResp->res.jsonValue["MemoryType"] = "DRAM";
1013 }
James Feistc50e7c62020-07-27 15:39:36 -07001014 else if (boost::ends_with(*value, "Logical"))
1015 {
1016 aResp->res.jsonValue["MemoryType"] = "IntelOptane";
1017 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001018 }
1019 }
James Feistc50e7c62020-07-27 15:39:36 -07001020 // memory location interface
1021 else if (property.first == "Channel" ||
1022 property.first == "MemoryController" ||
1023 property.first == "Slot" || property.first == "Socket")
1024 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -07001025 const std::string* value =
1026 std::get_if<std::string>(&property.second);
1027 if (value == nullptr)
1028 {
1029 messages::internalError(aResp->res);
1030 continue;
1031 }
James Feistc50e7c62020-07-27 15:39:36 -07001032 aResp->res.jsonValue["MemoryLocation"][property.first] =
Ed Tanous5fb91ba2020-09-28 15:41:28 -07001033 *value;
James Feistc50e7c62020-07-27 15:39:36 -07001034 }
1035 else
1036 {
1037 getPersistentMemoryProperties(aResp, properties);
1038 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001039 }
1040 },
1041 service, objPath, "org.freedesktop.DBus.Properties", "GetAll", "");
1042}
1043
Ed Tanous23a21a12020-07-25 04:45:05 +00001044inline void getDimmPartitionData(std::shared_ptr<AsyncResp> aResp,
1045 const std::string& service,
1046 const std::string& path)
James Feist45094ad2020-04-29 14:02:30 -07001047{
1048 crow::connections::systemBus->async_method_call(
1049 [aResp{std::move(aResp)}](
1050 const boost::system::error_code ec,
1051 const boost::container::flat_map<
1052 std::string, std::variant<std::string, uint64_t, uint32_t,
1053 bool>>& properties) {
1054 if (ec)
1055 {
1056 BMCWEB_LOG_DEBUG << "DBUS response error";
1057 messages::internalError(aResp->res);
1058
1059 return;
1060 }
1061
1062 nlohmann::json& partition =
1063 aResp->res.jsonValue["Regions"].emplace_back(
1064 nlohmann::json::object());
1065 for (const auto& [key, val] : properties)
1066 {
1067 if (key == "MemoryClassification")
1068 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -07001069 const std::string* value = std::get_if<std::string>(&val);
1070 if (value == nullptr)
1071 {
1072 messages::internalError(aResp->res);
1073 continue;
1074 }
1075 partition[key] = *value;
James Feist45094ad2020-04-29 14:02:30 -07001076 }
1077 else if (key == "OffsetInKiB")
1078 {
1079 const uint64_t* value = std::get_if<uint64_t>(&val);
1080 if (value == nullptr)
1081 {
1082 messages::internalError(aResp->res);
James Feist45094ad2020-04-29 14:02:30 -07001083 continue;
1084 }
1085
1086 partition["OffsetMiB"] = (*value >> 10);
1087 }
1088 else if (key == "PartitionId")
1089 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -07001090 const std::string* value = std::get_if<std::string>(&val);
1091 if (value == nullptr)
1092 {
1093 messages::internalError(aResp->res);
1094 continue;
1095 }
1096 partition["RegionId"] = *value;
James Feist45094ad2020-04-29 14:02:30 -07001097 }
1098
1099 else if (key == "PassphraseState")
1100 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -07001101 const bool* value = std::get_if<bool>(&val);
1102 if (value == nullptr)
1103 {
1104 messages::internalError(aResp->res);
1105 continue;
1106 }
1107 partition["PassphraseEnabled"] = *value;
James Feist45094ad2020-04-29 14:02:30 -07001108 }
1109 else if (key == "SizeInKiB")
1110 {
1111 const uint64_t* value = std::get_if<uint64_t>(&val);
1112 if (value == nullptr)
1113 {
1114 messages::internalError(aResp->res);
1115 BMCWEB_LOG_DEBUG
1116 << "Invalid property type for SizeInKiB";
1117 continue;
1118 }
1119 partition["SizeMiB"] = (*value >> 10);
1120 }
1121 }
1122 },
1123
1124 service, path, "org.freedesktop.DBus.Properties", "GetAll",
1125 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition");
1126}
1127
Ed Tanous23a21a12020-07-25 04:45:05 +00001128inline void getDimmData(std::shared_ptr<AsyncResp> aResp,
1129 const std::string& dimmId)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001130{
1131 BMCWEB_LOG_DEBUG << "Get available system dimm resources.";
1132 crow::connections::systemBus->async_method_call(
Ed Tanous029573d2019-02-01 10:57:49 -08001133 [dimmId, aResp{std::move(aResp)}](
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001134 const boost::system::error_code ec,
1135 const boost::container::flat_map<
1136 std::string, boost::container::flat_map<
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001137 std::string, std::vector<std::string>>>&
1138 subtree) {
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001139 if (ec)
1140 {
1141 BMCWEB_LOG_DEBUG << "DBUS response error";
1142 messages::internalError(aResp->res);
1143
1144 return;
1145 }
James Feist45094ad2020-04-29 14:02:30 -07001146 bool found = false;
1147 for (const auto& [path, object] : subtree)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001148 {
James Feist45094ad2020-04-29 14:02:30 -07001149 if (path.find(dimmId) != std::string::npos)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001150 {
James Feist45094ad2020-04-29 14:02:30 -07001151 for (const auto& [service, interfaces] : object)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001152 {
James Feist45094ad2020-04-29 14:02:30 -07001153 if (!found &&
1154 (std::find(
1155 interfaces.begin(), interfaces.end(),
1156 "xyz.openbmc_project.Inventory.Item.Dimm") !=
1157 interfaces.end()))
1158 {
1159 getDimmDataByService(aResp, dimmId, service, path);
1160 found = true;
1161 }
1162
1163 // partitions are separate as there can be multiple per
1164 // device, i.e.
1165 // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition1
1166 // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition2
1167 if (std::find(interfaces.begin(), interfaces.end(),
1168 "xyz.openbmc_project.Inventory.Item."
1169 "PersistentMemory.Partition") !=
1170 interfaces.end())
1171 {
1172 getDimmPartitionData(aResp, service, path);
1173 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001174 }
1175 }
1176 }
1177 // Object not found
James Feist45094ad2020-04-29 14:02:30 -07001178 if (!found)
1179 {
1180 messages::resourceNotFound(aResp->res, "Memory", dimmId);
1181 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001182 return;
1183 },
1184 "xyz.openbmc_project.ObjectMapper",
1185 "/xyz/openbmc_project/object_mapper",
1186 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous271584a2019-07-09 16:24:22 -07001187 "/xyz/openbmc_project/inventory", 0,
James Feist45094ad2020-04-29 14:02:30 -07001188 std::array<const char*, 2>{
1189 "xyz.openbmc_project.Inventory.Item.Dimm",
1190 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition"});
Ed Tanous271584a2019-07-09 16:24:22 -07001191}
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001192
1193class ProcessorCollection : public Node
1194{
1195 public:
1196 /*
1197 * Default Constructor
1198 */
Ed Tanous52cc1122020-07-18 13:51:21 -07001199 ProcessorCollection(App& app) :
Ed Tanous029573d2019-02-01 10:57:49 -08001200 Node(app, "/redfish/v1/Systems/system/Processors/")
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001201 {
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001202 entityPrivileges = {
1203 {boost::beast::http::verb::get, {{"Login"}}},
1204 {boost::beast::http::verb::head, {{"Login"}}},
1205 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
1206 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
1207 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
1208 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
1209 }
1210
1211 private:
1212 /**
1213 * Functions triggers appropriate requests on DBus
1214 */
Ed Tanouscb13a392020-07-25 19:02:03 +00001215 void doGet(crow::Response& res, const crow::Request&,
1216 const std::vector<std::string>&) override
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001217 {
Ed Tanous0f74e642018-11-12 15:17:05 -08001218 res.jsonValue["@odata.type"] =
1219 "#ProcessorCollection.ProcessorCollection";
1220 res.jsonValue["Name"] = "Processor Collection";
Ed Tanous0f74e642018-11-12 15:17:05 -08001221
Ed Tanous029573d2019-02-01 10:57:49 -08001222 res.jsonValue["@odata.id"] = "/redfish/v1/Systems/system/Processors/";
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001223 auto asyncResp = std::make_shared<AsyncResp>(res);
1224
Ed Tanous029573d2019-02-01 10:57:49 -08001225 getResourceList(asyncResp, "Processors",
Alpana Kumari32bee762019-04-25 04:47:57 -05001226 {"xyz.openbmc_project.Inventory.Item.Cpu",
1227 "xyz.openbmc_project.Inventory.Item.Accelerator"});
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001228 }
1229};
1230
1231class Processor : public Node
1232{
1233 public:
1234 /*
1235 * Default Constructor
1236 */
Ed Tanous52cc1122020-07-18 13:51:21 -07001237 Processor(App& app) :
Ed Tanous029573d2019-02-01 10:57:49 -08001238 Node(app, "/redfish/v1/Systems/system/Processors/<str>/", std::string())
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001239 {
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001240 entityPrivileges = {
1241 {boost::beast::http::verb::get, {{"Login"}}},
1242 {boost::beast::http::verb::head, {{"Login"}}},
1243 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
1244 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
1245 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
1246 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
1247 }
1248
1249 private:
1250 /**
1251 * Functions triggers appropriate requests on DBus
1252 */
Ed Tanouscb13a392020-07-25 19:02:03 +00001253 void doGet(crow::Response& res, const crow::Request&,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001254 const std::vector<std::string>& params) override
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001255 {
1256 // Check if there is required param, truly entering this shall be
1257 // impossible
1258 if (params.size() != 1)
1259 {
1260 messages::internalError(res);
1261
1262 res.end();
1263 return;
1264 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001265 const std::string& processorId = params[0];
Zhikui Ren029cc1f2020-08-25 15:21:41 -07001266 res.jsonValue["@odata.type"] = "#Processor.v1_9_0.Processor";
Ed Tanous029573d2019-02-01 10:57:49 -08001267 res.jsonValue["@odata.id"] =
Alpana Kumari32bee762019-04-25 04:47:57 -05001268 "/redfish/v1/Systems/system/Processors/" + processorId;
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001269
Ed Tanous029573d2019-02-01 10:57:49 -08001270 auto asyncResp = std::make_shared<AsyncResp>(res);
1271
Alpana Kumari32bee762019-04-25 04:47:57 -05001272 getCpuData(asyncResp, processorId,
1273 {"xyz.openbmc_project.Inventory.Item.Cpu",
Zhikui Ren5e54a362020-07-13 15:31:38 -07001274 "xyz.openbmc_project.Inventory.Decorator.Asset",
Alpana Kumari32bee762019-04-25 04:47:57 -05001275 "xyz.openbmc_project.Inventory.Item.Accelerator"});
Ed Tanous029573d2019-02-01 10:57:49 -08001276 }
1277};
1278
1279class MemoryCollection : public Node
1280{
1281 public:
1282 /*
1283 * Default Constructor
1284 */
Ed Tanous52cc1122020-07-18 13:51:21 -07001285 MemoryCollection(App& app) : Node(app, "/redfish/v1/Systems/system/Memory/")
Ed Tanous029573d2019-02-01 10:57:49 -08001286 {
1287 entityPrivileges = {
1288 {boost::beast::http::verb::get, {{"Login"}}},
1289 {boost::beast::http::verb::head, {{"Login"}}},
1290 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
1291 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
1292 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
1293 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
1294 }
1295
1296 private:
1297 /**
1298 * Functions triggers appropriate requests on DBus
1299 */
Ed Tanouscb13a392020-07-25 19:02:03 +00001300 void doGet(crow::Response& res, const crow::Request&,
1301 const std::vector<std::string>&) override
Ed Tanous029573d2019-02-01 10:57:49 -08001302 {
Ed Tanous0f74e642018-11-12 15:17:05 -08001303 res.jsonValue["@odata.type"] = "#MemoryCollection.MemoryCollection";
1304 res.jsonValue["Name"] = "Memory Module Collection";
James Feistc50e7c62020-07-27 15:39:36 -07001305 res.jsonValue["@odata.id"] = "/redfish/v1/Systems/system/Memory";
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001306 auto asyncResp = std::make_shared<AsyncResp>(res);
1307
Ed Tanous029573d2019-02-01 10:57:49 -08001308 getResourceList(asyncResp, "Memory",
Alpana Kumari32bee762019-04-25 04:47:57 -05001309 {"xyz.openbmc_project.Inventory.Item.Dimm"});
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001310 }
1311};
1312
1313class Memory : public Node
1314{
1315 public:
1316 /*
1317 * Default Constructor
1318 */
Ed Tanous52cc1122020-07-18 13:51:21 -07001319 Memory(App& app) :
Ed Tanous029573d2019-02-01 10:57:49 -08001320 Node(app, "/redfish/v1/Systems/system/Memory/<str>/", std::string())
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001321 {
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001322 entityPrivileges = {
1323 {boost::beast::http::verb::get, {{"Login"}}},
1324 {boost::beast::http::verb::head, {{"Login"}}},
1325 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
1326 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
1327 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
1328 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
1329 }
1330
1331 private:
1332 /**
1333 * Functions triggers appropriate requests on DBus
1334 */
Ed Tanouscb13a392020-07-25 19:02:03 +00001335 void doGet(crow::Response& res, const crow::Request&,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001336 const std::vector<std::string>& params) override
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001337 {
1338 // Check if there is required param, truly entering this shall be
1339 // impossible
Ed Tanous029573d2019-02-01 10:57:49 -08001340 if (params.size() != 1)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001341 {
1342 messages::internalError(res);
1343 res.end();
1344 return;
1345 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001346 const std::string& dimmId = params[0];
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001347
James Feistc50e7c62020-07-27 15:39:36 -07001348 res.jsonValue["@odata.type"] = "#Memory.v1_7_0.Memory";
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001349 res.jsonValue["@odata.id"] =
Ed Tanous029573d2019-02-01 10:57:49 -08001350 "/redfish/v1/Systems/system/Memory/" + dimmId;
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001351 auto asyncResp = std::make_shared<AsyncResp>(res);
1352
Ed Tanous029573d2019-02-01 10:57:49 -08001353 getDimmData(asyncResp, dimmId);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001354 }
1355};
1356
1357} // namespace redfish