blob: 62d5933c089255d141639a49374ee336dafc2e62 [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
John Edward Broadbent7e860f12021-04-08 15:57:16 -070020#include <app.hpp>
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +020021#include <boost/container/flat_map.hpp>
James Feistc50e7c62020-07-27 15:39:36 -070022#include <boost/format.hpp>
Ed Tanoused398212021-06-09 17:05:54 -070023#include <registries/privilege_registry.hpp>
Gunnar Mills116bcc52020-10-14 15:23:42 -050024#include <utils/collection.hpp>
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +020025#include <utils/json_utils.hpp>
26
27namespace redfish
28{
29
James Feistc50e7c62020-07-27 15:39:36 -070030using DimmProperty =
31 std::variant<std::string, std::vector<uint32_t>, std::vector<uint16_t>,
32 uint64_t, uint32_t, uint16_t, uint8_t, bool>;
33
34using DimmProperties = boost::container::flat_map<std::string, DimmProperty>;
35
Gunnar Mills313efb12020-10-26 16:05:08 -050036inline std::string translateMemoryTypeToRedfish(const std::string& memoryType)
37{
38 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR")
39 {
40 return "DDR";
41 }
42 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR2")
43 {
44 return "DDR2";
45 }
46 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR3")
47 {
48 return "DDR3";
49 }
50 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR4")
51 {
52 return "DDR4";
53 }
54 if (memoryType ==
55 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR4E_SDRAM")
56 {
57 return "DDR4E_SDRAM";
58 }
59 if (memoryType ==
60 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.LPDDR4_SDRAM")
61 {
62 return "LPDDR4_SDRAM";
63 }
64 if (memoryType ==
65 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.LPDDR3_SDRAM")
66 {
67 return "LPDDR3_SDRAM";
68 }
69 if (memoryType ==
70 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR2_SDRAM_FB_DIMM")
71 {
72 return "DDR2_SDRAM_FB_DIMM";
73 }
74 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR2_"
75 "SDRAM_FB_DIMM_PROB")
76 {
77 return "DDR2_SDRAM_FB_DIMM_PROBE";
78 }
79 if (memoryType ==
80 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR_SGRAM")
81 {
82 return "DDR_SGRAM";
83 }
84 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.ROM")
85 {
86 return "ROM";
87 }
88 if (memoryType ==
89 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.SDRAM")
90 {
91 return "SDRAM";
92 }
93 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.EDO")
94 {
95 return "EDO";
96 }
97 if (memoryType ==
98 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.FastPageMode")
99 {
100 return "FastPageMode";
101 }
102 if (memoryType ==
103 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.PipelinedNibble")
104 {
105 return "PipelinedNibble";
106 }
107 if (memoryType ==
108 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.Logical")
109 {
110 return "Logical";
111 }
112 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.HBM")
113 {
114 return "HBM";
115 }
116 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.HBM2")
117 {
118 return "HBM2";
119 }
120 // This is values like Other or Unknown
121 // Also D-Bus values:
122 // DRAM
123 // EDRAM
124 // VRAM
125 // SRAM
126 // RAM
127 // FLASH
128 // EEPROM
129 // FEPROM
130 // EPROM
131 // CDRAM
132 // ThreeDRAM
133 // RDRAM
134 // FBD2
135 // LPDDR_SDRAM
136 // LPDDR2_SDRAM
137 return "";
138}
139
zhanghch058d1b46d2021-04-01 11:18:24 +0800140inline void dimmPropToHex(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanousb5a76932020-09-29 16:16:58 -0700141 const char* key,
Ed Tanous80789c82020-08-19 09:19:09 -0700142 const std::pair<std::string, DimmProperty>& property)
James Feistc50e7c62020-07-27 15:39:36 -0700143{
144 const uint16_t* value = std::get_if<uint16_t>(&property.second);
145 if (value == nullptr)
146 {
147 messages::internalError(aResp->res);
148 BMCWEB_LOG_DEBUG << "Invalid property type for " << property.first;
149 return;
150 }
151
152 aResp->res.jsonValue[key] = (boost::format("0x%04x") % *value).str();
153}
154
zhanghch058d1b46d2021-04-01 11:18:24 +0800155inline void getPersistentMemoryProperties(
156 const std::shared_ptr<bmcweb::AsyncResp>& aResp,
157 const DimmProperties& properties)
James Feistc50e7c62020-07-27 15:39:36 -0700158{
159 for (const auto& property : properties)
160 {
161 if (property.first == "ModuleManufacturerID")
162 {
163 dimmPropToHex(aResp, "ModuleManufacturerID", property);
164 }
165 else if (property.first == "ModuleProductID")
166 {
167 dimmPropToHex(aResp, "ModuleProductID", property);
168 }
169 else if (property.first == "SubsystemVendorID")
170 {
171 dimmPropToHex(aResp, "MemorySubsystemControllerManufacturerID",
172 property);
173 }
174 else if (property.first == "SubsystemDeviceID")
175 {
176 dimmPropToHex(aResp, "MemorySubsystemControllerProductID",
177 property);
178 }
179 else if (property.first == "VolatileRegionSizeLimitInKiB")
180 {
181 const uint64_t* value = std::get_if<uint64_t>(&property.second);
182
183 if (value == nullptr)
184 {
185 messages::internalError(aResp->res);
186 BMCWEB_LOG_DEBUG << "Invalid property type for "
187 "VolatileRegionSizeLimitKiB";
Chicago Duan601af5e2021-04-15 16:59:25 +0800188 return;
James Feistc50e7c62020-07-27 15:39:36 -0700189 }
190 aResp->res.jsonValue["VolatileRegionSizeLimitMiB"] = (*value) >> 10;
191 }
192 else if (property.first == "PmRegionSizeLimitInKiB")
193 {
194 const uint64_t* value = std::get_if<uint64_t>(&property.second);
195
196 if (value == nullptr)
197 {
198 messages::internalError(aResp->res);
199 BMCWEB_LOG_DEBUG
200 << "Invalid property type for PmRegioSizeLimitKiB";
Chicago Duan601af5e2021-04-15 16:59:25 +0800201 return;
James Feistc50e7c62020-07-27 15:39:36 -0700202 }
203 aResp->res.jsonValue["PersistentRegionSizeLimitMiB"] =
204 (*value) >> 10;
205 }
206 else if (property.first == "VolatileSizeInKiB")
207 {
208 const uint64_t* value = std::get_if<uint64_t>(&property.second);
209
210 if (value == nullptr)
211 {
212 messages::internalError(aResp->res);
213 BMCWEB_LOG_DEBUG
214 << "Invalid property type for VolatileSizeInKiB";
Chicago Duan601af5e2021-04-15 16:59:25 +0800215 return;
James Feistc50e7c62020-07-27 15:39:36 -0700216 }
217 aResp->res.jsonValue["VolatileSizeMiB"] = (*value) >> 10;
218 }
219 else if (property.first == "PmSizeInKiB")
220 {
221 const uint64_t* value = std::get_if<uint64_t>(&property.second);
222 if (value == nullptr)
223 {
224 messages::internalError(aResp->res);
225 BMCWEB_LOG_DEBUG << "Invalid property type for PmSizeInKiB";
Chicago Duan601af5e2021-04-15 16:59:25 +0800226 return;
James Feistc50e7c62020-07-27 15:39:36 -0700227 }
228 aResp->res.jsonValue["NonVolatileSizeMiB"] = (*value) >> 10;
229 }
230 else if (property.first == "CacheSizeInKB")
231 {
232 const uint64_t* value = std::get_if<uint64_t>(&property.second);
233 if (value == nullptr)
234 {
235 messages::internalError(aResp->res);
236 BMCWEB_LOG_DEBUG << "Invalid property type for CacheSizeInKB";
Chicago Duan601af5e2021-04-15 16:59:25 +0800237 return;
James Feistc50e7c62020-07-27 15:39:36 -0700238 }
239 aResp->res.jsonValue["CacheSizeMiB"] = (*value >> 10);
240 }
241
242 else if (property.first == "VoltaileRegionMaxSizeInKib")
243 {
244 const uint64_t* value = std::get_if<uint64_t>(&property.second);
245
246 if (value == nullptr)
247 {
248 messages::internalError(aResp->res);
249 BMCWEB_LOG_DEBUG << "Invalid property type for "
250 "VolatileRegionMaxSizeInKib";
Chicago Duan601af5e2021-04-15 16:59:25 +0800251 return;
James Feistc50e7c62020-07-27 15:39:36 -0700252 }
253 aResp->res.jsonValue["VolatileRegionSizeMaxMiB"] = (*value) >> 10;
254 }
255 else if (property.first == "PmRegionMaxSizeInKiB")
256 {
257 const uint64_t* value = std::get_if<uint64_t>(&property.second);
258
259 if (value == nullptr)
260 {
261 messages::internalError(aResp->res);
262 BMCWEB_LOG_DEBUG
263 << "Invalid property type for PmRegionMaxSizeInKiB";
Chicago Duan601af5e2021-04-15 16:59:25 +0800264 return;
James Feistc50e7c62020-07-27 15:39:36 -0700265 }
266 aResp->res.jsonValue["PersistentRegionSizeMaxMiB"] = (*value) >> 10;
267 }
268 else if (property.first == "AllocationIncrementInKiB")
269 {
270 const uint64_t* value = std::get_if<uint64_t>(&property.second);
271
272 if (value == nullptr)
273 {
274 messages::internalError(aResp->res);
275 BMCWEB_LOG_DEBUG << "Invalid property type for "
276 "AllocationIncrementInKiB";
Chicago Duan601af5e2021-04-15 16:59:25 +0800277 return;
James Feistc50e7c62020-07-27 15:39:36 -0700278 }
279 aResp->res.jsonValue["AllocationIncrementMiB"] = (*value) >> 10;
280 }
281 else if (property.first == "AllocationAlignmentInKiB")
282 {
283 const uint64_t* value = std::get_if<uint64_t>(&property.second);
284
285 if (value == nullptr)
286 {
287 messages::internalError(aResp->res);
288 BMCWEB_LOG_DEBUG << "Invalid property type for "
289 "AllocationAlignmentInKiB";
Chicago Duan601af5e2021-04-15 16:59:25 +0800290 return;
James Feistc50e7c62020-07-27 15:39:36 -0700291 }
292 aResp->res.jsonValue["AllocationAlignmentMiB"] = (*value) >> 10;
293 }
294 else if (property.first == "VolatileRegionNumberLimit")
295 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700296 const uint64_t* value = std::get_if<uint64_t>(&property.second);
297 if (value == nullptr)
298 {
299 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800300 return;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700301 }
302 aResp->res.jsonValue["VolatileRegionNumberLimit"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700303 }
304 else if (property.first == "PmRegionNumberLimit")
305 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700306 const uint64_t* value = std::get_if<uint64_t>(&property.second);
307 if (value == nullptr)
308 {
309 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800310 return;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700311 }
312 aResp->res.jsonValue["PersistentRegionNumberLimit"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700313 }
314 else if (property.first == "SpareDeviceCount")
315 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700316 const uint64_t* value = std::get_if<uint64_t>(&property.second);
317 if (value == nullptr)
318 {
319 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800320 return;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700321 }
322 aResp->res.jsonValue["SpareDeviceCount"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700323 }
324 else if (property.first == "IsSpareDeviceInUse")
325 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700326 const bool* value = std::get_if<bool>(&property.second);
327 if (value == nullptr)
328 {
329 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800330 return;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700331 }
332 aResp->res.jsonValue["IsSpareDeviceEnabled"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700333 }
334 else if (property.first == "IsRankSpareEnabled")
335 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700336 const bool* value = std::get_if<bool>(&property.second);
337 if (value == nullptr)
338 {
339 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800340 return;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700341 }
342 aResp->res.jsonValue["IsRankSpareEnabled"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700343 }
344 else if (property.first == "MaxAveragePowerLimitmW")
345 {
346 const auto* value =
347 std::get_if<std::vector<uint32_t>>(&property.second);
348 if (value == nullptr)
349 {
350 messages::internalError(aResp->res);
351 BMCWEB_LOG_DEBUG << "Invalid property type for "
352 "MaxAveragePowerLimitmW";
Chicago Duan601af5e2021-04-15 16:59:25 +0800353 return;
James Feistc50e7c62020-07-27 15:39:36 -0700354 }
355 aResp->res.jsonValue["MaxTDPMilliWatts"] = *value;
356 }
James Feistc50e7c62020-07-27 15:39:36 -0700357 else if (property.first == "ConfigurationLocked")
358 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700359 const bool* value = std::get_if<bool>(&property.second);
360 if (value == nullptr)
361 {
362 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800363 return;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700364 }
365 aResp->res.jsonValue["ConfigurationLocked"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700366 }
367 else if (property.first == "AllowedMemoryModes")
368 {
369 const std::string* value =
370 std::get_if<std::string>(&property.second);
371 if (value == nullptr)
372 {
373 messages::internalError(aResp->res);
374 BMCWEB_LOG_DEBUG << "Invalid property type for FormFactor";
Chicago Duan601af5e2021-04-15 16:59:25 +0800375 return;
James Feistc50e7c62020-07-27 15:39:36 -0700376 }
377 constexpr const std::array<const char*, 3> values{"Volatile",
378 "PMEM", "Block"};
379
380 for (const char* v : values)
381 {
382 if (boost::ends_with(*value, v))
383 {
384 aResp->res.jsonValue["OperatingMemoryModes "] = v;
385 break;
386 }
387 }
388 }
389 else if (property.first == "MemoryMedia")
390 {
391 const std::string* value =
392 std::get_if<std::string>(&property.second);
393 if (value == nullptr)
394 {
395 messages::internalError(aResp->res);
396 BMCWEB_LOG_DEBUG << "Invalid property type for MemoryMedia";
Chicago Duan601af5e2021-04-15 16:59:25 +0800397 return;
James Feistc50e7c62020-07-27 15:39:36 -0700398 }
399 constexpr const std::array<const char*, 3> values{"DRAM", "NAND",
400 "Intel3DXPoint"};
401
402 for (const char* v : values)
403 {
404 if (boost::ends_with(*value, v))
405 {
406 aResp->res.jsonValue["MemoryMedia"] = v;
407 break;
408 }
409 }
410 }
James Feistc50e7c62020-07-27 15:39:36 -0700411 // PersistantMemory.SecurityCapabilites interface
412 else if (property.first == "ConfigurationLockCapable" ||
413 property.first == "DataLockCapable" ||
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700414 property.first == "PassphraseCapable")
415 {
416 const bool* value = std::get_if<bool>(&property.second);
417 if (value == nullptr)
418 {
419 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800420 return;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700421 }
422 aResp->res.jsonValue["SecurityCapabilities"][property.first] =
423 *value;
424 }
425 else if (property.first == "MaxPassphraseCount" ||
James Feistc50e7c62020-07-27 15:39:36 -0700426 property.first == "PassphraseLockLimit")
427 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700428 const uint64_t* value = std::get_if<uint64_t>(&property.second);
429 if (value == nullptr)
430 {
431 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800432 return;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700433 }
James Feistc50e7c62020-07-27 15:39:36 -0700434 aResp->res.jsonValue["SecurityCapabilities"][property.first] =
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700435 *value;
James Feistc50e7c62020-07-27 15:39:36 -0700436 }
437 }
438}
439
zhanghch058d1b46d2021-04-01 11:18:24 +0800440inline void getDimmDataByService(std::shared_ptr<bmcweb::AsyncResp> aResp,
Ed Tanous80789c82020-08-19 09:19:09 -0700441 const std::string& dimmId,
442 const std::string& service,
443 const std::string& objPath)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200444{
James Feist35e257a2020-06-05 13:30:51 -0700445 auto health = std::make_shared<HealthPopulate>(aResp);
446 health->selfPath = objPath;
447 health->populate();
448
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200449 BMCWEB_LOG_DEBUG << "Get available system components.";
450 crow::connections::systemBus->async_method_call(
James Feistc50e7c62020-07-27 15:39:36 -0700451 [dimmId, aResp{std::move(aResp)}](const boost::system::error_code ec,
452 const DimmProperties& properties) {
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200453 if (ec)
454 {
455 BMCWEB_LOG_DEBUG << "DBUS response error";
456 messages::internalError(aResp->res);
457
458 return;
459 }
460 aResp->res.jsonValue["Id"] = dimmId;
461 aResp->res.jsonValue["Name"] = "DIMM Slot";
462
463 const auto memorySizeProperty = properties.find("MemorySizeInKB");
Gunnar Millsaceb7fc2018-12-10 15:17:20 -0600464 if (memorySizeProperty != properties.end())
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200465 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500466 const uint32_t* memorySize =
Ed Tanousabf2add2019-01-22 16:40:12 -0800467 std::get_if<uint32_t>(&memorySizeProperty->second);
Gunnar Millsaceb7fc2018-12-10 15:17:20 -0600468 if (memorySize == nullptr)
469 {
470 // Important property not in desired type
471 messages::internalError(aResp->res);
Gunnar Millsaceb7fc2018-12-10 15:17:20 -0600472 return;
473 }
474 aResp->res.jsonValue["CapacityMiB"] = (*memorySize >> 10);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200475 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200476 aResp->res.jsonValue["Status"]["State"] = "Enabled";
477 aResp->res.jsonValue["Status"]["Health"] = "OK";
478
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500479 for (const auto& property : properties)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200480 {
481 if (property.first == "MemoryDataWidth")
482 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700483 const uint16_t* value =
484 std::get_if<uint16_t>(&property.second);
485 if (value == nullptr)
486 {
487 continue;
488 }
489 aResp->res.jsonValue["DataWidthBits"] = *value;
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200490 }
Manojkiran Eda7e236ca2019-06-25 23:06:32 +0530491 else if (property.first == "PartNumber")
492 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700493 const std::string* value =
494 std::get_if<std::string>(&property.second);
495 if (value == nullptr)
496 {
497 continue;
498 }
499 aResp->res.jsonValue["PartNumber"] = *value;
Manojkiran Eda7e236ca2019-06-25 23:06:32 +0530500 }
501 else if (property.first == "SerialNumber")
502 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700503 const std::string* value =
504 std::get_if<std::string>(&property.second);
505 if (value == nullptr)
506 {
507 continue;
508 }
509 aResp->res.jsonValue["SerialNumber"] = *value;
Manojkiran Eda7e236ca2019-06-25 23:06:32 +0530510 }
511 else if (property.first == "Manufacturer")
512 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700513 const std::string* value =
514 std::get_if<std::string>(&property.second);
515 if (value == nullptr)
516 {
517 continue;
518 }
519 aResp->res.jsonValue["Manufacturer"] = *value;
Manojkiran Eda7e236ca2019-06-25 23:06:32 +0530520 }
James Feistc50e7c62020-07-27 15:39:36 -0700521 else if (property.first == "RevisionCode")
522 {
523 const uint16_t* value =
524 std::get_if<uint16_t>(&property.second);
525
526 if (value == nullptr)
527 {
528 messages::internalError(aResp->res);
529 BMCWEB_LOG_DEBUG
530 << "Invalid property type for RevisionCode";
Chicago Duan601af5e2021-04-15 16:59:25 +0800531 return;
James Feistc50e7c62020-07-27 15:39:36 -0700532 }
533 aResp->res.jsonValue["FirmwareRevision"] =
534 std::to_string(*value);
535 }
Joshi-Mansi9a128eb2021-03-19 03:30:17 +0530536 else if (property.first == "Present")
537 {
538 const bool* value = std::get_if<bool>(&property.second);
539 if (value == nullptr)
540 {
541 messages::internalError(aResp->res);
542 BMCWEB_LOG_DEBUG
543 << "Invalid property type for Dimm Presence";
544 return;
545 }
546 if (*value == false)
547 {
548 aResp->res.jsonValue["Status"]["State"] = "Absent";
549 }
550 }
James Feistc50e7c62020-07-27 15:39:36 -0700551 else if (property.first == "MemoryTotalWidth")
552 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700553 const uint16_t* value =
554 std::get_if<uint16_t>(&property.second);
555 if (value == nullptr)
556 {
557 continue;
558 }
559 aResp->res.jsonValue["BusWidthBits"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700560 }
561 else if (property.first == "ECC")
562 {
563 const std::string* value =
564 std::get_if<std::string>(&property.second);
565 if (value == nullptr)
566 {
567 messages::internalError(aResp->res);
568 BMCWEB_LOG_DEBUG << "Invalid property type for ECC";
Chicago Duan601af5e2021-04-15 16:59:25 +0800569 return;
James Feistc50e7c62020-07-27 15:39:36 -0700570 }
571 constexpr const std::array<const char*, 4> values{
572 "NoECC", "SingleBitECC", "MultiBitECC",
573 "AddressParity"};
574
575 for (const char* v : values)
576 {
577 if (boost::ends_with(*value, v))
578 {
579 aResp->res.jsonValue["ErrorCorrection"] = v;
580 break;
581 }
582 }
583 }
584 else if (property.first == "FormFactor")
585 {
586 const std::string* value =
587 std::get_if<std::string>(&property.second);
588 if (value == nullptr)
589 {
590 messages::internalError(aResp->res);
591 BMCWEB_LOG_DEBUG
592 << "Invalid property type for FormFactor";
Chicago Duan601af5e2021-04-15 16:59:25 +0800593 return;
James Feistc50e7c62020-07-27 15:39:36 -0700594 }
595 constexpr const std::array<const char*, 11> values{
596 "RDIMM", "UDIMM", "SO_DIMM",
597 "LRDIMM", "Mini_RDIMM", "Mini_UDIMM",
598 "SO_RDIMM_72b", "SO_UDIMM_72b", "SO_DIMM_16b",
599 "SO_DIMM_32b", "Die"};
600
601 for (const char* v : values)
602 {
603 if (boost::ends_with(*value, v))
604 {
605 aResp->res.jsonValue["BaseModuleType"] = v;
606 break;
607 }
608 }
609 }
610 else if (property.first == "AllowedSpeedsMT")
611 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700612 const std::vector<uint16_t>* value =
613 std::get_if<std::vector<uint16_t>>(&property.second);
614 if (value == nullptr)
615 {
616 continue;
617 }
618 nlohmann::json& jValue =
619 aResp->res.jsonValue["AllowedSpeedsMHz"];
620 jValue = nlohmann::json::array();
621 for (uint16_t subVal : *value)
622 {
623 jValue.push_back(subVal);
624 }
James Feistc50e7c62020-07-27 15:39:36 -0700625 }
626 else if (property.first == "MemoryAttributes")
627 {
628 const uint8_t* value =
629 std::get_if<uint8_t>(&property.second);
630
631 if (value == nullptr)
632 {
633 messages::internalError(aResp->res);
634 BMCWEB_LOG_DEBUG
635 << "Invalid property type for MemoryAttributes";
Chicago Duan601af5e2021-04-15 16:59:25 +0800636 return;
James Feistc50e7c62020-07-27 15:39:36 -0700637 }
638 aResp->res.jsonValue["RankCount"] =
639 static_cast<uint64_t>(*value);
640 }
641 else if (property.first == "MemoryConfiguredSpeedInMhz")
642 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700643 const uint16_t* value =
644 std::get_if<uint16_t>(&property.second);
645 if (value == nullptr)
646 {
647 continue;
648 }
649 aResp->res.jsonValue["OperatingSpeedMhz"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700650 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200651 else if (property.first == "MemoryType")
652 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500653 const auto* value =
Ed Tanousabf2add2019-01-22 16:40:12 -0800654 std::get_if<std::string>(&property.second);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200655 if (value != nullptr)
656 {
Gunnar Mills313efb12020-10-26 16:05:08 -0500657 std::string memoryDeviceType =
658 translateMemoryTypeToRedfish(*value);
659 // Values like "Unknown" or "Other" will return empty
660 // so just leave off
661 if (!memoryDeviceType.empty())
James Feistc50e7c62020-07-27 15:39:36 -0700662 {
Gunnar Mills313efb12020-10-26 16:05:08 -0500663 aResp->res.jsonValue["MemoryDeviceType"] =
664 memoryDeviceType;
James Feistc50e7c62020-07-27 15:39:36 -0700665 }
James Feistc50e7c62020-07-27 15:39:36 -0700666 if (value->find("DDR") != std::string::npos)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200667 {
668 aResp->res.jsonValue["MemoryType"] = "DRAM";
669 }
James Feistc50e7c62020-07-27 15:39:36 -0700670 else if (boost::ends_with(*value, "Logical"))
671 {
672 aResp->res.jsonValue["MemoryType"] = "IntelOptane";
673 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200674 }
675 }
James Feistc50e7c62020-07-27 15:39:36 -0700676 // memory location interface
677 else if (property.first == "Channel" ||
678 property.first == "MemoryController" ||
679 property.first == "Slot" || property.first == "Socket")
680 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700681 const std::string* value =
682 std::get_if<std::string>(&property.second);
683 if (value == nullptr)
684 {
685 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800686 return;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700687 }
James Feistc50e7c62020-07-27 15:39:36 -0700688 aResp->res.jsonValue["MemoryLocation"][property.first] =
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700689 *value;
James Feistc50e7c62020-07-27 15:39:36 -0700690 }
SunnySrivastava1984ee135e22020-12-15 12:42:19 -0600691 else if (property.first == "SparePartNumber")
692 {
693 const std::string* value =
694 std::get_if<std::string>(&property.second);
695 if (value == nullptr)
696 {
697 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800698 return;
SunnySrivastava1984ee135e22020-12-15 12:42:19 -0600699 }
700 aResp->res.jsonValue["SparePartNumber"] = *value;
701 }
702 else if (property.first == "Model")
703 {
704 const std::string* value =
705 std::get_if<std::string>(&property.second);
706 if (value == nullptr)
707 {
708 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800709 return;
SunnySrivastava1984ee135e22020-12-15 12:42:19 -0600710 }
711 aResp->res.jsonValue["Model"] = *value;
712 }
713 else if (property.first == "LocationCode")
714 {
715 const std::string* value =
716 std::get_if<std::string>(&property.second);
717 if (value == nullptr)
718 {
719 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800720 return;
SunnySrivastava1984ee135e22020-12-15 12:42:19 -0600721 }
722 aResp->res
723 .jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
724 *value;
725 }
James Feistc50e7c62020-07-27 15:39:36 -0700726 else
727 {
728 getPersistentMemoryProperties(aResp, properties);
729 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200730 }
731 },
732 service, objPath, "org.freedesktop.DBus.Properties", "GetAll", "");
733}
734
zhanghch058d1b46d2021-04-01 11:18:24 +0800735inline void getDimmPartitionData(std::shared_ptr<bmcweb::AsyncResp> aResp,
Ed Tanous23a21a12020-07-25 04:45:05 +0000736 const std::string& service,
737 const std::string& path)
James Feist45094ad2020-04-29 14:02:30 -0700738{
739 crow::connections::systemBus->async_method_call(
740 [aResp{std::move(aResp)}](
741 const boost::system::error_code ec,
742 const boost::container::flat_map<
743 std::string, std::variant<std::string, uint64_t, uint32_t,
744 bool>>& properties) {
745 if (ec)
746 {
747 BMCWEB_LOG_DEBUG << "DBUS response error";
748 messages::internalError(aResp->res);
749
750 return;
751 }
752
753 nlohmann::json& partition =
754 aResp->res.jsonValue["Regions"].emplace_back(
755 nlohmann::json::object());
756 for (const auto& [key, val] : properties)
757 {
758 if (key == "MemoryClassification")
759 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700760 const std::string* value = std::get_if<std::string>(&val);
761 if (value == nullptr)
762 {
763 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800764 return;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700765 }
766 partition[key] = *value;
James Feist45094ad2020-04-29 14:02:30 -0700767 }
768 else if (key == "OffsetInKiB")
769 {
770 const uint64_t* value = std::get_if<uint64_t>(&val);
771 if (value == nullptr)
772 {
773 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800774 return;
James Feist45094ad2020-04-29 14:02:30 -0700775 }
776
777 partition["OffsetMiB"] = (*value >> 10);
778 }
779 else if (key == "PartitionId")
780 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700781 const std::string* value = std::get_if<std::string>(&val);
782 if (value == nullptr)
783 {
784 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800785 return;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700786 }
787 partition["RegionId"] = *value;
James Feist45094ad2020-04-29 14:02:30 -0700788 }
789
790 else if (key == "PassphraseState")
791 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700792 const bool* value = std::get_if<bool>(&val);
793 if (value == nullptr)
794 {
795 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800796 return;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700797 }
798 partition["PassphraseEnabled"] = *value;
James Feist45094ad2020-04-29 14:02:30 -0700799 }
800 else if (key == "SizeInKiB")
801 {
802 const uint64_t* value = std::get_if<uint64_t>(&val);
803 if (value == nullptr)
804 {
805 messages::internalError(aResp->res);
806 BMCWEB_LOG_DEBUG
807 << "Invalid property type for SizeInKiB";
Chicago Duan601af5e2021-04-15 16:59:25 +0800808 return;
James Feist45094ad2020-04-29 14:02:30 -0700809 }
810 partition["SizeMiB"] = (*value >> 10);
811 }
812 }
813 },
814
815 service, path, "org.freedesktop.DBus.Properties", "GetAll",
816 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition");
817}
818
zhanghch058d1b46d2021-04-01 11:18:24 +0800819inline void getDimmData(std::shared_ptr<bmcweb::AsyncResp> aResp,
Ed Tanous23a21a12020-07-25 04:45:05 +0000820 const std::string& dimmId)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200821{
822 BMCWEB_LOG_DEBUG << "Get available system dimm resources.";
823 crow::connections::systemBus->async_method_call(
Ed Tanous029573d2019-02-01 10:57:49 -0800824 [dimmId, aResp{std::move(aResp)}](
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200825 const boost::system::error_code ec,
826 const boost::container::flat_map<
827 std::string, boost::container::flat_map<
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500828 std::string, std::vector<std::string>>>&
829 subtree) {
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200830 if (ec)
831 {
832 BMCWEB_LOG_DEBUG << "DBUS response error";
833 messages::internalError(aResp->res);
834
835 return;
836 }
James Feist45094ad2020-04-29 14:02:30 -0700837 bool found = false;
838 for (const auto& [path, object] : subtree)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200839 {
James Feist45094ad2020-04-29 14:02:30 -0700840 if (path.find(dimmId) != std::string::npos)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200841 {
James Feist45094ad2020-04-29 14:02:30 -0700842 for (const auto& [service, interfaces] : object)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200843 {
James Feist45094ad2020-04-29 14:02:30 -0700844 if (!found &&
845 (std::find(
846 interfaces.begin(), interfaces.end(),
847 "xyz.openbmc_project.Inventory.Item.Dimm") !=
848 interfaces.end()))
849 {
850 getDimmDataByService(aResp, dimmId, service, path);
851 found = true;
852 }
853
854 // partitions are separate as there can be multiple per
855 // device, i.e.
856 // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition1
857 // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition2
858 if (std::find(interfaces.begin(), interfaces.end(),
859 "xyz.openbmc_project.Inventory.Item."
860 "PersistentMemory.Partition") !=
861 interfaces.end())
862 {
863 getDimmPartitionData(aResp, service, path);
864 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200865 }
866 }
867 }
868 // Object not found
James Feist45094ad2020-04-29 14:02:30 -0700869 if (!found)
870 {
871 messages::resourceNotFound(aResp->res, "Memory", dimmId);
872 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200873 return;
874 },
875 "xyz.openbmc_project.ObjectMapper",
876 "/xyz/openbmc_project/object_mapper",
877 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous271584a2019-07-09 16:24:22 -0700878 "/xyz/openbmc_project/inventory", 0,
James Feist45094ad2020-04-29 14:02:30 -0700879 std::array<const char*, 2>{
880 "xyz.openbmc_project.Inventory.Item.Dimm",
881 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition"});
Ed Tanous271584a2019-07-09 16:24:22 -0700882}
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200883
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700884inline void requestRoutesMemoryCollection(App& app)
Ed Tanous029573d2019-02-01 10:57:49 -0800885{
Ed Tanous029573d2019-02-01 10:57:49 -0800886 /**
887 * Functions triggers appropriate requests on DBus
888 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700889 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Memory/")
Ed Tanoused398212021-06-09 17:05:54 -0700890 .privileges(redfish::privileges::getMemoryCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700891 .methods(boost::beast::http::verb::get)(
892 [](const crow::Request&,
893 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
894 asyncResp->res.jsonValue["@odata.type"] =
895 "#MemoryCollection.MemoryCollection";
896 asyncResp->res.jsonValue["Name"] = "Memory Module Collection";
897 asyncResp->res.jsonValue["@odata.id"] =
898 "/redfish/v1/Systems/system/Memory";
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200899
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700900 collection_util::getCollectionMembers(
901 asyncResp, "/redfish/v1/Systems/system/Memory",
902 {"xyz.openbmc_project.Inventory.Item.Dimm"});
903 });
904}
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200905
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700906inline void requestRoutesMemory(App& app)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200907{
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200908 /**
909 * Functions triggers appropriate requests on DBus
910 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700911 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Memory/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700912 .privileges(redfish::privileges::getMemory)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700913 .methods(boost::beast::http::verb::get)(
914 [](const crow::Request&,
915 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
916 const std::string& dimmId) {
917 asyncResp->res.jsonValue["@odata.type"] =
918 "#Memory.v1_11_0.Memory";
919 asyncResp->res.jsonValue["@odata.id"] =
920 "/redfish/v1/Systems/system/Memory/" + dimmId;
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200921
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700922 getDimmData(asyncResp, dimmId);
923 });
924}
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200925
926} // namespace redfish