blob: 465beae532519fa853cc81a6b14dcb347dc1fa94 [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>
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
Gunnar Mills313efb12020-10-26 16:05:08 -050035inline std::string translateMemoryTypeToRedfish(const std::string& memoryType)
36{
37 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR")
38 {
39 return "DDR";
40 }
41 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR2")
42 {
43 return "DDR2";
44 }
45 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR3")
46 {
47 return "DDR3";
48 }
49 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR4")
50 {
51 return "DDR4";
52 }
53 if (memoryType ==
54 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR4E_SDRAM")
55 {
56 return "DDR4E_SDRAM";
57 }
58 if (memoryType ==
59 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.LPDDR4_SDRAM")
60 {
61 return "LPDDR4_SDRAM";
62 }
63 if (memoryType ==
64 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.LPDDR3_SDRAM")
65 {
66 return "LPDDR3_SDRAM";
67 }
68 if (memoryType ==
69 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR2_SDRAM_FB_DIMM")
70 {
71 return "DDR2_SDRAM_FB_DIMM";
72 }
73 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR2_"
74 "SDRAM_FB_DIMM_PROB")
75 {
76 return "DDR2_SDRAM_FB_DIMM_PROBE";
77 }
78 if (memoryType ==
79 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR_SGRAM")
80 {
81 return "DDR_SGRAM";
82 }
83 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.ROM")
84 {
85 return "ROM";
86 }
87 if (memoryType ==
88 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.SDRAM")
89 {
90 return "SDRAM";
91 }
92 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.EDO")
93 {
94 return "EDO";
95 }
96 if (memoryType ==
97 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.FastPageMode")
98 {
99 return "FastPageMode";
100 }
101 if (memoryType ==
102 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.PipelinedNibble")
103 {
104 return "PipelinedNibble";
105 }
106 if (memoryType ==
107 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.Logical")
108 {
109 return "Logical";
110 }
111 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.HBM")
112 {
113 return "HBM";
114 }
115 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.HBM2")
116 {
117 return "HBM2";
118 }
119 // This is values like Other or Unknown
120 // Also D-Bus values:
121 // DRAM
122 // EDRAM
123 // VRAM
124 // SRAM
125 // RAM
126 // FLASH
127 // EEPROM
128 // FEPROM
129 // EPROM
130 // CDRAM
131 // ThreeDRAM
132 // RDRAM
133 // FBD2
134 // LPDDR_SDRAM
135 // LPDDR2_SDRAM
136 return "";
137}
138
zhanghch058d1b46d2021-04-01 11:18:24 +0800139inline void dimmPropToHex(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanousb5a76932020-09-29 16:16:58 -0700140 const char* key,
Ed Tanous80789c82020-08-19 09:19:09 -0700141 const std::pair<std::string, DimmProperty>& property)
James Feistc50e7c62020-07-27 15:39:36 -0700142{
143 const uint16_t* value = std::get_if<uint16_t>(&property.second);
144 if (value == nullptr)
145 {
146 messages::internalError(aResp->res);
147 BMCWEB_LOG_DEBUG << "Invalid property type for " << property.first;
148 return;
149 }
150
151 aResp->res.jsonValue[key] = (boost::format("0x%04x") % *value).str();
152}
153
zhanghch058d1b46d2021-04-01 11:18:24 +0800154inline void getPersistentMemoryProperties(
155 const std::shared_ptr<bmcweb::AsyncResp>& aResp,
156 const DimmProperties& properties)
James Feistc50e7c62020-07-27 15:39:36 -0700157{
158 for (const auto& property : properties)
159 {
160 if (property.first == "ModuleManufacturerID")
161 {
162 dimmPropToHex(aResp, "ModuleManufacturerID", property);
163 }
164 else if (property.first == "ModuleProductID")
165 {
166 dimmPropToHex(aResp, "ModuleProductID", property);
167 }
168 else if (property.first == "SubsystemVendorID")
169 {
170 dimmPropToHex(aResp, "MemorySubsystemControllerManufacturerID",
171 property);
172 }
173 else if (property.first == "SubsystemDeviceID")
174 {
175 dimmPropToHex(aResp, "MemorySubsystemControllerProductID",
176 property);
177 }
178 else if (property.first == "VolatileRegionSizeLimitInKiB")
179 {
180 const uint64_t* value = std::get_if<uint64_t>(&property.second);
181
182 if (value == nullptr)
183 {
184 messages::internalError(aResp->res);
185 BMCWEB_LOG_DEBUG << "Invalid property type for "
186 "VolatileRegionSizeLimitKiB";
Chicago Duan601af5e2021-04-15 16:59:25 +0800187 return;
James Feistc50e7c62020-07-27 15:39:36 -0700188 }
189 aResp->res.jsonValue["VolatileRegionSizeLimitMiB"] = (*value) >> 10;
190 }
191 else if (property.first == "PmRegionSizeLimitInKiB")
192 {
193 const uint64_t* value = std::get_if<uint64_t>(&property.second);
194
195 if (value == nullptr)
196 {
197 messages::internalError(aResp->res);
198 BMCWEB_LOG_DEBUG
199 << "Invalid property type for PmRegioSizeLimitKiB";
Chicago Duan601af5e2021-04-15 16:59:25 +0800200 return;
James Feistc50e7c62020-07-27 15:39:36 -0700201 }
202 aResp->res.jsonValue["PersistentRegionSizeLimitMiB"] =
203 (*value) >> 10;
204 }
205 else if (property.first == "VolatileSizeInKiB")
206 {
207 const uint64_t* value = std::get_if<uint64_t>(&property.second);
208
209 if (value == nullptr)
210 {
211 messages::internalError(aResp->res);
212 BMCWEB_LOG_DEBUG
213 << "Invalid property type for VolatileSizeInKiB";
Chicago Duan601af5e2021-04-15 16:59:25 +0800214 return;
James Feistc50e7c62020-07-27 15:39:36 -0700215 }
216 aResp->res.jsonValue["VolatileSizeMiB"] = (*value) >> 10;
217 }
218 else if (property.first == "PmSizeInKiB")
219 {
220 const uint64_t* value = std::get_if<uint64_t>(&property.second);
221 if (value == nullptr)
222 {
223 messages::internalError(aResp->res);
224 BMCWEB_LOG_DEBUG << "Invalid property type for PmSizeInKiB";
Chicago Duan601af5e2021-04-15 16:59:25 +0800225 return;
James Feistc50e7c62020-07-27 15:39:36 -0700226 }
227 aResp->res.jsonValue["NonVolatileSizeMiB"] = (*value) >> 10;
228 }
229 else if (property.first == "CacheSizeInKB")
230 {
231 const uint64_t* value = std::get_if<uint64_t>(&property.second);
232 if (value == nullptr)
233 {
234 messages::internalError(aResp->res);
235 BMCWEB_LOG_DEBUG << "Invalid property type for CacheSizeInKB";
Chicago Duan601af5e2021-04-15 16:59:25 +0800236 return;
James Feistc50e7c62020-07-27 15:39:36 -0700237 }
238 aResp->res.jsonValue["CacheSizeMiB"] = (*value >> 10);
239 }
240
241 else if (property.first == "VoltaileRegionMaxSizeInKib")
242 {
243 const uint64_t* value = std::get_if<uint64_t>(&property.second);
244
245 if (value == nullptr)
246 {
247 messages::internalError(aResp->res);
248 BMCWEB_LOG_DEBUG << "Invalid property type for "
249 "VolatileRegionMaxSizeInKib";
Chicago Duan601af5e2021-04-15 16:59:25 +0800250 return;
James Feistc50e7c62020-07-27 15:39:36 -0700251 }
252 aResp->res.jsonValue["VolatileRegionSizeMaxMiB"] = (*value) >> 10;
253 }
254 else if (property.first == "PmRegionMaxSizeInKiB")
255 {
256 const uint64_t* value = std::get_if<uint64_t>(&property.second);
257
258 if (value == nullptr)
259 {
260 messages::internalError(aResp->res);
261 BMCWEB_LOG_DEBUG
262 << "Invalid property type for PmRegionMaxSizeInKiB";
Chicago Duan601af5e2021-04-15 16:59:25 +0800263 return;
James Feistc50e7c62020-07-27 15:39:36 -0700264 }
265 aResp->res.jsonValue["PersistentRegionSizeMaxMiB"] = (*value) >> 10;
266 }
267 else if (property.first == "AllocationIncrementInKiB")
268 {
269 const uint64_t* value = std::get_if<uint64_t>(&property.second);
270
271 if (value == nullptr)
272 {
273 messages::internalError(aResp->res);
274 BMCWEB_LOG_DEBUG << "Invalid property type for "
275 "AllocationIncrementInKiB";
Chicago Duan601af5e2021-04-15 16:59:25 +0800276 return;
James Feistc50e7c62020-07-27 15:39:36 -0700277 }
278 aResp->res.jsonValue["AllocationIncrementMiB"] = (*value) >> 10;
279 }
280 else if (property.first == "AllocationAlignmentInKiB")
281 {
282 const uint64_t* value = std::get_if<uint64_t>(&property.second);
283
284 if (value == nullptr)
285 {
286 messages::internalError(aResp->res);
287 BMCWEB_LOG_DEBUG << "Invalid property type for "
288 "AllocationAlignmentInKiB";
Chicago Duan601af5e2021-04-15 16:59:25 +0800289 return;
James Feistc50e7c62020-07-27 15:39:36 -0700290 }
291 aResp->res.jsonValue["AllocationAlignmentMiB"] = (*value) >> 10;
292 }
293 else if (property.first == "VolatileRegionNumberLimit")
294 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700295 const uint64_t* value = std::get_if<uint64_t>(&property.second);
296 if (value == nullptr)
297 {
298 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800299 return;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700300 }
301 aResp->res.jsonValue["VolatileRegionNumberLimit"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700302 }
303 else if (property.first == "PmRegionNumberLimit")
304 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700305 const uint64_t* value = std::get_if<uint64_t>(&property.second);
306 if (value == nullptr)
307 {
308 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800309 return;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700310 }
311 aResp->res.jsonValue["PersistentRegionNumberLimit"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700312 }
313 else if (property.first == "SpareDeviceCount")
314 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700315 const uint64_t* value = std::get_if<uint64_t>(&property.second);
316 if (value == nullptr)
317 {
318 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800319 return;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700320 }
321 aResp->res.jsonValue["SpareDeviceCount"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700322 }
323 else if (property.first == "IsSpareDeviceInUse")
324 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700325 const bool* value = std::get_if<bool>(&property.second);
326 if (value == nullptr)
327 {
328 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800329 return;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700330 }
331 aResp->res.jsonValue["IsSpareDeviceEnabled"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700332 }
333 else if (property.first == "IsRankSpareEnabled")
334 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700335 const bool* value = std::get_if<bool>(&property.second);
336 if (value == nullptr)
337 {
338 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800339 return;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700340 }
341 aResp->res.jsonValue["IsRankSpareEnabled"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700342 }
343 else if (property.first == "MaxAveragePowerLimitmW")
344 {
345 const auto* value =
346 std::get_if<std::vector<uint32_t>>(&property.second);
347 if (value == nullptr)
348 {
349 messages::internalError(aResp->res);
350 BMCWEB_LOG_DEBUG << "Invalid property type for "
351 "MaxAveragePowerLimitmW";
Chicago Duan601af5e2021-04-15 16:59:25 +0800352 return;
James Feistc50e7c62020-07-27 15:39:36 -0700353 }
354 aResp->res.jsonValue["MaxTDPMilliWatts"] = *value;
355 }
James Feistc50e7c62020-07-27 15:39:36 -0700356 else if (property.first == "ConfigurationLocked")
357 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700358 const bool* value = std::get_if<bool>(&property.second);
359 if (value == nullptr)
360 {
361 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800362 return;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700363 }
364 aResp->res.jsonValue["ConfigurationLocked"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700365 }
366 else if (property.first == "AllowedMemoryModes")
367 {
368 const std::string* value =
369 std::get_if<std::string>(&property.second);
370 if (value == nullptr)
371 {
372 messages::internalError(aResp->res);
373 BMCWEB_LOG_DEBUG << "Invalid property type for FormFactor";
Chicago Duan601af5e2021-04-15 16:59:25 +0800374 return;
James Feistc50e7c62020-07-27 15:39:36 -0700375 }
376 constexpr const std::array<const char*, 3> values{"Volatile",
377 "PMEM", "Block"};
378
379 for (const char* v : values)
380 {
381 if (boost::ends_with(*value, v))
382 {
383 aResp->res.jsonValue["OperatingMemoryModes "] = v;
384 break;
385 }
386 }
387 }
388 else if (property.first == "MemoryMedia")
389 {
390 const std::string* value =
391 std::get_if<std::string>(&property.second);
392 if (value == nullptr)
393 {
394 messages::internalError(aResp->res);
395 BMCWEB_LOG_DEBUG << "Invalid property type for MemoryMedia";
Chicago Duan601af5e2021-04-15 16:59:25 +0800396 return;
James Feistc50e7c62020-07-27 15:39:36 -0700397 }
398 constexpr const std::array<const char*, 3> values{"DRAM", "NAND",
399 "Intel3DXPoint"};
400
401 for (const char* v : values)
402 {
403 if (boost::ends_with(*value, v))
404 {
405 aResp->res.jsonValue["MemoryMedia"] = v;
406 break;
407 }
408 }
409 }
James Feistc50e7c62020-07-27 15:39:36 -0700410 // PersistantMemory.SecurityCapabilites interface
411 else if (property.first == "ConfigurationLockCapable" ||
412 property.first == "DataLockCapable" ||
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700413 property.first == "PassphraseCapable")
414 {
415 const bool* value = std::get_if<bool>(&property.second);
416 if (value == nullptr)
417 {
418 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800419 return;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700420 }
421 aResp->res.jsonValue["SecurityCapabilities"][property.first] =
422 *value;
423 }
424 else if (property.first == "MaxPassphraseCount" ||
James Feistc50e7c62020-07-27 15:39:36 -0700425 property.first == "PassphraseLockLimit")
426 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700427 const uint64_t* value = std::get_if<uint64_t>(&property.second);
428 if (value == nullptr)
429 {
430 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800431 return;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700432 }
James Feistc50e7c62020-07-27 15:39:36 -0700433 aResp->res.jsonValue["SecurityCapabilities"][property.first] =
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700434 *value;
James Feistc50e7c62020-07-27 15:39:36 -0700435 }
436 }
437}
438
zhanghch058d1b46d2021-04-01 11:18:24 +0800439inline void getDimmDataByService(std::shared_ptr<bmcweb::AsyncResp> aResp,
Ed Tanous80789c82020-08-19 09:19:09 -0700440 const std::string& dimmId,
441 const std::string& service,
442 const std::string& objPath)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200443{
James Feist35e257a2020-06-05 13:30:51 -0700444 auto health = std::make_shared<HealthPopulate>(aResp);
445 health->selfPath = objPath;
446 health->populate();
447
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200448 BMCWEB_LOG_DEBUG << "Get available system components.";
449 crow::connections::systemBus->async_method_call(
James Feistc50e7c62020-07-27 15:39:36 -0700450 [dimmId, aResp{std::move(aResp)}](const boost::system::error_code ec,
451 const DimmProperties& properties) {
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200452 if (ec)
453 {
454 BMCWEB_LOG_DEBUG << "DBUS response error";
455 messages::internalError(aResp->res);
456
457 return;
458 }
459 aResp->res.jsonValue["Id"] = dimmId;
460 aResp->res.jsonValue["Name"] = "DIMM Slot";
461
462 const auto memorySizeProperty = properties.find("MemorySizeInKB");
Gunnar Millsaceb7fc2018-12-10 15:17:20 -0600463 if (memorySizeProperty != properties.end())
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200464 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500465 const uint32_t* memorySize =
Ed Tanousabf2add2019-01-22 16:40:12 -0800466 std::get_if<uint32_t>(&memorySizeProperty->second);
Gunnar Millsaceb7fc2018-12-10 15:17:20 -0600467 if (memorySize == nullptr)
468 {
469 // Important property not in desired type
470 messages::internalError(aResp->res);
Gunnar Millsaceb7fc2018-12-10 15:17:20 -0600471 return;
472 }
473 aResp->res.jsonValue["CapacityMiB"] = (*memorySize >> 10);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200474 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200475 aResp->res.jsonValue["Status"]["State"] = "Enabled";
476 aResp->res.jsonValue["Status"]["Health"] = "OK";
477
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500478 for (const auto& property : properties)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200479 {
480 if (property.first == "MemoryDataWidth")
481 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700482 const uint16_t* value =
483 std::get_if<uint16_t>(&property.second);
484 if (value == nullptr)
485 {
486 continue;
487 }
488 aResp->res.jsonValue["DataWidthBits"] = *value;
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200489 }
Manojkiran Eda7e236ca2019-06-25 23:06:32 +0530490 else if (property.first == "PartNumber")
491 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700492 const std::string* value =
493 std::get_if<std::string>(&property.second);
494 if (value == nullptr)
495 {
496 continue;
497 }
498 aResp->res.jsonValue["PartNumber"] = *value;
Manojkiran Eda7e236ca2019-06-25 23:06:32 +0530499 }
500 else if (property.first == "SerialNumber")
501 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700502 const std::string* value =
503 std::get_if<std::string>(&property.second);
504 if (value == nullptr)
505 {
506 continue;
507 }
508 aResp->res.jsonValue["SerialNumber"] = *value;
Manojkiran Eda7e236ca2019-06-25 23:06:32 +0530509 }
510 else if (property.first == "Manufacturer")
511 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700512 const std::string* value =
513 std::get_if<std::string>(&property.second);
514 if (value == nullptr)
515 {
516 continue;
517 }
518 aResp->res.jsonValue["Manufacturer"] = *value;
Manojkiran Eda7e236ca2019-06-25 23:06:32 +0530519 }
James Feistc50e7c62020-07-27 15:39:36 -0700520 else if (property.first == "RevisionCode")
521 {
522 const uint16_t* value =
523 std::get_if<uint16_t>(&property.second);
524
525 if (value == nullptr)
526 {
527 messages::internalError(aResp->res);
528 BMCWEB_LOG_DEBUG
529 << "Invalid property type for RevisionCode";
Chicago Duan601af5e2021-04-15 16:59:25 +0800530 return;
James Feistc50e7c62020-07-27 15:39:36 -0700531 }
532 aResp->res.jsonValue["FirmwareRevision"] =
533 std::to_string(*value);
534 }
Joshi-Mansi9a128eb2021-03-19 03:30:17 +0530535 else if (property.first == "Present")
536 {
537 const bool* value = std::get_if<bool>(&property.second);
538 if (value == nullptr)
539 {
540 messages::internalError(aResp->res);
541 BMCWEB_LOG_DEBUG
542 << "Invalid property type for Dimm Presence";
543 return;
544 }
545 if (*value == false)
546 {
547 aResp->res.jsonValue["Status"]["State"] = "Absent";
548 }
549 }
James Feistc50e7c62020-07-27 15:39:36 -0700550 else if (property.first == "MemoryTotalWidth")
551 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700552 const uint16_t* value =
553 std::get_if<uint16_t>(&property.second);
554 if (value == nullptr)
555 {
556 continue;
557 }
558 aResp->res.jsonValue["BusWidthBits"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700559 }
560 else if (property.first == "ECC")
561 {
562 const std::string* value =
563 std::get_if<std::string>(&property.second);
564 if (value == nullptr)
565 {
566 messages::internalError(aResp->res);
567 BMCWEB_LOG_DEBUG << "Invalid property type for ECC";
Chicago Duan601af5e2021-04-15 16:59:25 +0800568 return;
James Feistc50e7c62020-07-27 15:39:36 -0700569 }
570 constexpr const std::array<const char*, 4> values{
571 "NoECC", "SingleBitECC", "MultiBitECC",
572 "AddressParity"};
573
574 for (const char* v : values)
575 {
576 if (boost::ends_with(*value, v))
577 {
578 aResp->res.jsonValue["ErrorCorrection"] = v;
579 break;
580 }
581 }
582 }
583 else if (property.first == "FormFactor")
584 {
585 const std::string* value =
586 std::get_if<std::string>(&property.second);
587 if (value == nullptr)
588 {
589 messages::internalError(aResp->res);
590 BMCWEB_LOG_DEBUG
591 << "Invalid property type for FormFactor";
Chicago Duan601af5e2021-04-15 16:59:25 +0800592 return;
James Feistc50e7c62020-07-27 15:39:36 -0700593 }
594 constexpr const std::array<const char*, 11> values{
595 "RDIMM", "UDIMM", "SO_DIMM",
596 "LRDIMM", "Mini_RDIMM", "Mini_UDIMM",
597 "SO_RDIMM_72b", "SO_UDIMM_72b", "SO_DIMM_16b",
598 "SO_DIMM_32b", "Die"};
599
600 for (const char* v : values)
601 {
602 if (boost::ends_with(*value, v))
603 {
604 aResp->res.jsonValue["BaseModuleType"] = v;
605 break;
606 }
607 }
608 }
609 else if (property.first == "AllowedSpeedsMT")
610 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700611 const std::vector<uint16_t>* value =
612 std::get_if<std::vector<uint16_t>>(&property.second);
613 if (value == nullptr)
614 {
615 continue;
616 }
617 nlohmann::json& jValue =
618 aResp->res.jsonValue["AllowedSpeedsMHz"];
619 jValue = nlohmann::json::array();
620 for (uint16_t subVal : *value)
621 {
622 jValue.push_back(subVal);
623 }
James Feistc50e7c62020-07-27 15:39:36 -0700624 }
625 else if (property.first == "MemoryAttributes")
626 {
627 const uint8_t* value =
628 std::get_if<uint8_t>(&property.second);
629
630 if (value == nullptr)
631 {
632 messages::internalError(aResp->res);
633 BMCWEB_LOG_DEBUG
634 << "Invalid property type for MemoryAttributes";
Chicago Duan601af5e2021-04-15 16:59:25 +0800635 return;
James Feistc50e7c62020-07-27 15:39:36 -0700636 }
637 aResp->res.jsonValue["RankCount"] =
638 static_cast<uint64_t>(*value);
639 }
640 else if (property.first == "MemoryConfiguredSpeedInMhz")
641 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700642 const uint16_t* value =
643 std::get_if<uint16_t>(&property.second);
644 if (value == nullptr)
645 {
646 continue;
647 }
648 aResp->res.jsonValue["OperatingSpeedMhz"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700649 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200650 else if (property.first == "MemoryType")
651 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500652 const auto* value =
Ed Tanousabf2add2019-01-22 16:40:12 -0800653 std::get_if<std::string>(&property.second);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200654 if (value != nullptr)
655 {
Gunnar Mills313efb12020-10-26 16:05:08 -0500656 std::string memoryDeviceType =
657 translateMemoryTypeToRedfish(*value);
658 // Values like "Unknown" or "Other" will return empty
659 // so just leave off
660 if (!memoryDeviceType.empty())
James Feistc50e7c62020-07-27 15:39:36 -0700661 {
Gunnar Mills313efb12020-10-26 16:05:08 -0500662 aResp->res.jsonValue["MemoryDeviceType"] =
663 memoryDeviceType;
James Feistc50e7c62020-07-27 15:39:36 -0700664 }
James Feistc50e7c62020-07-27 15:39:36 -0700665 if (value->find("DDR") != std::string::npos)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200666 {
667 aResp->res.jsonValue["MemoryType"] = "DRAM";
668 }
James Feistc50e7c62020-07-27 15:39:36 -0700669 else if (boost::ends_with(*value, "Logical"))
670 {
671 aResp->res.jsonValue["MemoryType"] = "IntelOptane";
672 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200673 }
674 }
James Feistc50e7c62020-07-27 15:39:36 -0700675 // memory location interface
676 else if (property.first == "Channel" ||
677 property.first == "MemoryController" ||
678 property.first == "Slot" || property.first == "Socket")
679 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700680 const std::string* value =
681 std::get_if<std::string>(&property.second);
682 if (value == nullptr)
683 {
684 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800685 return;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700686 }
James Feistc50e7c62020-07-27 15:39:36 -0700687 aResp->res.jsonValue["MemoryLocation"][property.first] =
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700688 *value;
James Feistc50e7c62020-07-27 15:39:36 -0700689 }
SunnySrivastava1984ee135e22020-12-15 12:42:19 -0600690 else if (property.first == "SparePartNumber")
691 {
692 const std::string* value =
693 std::get_if<std::string>(&property.second);
694 if (value == nullptr)
695 {
696 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800697 return;
SunnySrivastava1984ee135e22020-12-15 12:42:19 -0600698 }
699 aResp->res.jsonValue["SparePartNumber"] = *value;
700 }
701 else if (property.first == "Model")
702 {
703 const std::string* value =
704 std::get_if<std::string>(&property.second);
705 if (value == nullptr)
706 {
707 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800708 return;
SunnySrivastava1984ee135e22020-12-15 12:42:19 -0600709 }
710 aResp->res.jsonValue["Model"] = *value;
711 }
712 else if (property.first == "LocationCode")
713 {
714 const std::string* value =
715 std::get_if<std::string>(&property.second);
716 if (value == nullptr)
717 {
718 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800719 return;
SunnySrivastava1984ee135e22020-12-15 12:42:19 -0600720 }
721 aResp->res
722 .jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
723 *value;
724 }
James Feistc50e7c62020-07-27 15:39:36 -0700725 else
726 {
727 getPersistentMemoryProperties(aResp, properties);
728 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200729 }
730 },
731 service, objPath, "org.freedesktop.DBus.Properties", "GetAll", "");
732}
733
zhanghch058d1b46d2021-04-01 11:18:24 +0800734inline void getDimmPartitionData(std::shared_ptr<bmcweb::AsyncResp> aResp,
Ed Tanous23a21a12020-07-25 04:45:05 +0000735 const std::string& service,
736 const std::string& path)
James Feist45094ad2020-04-29 14:02:30 -0700737{
738 crow::connections::systemBus->async_method_call(
739 [aResp{std::move(aResp)}](
740 const boost::system::error_code ec,
741 const boost::container::flat_map<
742 std::string, std::variant<std::string, uint64_t, uint32_t,
743 bool>>& properties) {
744 if (ec)
745 {
746 BMCWEB_LOG_DEBUG << "DBUS response error";
747 messages::internalError(aResp->res);
748
749 return;
750 }
751
752 nlohmann::json& partition =
753 aResp->res.jsonValue["Regions"].emplace_back(
754 nlohmann::json::object());
755 for (const auto& [key, val] : properties)
756 {
757 if (key == "MemoryClassification")
758 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700759 const std::string* value = std::get_if<std::string>(&val);
760 if (value == nullptr)
761 {
762 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800763 return;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700764 }
765 partition[key] = *value;
James Feist45094ad2020-04-29 14:02:30 -0700766 }
767 else if (key == "OffsetInKiB")
768 {
769 const uint64_t* value = std::get_if<uint64_t>(&val);
770 if (value == nullptr)
771 {
772 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800773 return;
James Feist45094ad2020-04-29 14:02:30 -0700774 }
775
776 partition["OffsetMiB"] = (*value >> 10);
777 }
778 else if (key == "PartitionId")
779 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700780 const std::string* value = std::get_if<std::string>(&val);
781 if (value == nullptr)
782 {
783 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800784 return;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700785 }
786 partition["RegionId"] = *value;
James Feist45094ad2020-04-29 14:02:30 -0700787 }
788
789 else if (key == "PassphraseState")
790 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700791 const bool* value = std::get_if<bool>(&val);
792 if (value == nullptr)
793 {
794 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800795 return;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700796 }
797 partition["PassphraseEnabled"] = *value;
James Feist45094ad2020-04-29 14:02:30 -0700798 }
799 else if (key == "SizeInKiB")
800 {
801 const uint64_t* value = std::get_if<uint64_t>(&val);
802 if (value == nullptr)
803 {
804 messages::internalError(aResp->res);
805 BMCWEB_LOG_DEBUG
806 << "Invalid property type for SizeInKiB";
Chicago Duan601af5e2021-04-15 16:59:25 +0800807 return;
James Feist45094ad2020-04-29 14:02:30 -0700808 }
809 partition["SizeMiB"] = (*value >> 10);
810 }
811 }
812 },
813
814 service, path, "org.freedesktop.DBus.Properties", "GetAll",
815 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition");
816}
817
zhanghch058d1b46d2021-04-01 11:18:24 +0800818inline void getDimmData(std::shared_ptr<bmcweb::AsyncResp> aResp,
Ed Tanous23a21a12020-07-25 04:45:05 +0000819 const std::string& dimmId)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200820{
821 BMCWEB_LOG_DEBUG << "Get available system dimm resources.";
822 crow::connections::systemBus->async_method_call(
Ed Tanous029573d2019-02-01 10:57:49 -0800823 [dimmId, aResp{std::move(aResp)}](
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200824 const boost::system::error_code ec,
825 const boost::container::flat_map<
826 std::string, boost::container::flat_map<
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500827 std::string, std::vector<std::string>>>&
828 subtree) {
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200829 if (ec)
830 {
831 BMCWEB_LOG_DEBUG << "DBUS response error";
832 messages::internalError(aResp->res);
833
834 return;
835 }
James Feist45094ad2020-04-29 14:02:30 -0700836 bool found = false;
837 for (const auto& [path, object] : subtree)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200838 {
James Feist45094ad2020-04-29 14:02:30 -0700839 if (path.find(dimmId) != std::string::npos)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200840 {
James Feist45094ad2020-04-29 14:02:30 -0700841 for (const auto& [service, interfaces] : object)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200842 {
James Feist45094ad2020-04-29 14:02:30 -0700843 if (!found &&
844 (std::find(
845 interfaces.begin(), interfaces.end(),
846 "xyz.openbmc_project.Inventory.Item.Dimm") !=
847 interfaces.end()))
848 {
849 getDimmDataByService(aResp, dimmId, service, path);
850 found = true;
851 }
852
853 // partitions are separate as there can be multiple per
854 // device, i.e.
855 // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition1
856 // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition2
857 if (std::find(interfaces.begin(), interfaces.end(),
858 "xyz.openbmc_project.Inventory.Item."
859 "PersistentMemory.Partition") !=
860 interfaces.end())
861 {
862 getDimmPartitionData(aResp, service, path);
863 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200864 }
865 }
866 }
867 // Object not found
James Feist45094ad2020-04-29 14:02:30 -0700868 if (!found)
869 {
870 messages::resourceNotFound(aResp->res, "Memory", dimmId);
871 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200872 return;
873 },
874 "xyz.openbmc_project.ObjectMapper",
875 "/xyz/openbmc_project/object_mapper",
876 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous271584a2019-07-09 16:24:22 -0700877 "/xyz/openbmc_project/inventory", 0,
James Feist45094ad2020-04-29 14:02:30 -0700878 std::array<const char*, 2>{
879 "xyz.openbmc_project.Inventory.Item.Dimm",
880 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition"});
Ed Tanous271584a2019-07-09 16:24:22 -0700881}
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200882
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700883inline void requestRoutesMemoryCollection(App& app)
Ed Tanous029573d2019-02-01 10:57:49 -0800884{
Ed Tanous029573d2019-02-01 10:57:49 -0800885 /**
886 * Functions triggers appropriate requests on DBus
887 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700888 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Memory/")
889 .privileges({"Login"})
890 .methods(boost::beast::http::verb::get)(
891 [](const crow::Request&,
892 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
893 asyncResp->res.jsonValue["@odata.type"] =
894 "#MemoryCollection.MemoryCollection";
895 asyncResp->res.jsonValue["Name"] = "Memory Module Collection";
896 asyncResp->res.jsonValue["@odata.id"] =
897 "/redfish/v1/Systems/system/Memory";
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200898
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700899 collection_util::getCollectionMembers(
900 asyncResp, "/redfish/v1/Systems/system/Memory",
901 {"xyz.openbmc_project.Inventory.Item.Dimm"});
902 });
903}
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200904
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700905inline void requestRoutesMemory(App& app)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200906{
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200907 /**
908 * Functions triggers appropriate requests on DBus
909 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700910 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Memory/<str>/")
911 .privileges({"Login"})
912 .methods(boost::beast::http::verb::get)(
913 [](const crow::Request&,
914 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
915 const std::string& dimmId) {
916 asyncResp->res.jsonValue["@odata.type"] =
917 "#Memory.v1_11_0.Memory";
918 asyncResp->res.jsonValue["@odata.id"] =
919 "/redfish/v1/Systems/system/Memory/" + dimmId;
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200920
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700921 getDimmData(asyncResp, dimmId);
922 });
923}
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200924
925} // namespace redfish