blob: 4fa7c114d1980a9b87e1fef6456c0ea73af059c7 [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>
Gunnar Mills116bcc52020-10-14 15:23:42 -050023#include <utils/collection.hpp>
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +020024#include <utils/json_utils.hpp>
25
26namespace redfish
27{
28
James Feistc50e7c62020-07-27 15:39:36 -070029using DimmProperty =
30 std::variant<std::string, std::vector<uint32_t>, std::vector<uint16_t>,
31 uint64_t, uint32_t, uint16_t, uint8_t, bool>;
32
33using DimmProperties = boost::container::flat_map<std::string, DimmProperty>;
34
Ed Tanousb5a76932020-09-29 16:16:58 -070035inline void dimmPropToHex(const std::shared_ptr<AsyncResp>& aResp,
36 const char* key,
Ed Tanous80789c82020-08-19 09:19:09 -070037 const std::pair<std::string, DimmProperty>& property)
James Feistc50e7c62020-07-27 15:39:36 -070038{
39 const uint16_t* value = std::get_if<uint16_t>(&property.second);
40 if (value == nullptr)
41 {
42 messages::internalError(aResp->res);
43 BMCWEB_LOG_DEBUG << "Invalid property type for " << property.first;
44 return;
45 }
46
47 aResp->res.jsonValue[key] = (boost::format("0x%04x") % *value).str();
48}
49
Ed Tanousb5a76932020-09-29 16:16:58 -070050inline void
51 getPersistentMemoryProperties(const std::shared_ptr<AsyncResp>& aResp,
52 const DimmProperties& properties)
James Feistc50e7c62020-07-27 15:39:36 -070053{
54 for (const auto& property : properties)
55 {
56 if (property.first == "ModuleManufacturerID")
57 {
58 dimmPropToHex(aResp, "ModuleManufacturerID", property);
59 }
60 else if (property.first == "ModuleProductID")
61 {
62 dimmPropToHex(aResp, "ModuleProductID", property);
63 }
64 else if (property.first == "SubsystemVendorID")
65 {
66 dimmPropToHex(aResp, "MemorySubsystemControllerManufacturerID",
67 property);
68 }
69 else if (property.first == "SubsystemDeviceID")
70 {
71 dimmPropToHex(aResp, "MemorySubsystemControllerProductID",
72 property);
73 }
74 else if (property.first == "VolatileRegionSizeLimitInKiB")
75 {
76 const uint64_t* value = std::get_if<uint64_t>(&property.second);
77
78 if (value == nullptr)
79 {
80 messages::internalError(aResp->res);
81 BMCWEB_LOG_DEBUG << "Invalid property type for "
82 "VolatileRegionSizeLimitKiB";
83 continue;
84 }
85 aResp->res.jsonValue["VolatileRegionSizeLimitMiB"] = (*value) >> 10;
86 }
87 else if (property.first == "PmRegionSizeLimitInKiB")
88 {
89 const uint64_t* value = std::get_if<uint64_t>(&property.second);
90
91 if (value == nullptr)
92 {
93 messages::internalError(aResp->res);
94 BMCWEB_LOG_DEBUG
95 << "Invalid property type for PmRegioSizeLimitKiB";
96 continue;
97 }
98 aResp->res.jsonValue["PersistentRegionSizeLimitMiB"] =
99 (*value) >> 10;
100 }
101 else if (property.first == "VolatileSizeInKiB")
102 {
103 const uint64_t* value = std::get_if<uint64_t>(&property.second);
104
105 if (value == nullptr)
106 {
107 messages::internalError(aResp->res);
108 BMCWEB_LOG_DEBUG
109 << "Invalid property type for VolatileSizeInKiB";
110 continue;
111 }
112 aResp->res.jsonValue["VolatileSizeMiB"] = (*value) >> 10;
113 }
114 else if (property.first == "PmSizeInKiB")
115 {
116 const uint64_t* value = std::get_if<uint64_t>(&property.second);
117 if (value == nullptr)
118 {
119 messages::internalError(aResp->res);
120 BMCWEB_LOG_DEBUG << "Invalid property type for PmSizeInKiB";
121 continue;
122 }
123 aResp->res.jsonValue["NonVolatileSizeMiB"] = (*value) >> 10;
124 }
125 else if (property.first == "CacheSizeInKB")
126 {
127 const uint64_t* value = std::get_if<uint64_t>(&property.second);
128 if (value == nullptr)
129 {
130 messages::internalError(aResp->res);
131 BMCWEB_LOG_DEBUG << "Invalid property type for CacheSizeInKB";
132 continue;
133 }
134 aResp->res.jsonValue["CacheSizeMiB"] = (*value >> 10);
135 }
136
137 else if (property.first == "VoltaileRegionMaxSizeInKib")
138 {
139 const uint64_t* value = std::get_if<uint64_t>(&property.second);
140
141 if (value == nullptr)
142 {
143 messages::internalError(aResp->res);
144 BMCWEB_LOG_DEBUG << "Invalid property type for "
145 "VolatileRegionMaxSizeInKib";
146 continue;
147 }
148 aResp->res.jsonValue["VolatileRegionSizeMaxMiB"] = (*value) >> 10;
149 }
150 else if (property.first == "PmRegionMaxSizeInKiB")
151 {
152 const uint64_t* value = std::get_if<uint64_t>(&property.second);
153
154 if (value == nullptr)
155 {
156 messages::internalError(aResp->res);
157 BMCWEB_LOG_DEBUG
158 << "Invalid property type for PmRegionMaxSizeInKiB";
159 continue;
160 }
161 aResp->res.jsonValue["PersistentRegionSizeMaxMiB"] = (*value) >> 10;
162 }
163 else if (property.first == "AllocationIncrementInKiB")
164 {
165 const uint64_t* value = std::get_if<uint64_t>(&property.second);
166
167 if (value == nullptr)
168 {
169 messages::internalError(aResp->res);
170 BMCWEB_LOG_DEBUG << "Invalid property type for "
171 "AllocationIncrementInKiB";
172 continue;
173 }
174 aResp->res.jsonValue["AllocationIncrementMiB"] = (*value) >> 10;
175 }
176 else if (property.first == "AllocationAlignmentInKiB")
177 {
178 const uint64_t* value = std::get_if<uint64_t>(&property.second);
179
180 if (value == nullptr)
181 {
182 messages::internalError(aResp->res);
183 BMCWEB_LOG_DEBUG << "Invalid property type for "
184 "AllocationAlignmentInKiB";
185 continue;
186 }
187 aResp->res.jsonValue["AllocationAlignmentMiB"] = (*value) >> 10;
188 }
189 else if (property.first == "VolatileRegionNumberLimit")
190 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700191 const uint64_t* value = std::get_if<uint64_t>(&property.second);
192 if (value == nullptr)
193 {
194 messages::internalError(aResp->res);
195 continue;
196 }
197 aResp->res.jsonValue["VolatileRegionNumberLimit"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700198 }
199 else if (property.first == "PmRegionNumberLimit")
200 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700201 const uint64_t* value = std::get_if<uint64_t>(&property.second);
202 if (value == nullptr)
203 {
204 messages::internalError(aResp->res);
205 continue;
206 }
207 aResp->res.jsonValue["PersistentRegionNumberLimit"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700208 }
209 else if (property.first == "SpareDeviceCount")
210 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700211 const uint64_t* value = std::get_if<uint64_t>(&property.second);
212 if (value == nullptr)
213 {
214 messages::internalError(aResp->res);
215 continue;
216 }
217 aResp->res.jsonValue["SpareDeviceCount"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700218 }
219 else if (property.first == "IsSpareDeviceInUse")
220 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700221 const bool* value = std::get_if<bool>(&property.second);
222 if (value == nullptr)
223 {
224 messages::internalError(aResp->res);
225 continue;
226 }
227 aResp->res.jsonValue["IsSpareDeviceEnabled"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700228 }
229 else if (property.first == "IsRankSpareEnabled")
230 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700231 const bool* value = std::get_if<bool>(&property.second);
232 if (value == nullptr)
233 {
234 messages::internalError(aResp->res);
235 continue;
236 }
237 aResp->res.jsonValue["IsRankSpareEnabled"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700238 }
239 else if (property.first == "MaxAveragePowerLimitmW")
240 {
241 const auto* value =
242 std::get_if<std::vector<uint32_t>>(&property.second);
243 if (value == nullptr)
244 {
245 messages::internalError(aResp->res);
246 BMCWEB_LOG_DEBUG << "Invalid property type for "
247 "MaxAveragePowerLimitmW";
248 continue;
249 }
250 aResp->res.jsonValue["MaxTDPMilliWatts"] = *value;
251 }
James Feistc50e7c62020-07-27 15:39:36 -0700252 else if (property.first == "ConfigurationLocked")
253 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700254 const bool* value = std::get_if<bool>(&property.second);
255 if (value == nullptr)
256 {
257 messages::internalError(aResp->res);
258 continue;
259 }
260 aResp->res.jsonValue["ConfigurationLocked"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700261 }
262 else if (property.first == "AllowedMemoryModes")
263 {
264 const std::string* value =
265 std::get_if<std::string>(&property.second);
266 if (value == nullptr)
267 {
268 messages::internalError(aResp->res);
269 BMCWEB_LOG_DEBUG << "Invalid property type for FormFactor";
270 continue;
271 }
272 constexpr const std::array<const char*, 3> values{"Volatile",
273 "PMEM", "Block"};
274
275 for (const char* v : values)
276 {
277 if (boost::ends_with(*value, v))
278 {
279 aResp->res.jsonValue["OperatingMemoryModes "] = v;
280 break;
281 }
282 }
283 }
284 else if (property.first == "MemoryMedia")
285 {
286 const std::string* value =
287 std::get_if<std::string>(&property.second);
288 if (value == nullptr)
289 {
290 messages::internalError(aResp->res);
291 BMCWEB_LOG_DEBUG << "Invalid property type for MemoryMedia";
292 continue;
293 }
294 constexpr const std::array<const char*, 3> values{"DRAM", "NAND",
295 "Intel3DXPoint"};
296
297 for (const char* v : values)
298 {
299 if (boost::ends_with(*value, v))
300 {
301 aResp->res.jsonValue["MemoryMedia"] = v;
302 break;
303 }
304 }
305 }
James Feistc50e7c62020-07-27 15:39:36 -0700306 // PersistantMemory.SecurityCapabilites interface
307 else if (property.first == "ConfigurationLockCapable" ||
308 property.first == "DataLockCapable" ||
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700309 property.first == "PassphraseCapable")
310 {
311 const bool* value = std::get_if<bool>(&property.second);
312 if (value == nullptr)
313 {
314 messages::internalError(aResp->res);
315 continue;
316 }
317 aResp->res.jsonValue["SecurityCapabilities"][property.first] =
318 *value;
319 }
320 else if (property.first == "MaxPassphraseCount" ||
James Feistc50e7c62020-07-27 15:39:36 -0700321 property.first == "PassphraseLockLimit")
322 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700323 const uint64_t* value = std::get_if<uint64_t>(&property.second);
324 if (value == nullptr)
325 {
326 messages::internalError(aResp->res);
327 continue;
328 }
James Feistc50e7c62020-07-27 15:39:36 -0700329 aResp->res.jsonValue["SecurityCapabilities"][property.first] =
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700330 *value;
James Feistc50e7c62020-07-27 15:39:36 -0700331 }
332 }
333}
334
Ed Tanous80789c82020-08-19 09:19:09 -0700335inline void getDimmDataByService(std::shared_ptr<AsyncResp> aResp,
336 const std::string& dimmId,
337 const std::string& service,
338 const std::string& objPath)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200339{
James Feist35e257a2020-06-05 13:30:51 -0700340 auto health = std::make_shared<HealthPopulate>(aResp);
341 health->selfPath = objPath;
342 health->populate();
343
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200344 BMCWEB_LOG_DEBUG << "Get available system components.";
345 crow::connections::systemBus->async_method_call(
James Feistc50e7c62020-07-27 15:39:36 -0700346 [dimmId, aResp{std::move(aResp)}](const boost::system::error_code ec,
347 const DimmProperties& properties) {
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200348 if (ec)
349 {
350 BMCWEB_LOG_DEBUG << "DBUS response error";
351 messages::internalError(aResp->res);
352
353 return;
354 }
355 aResp->res.jsonValue["Id"] = dimmId;
356 aResp->res.jsonValue["Name"] = "DIMM Slot";
357
358 const auto memorySizeProperty = properties.find("MemorySizeInKB");
Gunnar Millsaceb7fc2018-12-10 15:17:20 -0600359 if (memorySizeProperty != properties.end())
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200360 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500361 const uint32_t* memorySize =
Ed Tanousabf2add2019-01-22 16:40:12 -0800362 std::get_if<uint32_t>(&memorySizeProperty->second);
Gunnar Millsaceb7fc2018-12-10 15:17:20 -0600363 if (memorySize == nullptr)
364 {
365 // Important property not in desired type
366 messages::internalError(aResp->res);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200367
Gunnar Millsaceb7fc2018-12-10 15:17:20 -0600368 return;
369 }
370 if (*memorySize == 0)
371 {
372 // Slot is not populated, set status end return
373 aResp->res.jsonValue["Status"]["State"] = "Absent";
374 aResp->res.jsonValue["Status"]["Health"] = "OK";
375 // HTTP Code will be set up automatically, just return
376 return;
377 }
378 aResp->res.jsonValue["CapacityMiB"] = (*memorySize >> 10);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200379 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200380 aResp->res.jsonValue["Status"]["State"] = "Enabled";
381 aResp->res.jsonValue["Status"]["Health"] = "OK";
382
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500383 for (const auto& property : properties)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200384 {
385 if (property.first == "MemoryDataWidth")
386 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700387 const uint16_t* value =
388 std::get_if<uint16_t>(&property.second);
389 if (value == nullptr)
390 {
391 continue;
392 }
393 aResp->res.jsonValue["DataWidthBits"] = *value;
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200394 }
Manojkiran Eda7e236ca2019-06-25 23:06:32 +0530395 else if (property.first == "PartNumber")
396 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700397 const std::string* value =
398 std::get_if<std::string>(&property.second);
399 if (value == nullptr)
400 {
401 continue;
402 }
403 aResp->res.jsonValue["PartNumber"] = *value;
Manojkiran Eda7e236ca2019-06-25 23:06:32 +0530404 }
405 else if (property.first == "SerialNumber")
406 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700407 const std::string* value =
408 std::get_if<std::string>(&property.second);
409 if (value == nullptr)
410 {
411 continue;
412 }
413 aResp->res.jsonValue["SerialNumber"] = *value;
Manojkiran Eda7e236ca2019-06-25 23:06:32 +0530414 }
415 else if (property.first == "Manufacturer")
416 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700417 const std::string* value =
418 std::get_if<std::string>(&property.second);
419 if (value == nullptr)
420 {
421 continue;
422 }
423 aResp->res.jsonValue["Manufacturer"] = *value;
Manojkiran Eda7e236ca2019-06-25 23:06:32 +0530424 }
James Feistc50e7c62020-07-27 15:39:36 -0700425 else if (property.first == "RevisionCode")
426 {
427 const uint16_t* value =
428 std::get_if<uint16_t>(&property.second);
429
430 if (value == nullptr)
431 {
432 messages::internalError(aResp->res);
433 BMCWEB_LOG_DEBUG
434 << "Invalid property type for RevisionCode";
435 continue;
436 }
437 aResp->res.jsonValue["FirmwareRevision"] =
438 std::to_string(*value);
439 }
440 else if (property.first == "MemoryTotalWidth")
441 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700442 const uint16_t* value =
443 std::get_if<uint16_t>(&property.second);
444 if (value == nullptr)
445 {
446 continue;
447 }
448 aResp->res.jsonValue["BusWidthBits"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700449 }
450 else if (property.first == "ECC")
451 {
452 const std::string* value =
453 std::get_if<std::string>(&property.second);
454 if (value == nullptr)
455 {
456 messages::internalError(aResp->res);
457 BMCWEB_LOG_DEBUG << "Invalid property type for ECC";
458 continue;
459 }
460 constexpr const std::array<const char*, 4> values{
461 "NoECC", "SingleBitECC", "MultiBitECC",
462 "AddressParity"};
463
464 for (const char* v : values)
465 {
466 if (boost::ends_with(*value, v))
467 {
468 aResp->res.jsonValue["ErrorCorrection"] = v;
469 break;
470 }
471 }
472 }
473 else if (property.first == "FormFactor")
474 {
475 const std::string* value =
476 std::get_if<std::string>(&property.second);
477 if (value == nullptr)
478 {
479 messages::internalError(aResp->res);
480 BMCWEB_LOG_DEBUG
481 << "Invalid property type for FormFactor";
482 continue;
483 }
484 constexpr const std::array<const char*, 11> values{
485 "RDIMM", "UDIMM", "SO_DIMM",
486 "LRDIMM", "Mini_RDIMM", "Mini_UDIMM",
487 "SO_RDIMM_72b", "SO_UDIMM_72b", "SO_DIMM_16b",
488 "SO_DIMM_32b", "Die"};
489
490 for (const char* v : values)
491 {
492 if (boost::ends_with(*value, v))
493 {
494 aResp->res.jsonValue["BaseModuleType"] = v;
495 break;
496 }
497 }
498 }
499 else if (property.first == "AllowedSpeedsMT")
500 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700501 const std::vector<uint16_t>* value =
502 std::get_if<std::vector<uint16_t>>(&property.second);
503 if (value == nullptr)
504 {
505 continue;
506 }
507 nlohmann::json& jValue =
508 aResp->res.jsonValue["AllowedSpeedsMHz"];
509 jValue = nlohmann::json::array();
510 for (uint16_t subVal : *value)
511 {
512 jValue.push_back(subVal);
513 }
James Feistc50e7c62020-07-27 15:39:36 -0700514 }
515 else if (property.first == "MemoryAttributes")
516 {
517 const uint8_t* value =
518 std::get_if<uint8_t>(&property.second);
519
520 if (value == nullptr)
521 {
522 messages::internalError(aResp->res);
523 BMCWEB_LOG_DEBUG
524 << "Invalid property type for MemoryAttributes";
525 continue;
526 }
527 aResp->res.jsonValue["RankCount"] =
528 static_cast<uint64_t>(*value);
529 }
530 else if (property.first == "MemoryConfiguredSpeedInMhz")
531 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700532 const uint16_t* value =
533 std::get_if<uint16_t>(&property.second);
534 if (value == nullptr)
535 {
536 continue;
537 }
538 aResp->res.jsonValue["OperatingSpeedMhz"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700539 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200540 else if (property.first == "MemoryType")
541 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500542 const auto* value =
Ed Tanousabf2add2019-01-22 16:40:12 -0800543 std::get_if<std::string>(&property.second);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200544 if (value != nullptr)
545 {
James Feistc50e7c62020-07-27 15:39:36 -0700546 size_t idx = value->rfind(".");
547 if (idx == std::string::npos ||
548 idx + 1 >= value->size())
549 {
550 messages::internalError(aResp->res);
551 BMCWEB_LOG_DEBUG << "Invalid property type for "
552 "MemoryType";
553 }
554 std::string result = value->substr(idx + 1);
555 aResp->res.jsonValue["MemoryDeviceType"] = result;
556 if (value->find("DDR") != std::string::npos)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200557 {
558 aResp->res.jsonValue["MemoryType"] = "DRAM";
559 }
James Feistc50e7c62020-07-27 15:39:36 -0700560 else if (boost::ends_with(*value, "Logical"))
561 {
562 aResp->res.jsonValue["MemoryType"] = "IntelOptane";
563 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200564 }
565 }
James Feistc50e7c62020-07-27 15:39:36 -0700566 // memory location interface
567 else if (property.first == "Channel" ||
568 property.first == "MemoryController" ||
569 property.first == "Slot" || property.first == "Socket")
570 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700571 const std::string* value =
572 std::get_if<std::string>(&property.second);
573 if (value == nullptr)
574 {
575 messages::internalError(aResp->res);
576 continue;
577 }
James Feistc50e7c62020-07-27 15:39:36 -0700578 aResp->res.jsonValue["MemoryLocation"][property.first] =
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700579 *value;
James Feistc50e7c62020-07-27 15:39:36 -0700580 }
581 else
582 {
583 getPersistentMemoryProperties(aResp, properties);
584 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200585 }
586 },
587 service, objPath, "org.freedesktop.DBus.Properties", "GetAll", "");
588}
589
Ed Tanous23a21a12020-07-25 04:45:05 +0000590inline void getDimmPartitionData(std::shared_ptr<AsyncResp> aResp,
591 const std::string& service,
592 const std::string& path)
James Feist45094ad2020-04-29 14:02:30 -0700593{
594 crow::connections::systemBus->async_method_call(
595 [aResp{std::move(aResp)}](
596 const boost::system::error_code ec,
597 const boost::container::flat_map<
598 std::string, std::variant<std::string, uint64_t, uint32_t,
599 bool>>& properties) {
600 if (ec)
601 {
602 BMCWEB_LOG_DEBUG << "DBUS response error";
603 messages::internalError(aResp->res);
604
605 return;
606 }
607
608 nlohmann::json& partition =
609 aResp->res.jsonValue["Regions"].emplace_back(
610 nlohmann::json::object());
611 for (const auto& [key, val] : properties)
612 {
613 if (key == "MemoryClassification")
614 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700615 const std::string* value = std::get_if<std::string>(&val);
616 if (value == nullptr)
617 {
618 messages::internalError(aResp->res);
619 continue;
620 }
621 partition[key] = *value;
James Feist45094ad2020-04-29 14:02:30 -0700622 }
623 else if (key == "OffsetInKiB")
624 {
625 const uint64_t* value = std::get_if<uint64_t>(&val);
626 if (value == nullptr)
627 {
628 messages::internalError(aResp->res);
James Feist45094ad2020-04-29 14:02:30 -0700629 continue;
630 }
631
632 partition["OffsetMiB"] = (*value >> 10);
633 }
634 else if (key == "PartitionId")
635 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700636 const std::string* value = std::get_if<std::string>(&val);
637 if (value == nullptr)
638 {
639 messages::internalError(aResp->res);
640 continue;
641 }
642 partition["RegionId"] = *value;
James Feist45094ad2020-04-29 14:02:30 -0700643 }
644
645 else if (key == "PassphraseState")
646 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700647 const bool* value = std::get_if<bool>(&val);
648 if (value == nullptr)
649 {
650 messages::internalError(aResp->res);
651 continue;
652 }
653 partition["PassphraseEnabled"] = *value;
James Feist45094ad2020-04-29 14:02:30 -0700654 }
655 else if (key == "SizeInKiB")
656 {
657 const uint64_t* value = std::get_if<uint64_t>(&val);
658 if (value == nullptr)
659 {
660 messages::internalError(aResp->res);
661 BMCWEB_LOG_DEBUG
662 << "Invalid property type for SizeInKiB";
663 continue;
664 }
665 partition["SizeMiB"] = (*value >> 10);
666 }
667 }
668 },
669
670 service, path, "org.freedesktop.DBus.Properties", "GetAll",
671 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition");
672}
673
Ed Tanous23a21a12020-07-25 04:45:05 +0000674inline void getDimmData(std::shared_ptr<AsyncResp> aResp,
675 const std::string& dimmId)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200676{
677 BMCWEB_LOG_DEBUG << "Get available system dimm resources.";
678 crow::connections::systemBus->async_method_call(
Ed Tanous029573d2019-02-01 10:57:49 -0800679 [dimmId, aResp{std::move(aResp)}](
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200680 const boost::system::error_code ec,
681 const boost::container::flat_map<
682 std::string, boost::container::flat_map<
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500683 std::string, std::vector<std::string>>>&
684 subtree) {
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200685 if (ec)
686 {
687 BMCWEB_LOG_DEBUG << "DBUS response error";
688 messages::internalError(aResp->res);
689
690 return;
691 }
James Feist45094ad2020-04-29 14:02:30 -0700692 bool found = false;
693 for (const auto& [path, object] : subtree)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200694 {
James Feist45094ad2020-04-29 14:02:30 -0700695 if (path.find(dimmId) != std::string::npos)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200696 {
James Feist45094ad2020-04-29 14:02:30 -0700697 for (const auto& [service, interfaces] : object)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200698 {
James Feist45094ad2020-04-29 14:02:30 -0700699 if (!found &&
700 (std::find(
701 interfaces.begin(), interfaces.end(),
702 "xyz.openbmc_project.Inventory.Item.Dimm") !=
703 interfaces.end()))
704 {
705 getDimmDataByService(aResp, dimmId, service, path);
706 found = true;
707 }
708
709 // partitions are separate as there can be multiple per
710 // device, i.e.
711 // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition1
712 // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition2
713 if (std::find(interfaces.begin(), interfaces.end(),
714 "xyz.openbmc_project.Inventory.Item."
715 "PersistentMemory.Partition") !=
716 interfaces.end())
717 {
718 getDimmPartitionData(aResp, service, path);
719 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200720 }
721 }
722 }
723 // Object not found
James Feist45094ad2020-04-29 14:02:30 -0700724 if (!found)
725 {
726 messages::resourceNotFound(aResp->res, "Memory", dimmId);
727 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200728 return;
729 },
730 "xyz.openbmc_project.ObjectMapper",
731 "/xyz/openbmc_project/object_mapper",
732 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous271584a2019-07-09 16:24:22 -0700733 "/xyz/openbmc_project/inventory", 0,
James Feist45094ad2020-04-29 14:02:30 -0700734 std::array<const char*, 2>{
735 "xyz.openbmc_project.Inventory.Item.Dimm",
736 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition"});
Ed Tanous271584a2019-07-09 16:24:22 -0700737}
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200738
Ed Tanous029573d2019-02-01 10:57:49 -0800739class MemoryCollection : public Node
740{
741 public:
742 /*
743 * Default Constructor
744 */
Ed Tanous52cc1122020-07-18 13:51:21 -0700745 MemoryCollection(App& app) : Node(app, "/redfish/v1/Systems/system/Memory/")
Ed Tanous029573d2019-02-01 10:57:49 -0800746 {
747 entityPrivileges = {
748 {boost::beast::http::verb::get, {{"Login"}}},
749 {boost::beast::http::verb::head, {{"Login"}}},
750 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
751 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
752 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
753 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
754 }
755
756 private:
757 /**
758 * Functions triggers appropriate requests on DBus
759 */
Ed Tanouscb13a392020-07-25 19:02:03 +0000760 void doGet(crow::Response& res, const crow::Request&,
761 const std::vector<std::string>&) override
Ed Tanous029573d2019-02-01 10:57:49 -0800762 {
Ed Tanous0f74e642018-11-12 15:17:05 -0800763 res.jsonValue["@odata.type"] = "#MemoryCollection.MemoryCollection";
764 res.jsonValue["Name"] = "Memory Module Collection";
James Feistc50e7c62020-07-27 15:39:36 -0700765 res.jsonValue["@odata.id"] = "/redfish/v1/Systems/system/Memory";
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200766 auto asyncResp = std::make_shared<AsyncResp>(res);
767
Gunnar Mills05030b82020-10-14 15:51:31 -0500768 collection_util::getCollectionMembers(
769 asyncResp, "/redfish/v1/Systems/system/Memory",
770 {"xyz.openbmc_project.Inventory.Item.Dimm"});
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200771 }
772};
773
774class Memory : public Node
775{
776 public:
777 /*
778 * Default Constructor
779 */
Ed Tanous52cc1122020-07-18 13:51:21 -0700780 Memory(App& app) :
Ed Tanous029573d2019-02-01 10:57:49 -0800781 Node(app, "/redfish/v1/Systems/system/Memory/<str>/", std::string())
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200782 {
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200783 entityPrivileges = {
784 {boost::beast::http::verb::get, {{"Login"}}},
785 {boost::beast::http::verb::head, {{"Login"}}},
786 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
787 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
788 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
789 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
790 }
791
792 private:
793 /**
794 * Functions triggers appropriate requests on DBus
795 */
Ed Tanouscb13a392020-07-25 19:02:03 +0000796 void doGet(crow::Response& res, const crow::Request&,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500797 const std::vector<std::string>& params) override
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200798 {
799 // Check if there is required param, truly entering this shall be
800 // impossible
Ed Tanous029573d2019-02-01 10:57:49 -0800801 if (params.size() != 1)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200802 {
803 messages::internalError(res);
804 res.end();
805 return;
806 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500807 const std::string& dimmId = params[0];
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200808
James Feistc50e7c62020-07-27 15:39:36 -0700809 res.jsonValue["@odata.type"] = "#Memory.v1_7_0.Memory";
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200810 res.jsonValue["@odata.id"] =
Ed Tanous029573d2019-02-01 10:57:49 -0800811 "/redfish/v1/Systems/system/Memory/" + dimmId;
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200812 auto asyncResp = std::make_shared<AsyncResp>(res);
813
Ed Tanous029573d2019-02-01 10:57:49 -0800814 getDimmData(asyncResp, dimmId);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200815 }
816};
817
818} // namespace redfish