blob: f20681b61c47a1122e54422885718ba4d688186c [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>
Ed Tanous168e20c2021-12-13 14:39:53 -080022#include <dbus_utility.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>
Ed Tanousf201ffb2021-10-09 14:49:28 -070025#include <utils/hex_utils.hpp>
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +020026#include <utils/json_utils.hpp>
27
28namespace redfish
29{
30
Ed Tanous168e20c2021-12-13 14:39:53 -080031using DimmProperties =
32 boost::container::flat_map<std::string, dbus::utility::DbusVariantType>;
James Feistc50e7c62020-07-27 15:39:36 -070033
Gunnar Mills313efb12020-10-26 16:05:08 -050034inline std::string translateMemoryTypeToRedfish(const std::string& memoryType)
35{
36 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR")
37 {
38 return "DDR";
39 }
40 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR2")
41 {
42 return "DDR2";
43 }
44 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR3")
45 {
46 return "DDR3";
47 }
48 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR4")
49 {
50 return "DDR4";
51 }
52 if (memoryType ==
53 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR4E_SDRAM")
54 {
55 return "DDR4E_SDRAM";
56 }
Mansi Joshi11a2f0f2021-07-19 14:33:27 +053057 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR5")
58 {
59 return "DDR5";
60 }
Gunnar Mills313efb12020-10-26 16:05:08 -050061 if (memoryType ==
62 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.LPDDR4_SDRAM")
63 {
64 return "LPDDR4_SDRAM";
65 }
66 if (memoryType ==
67 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.LPDDR3_SDRAM")
68 {
69 return "LPDDR3_SDRAM";
70 }
71 if (memoryType ==
72 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR2_SDRAM_FB_DIMM")
73 {
74 return "DDR2_SDRAM_FB_DIMM";
75 }
George Liu0fda0f12021-11-16 10:06:17 +080076 if (memoryType ==
77 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR2_SDRAM_FB_DIMM_PROB")
Gunnar Mills313efb12020-10-26 16:05:08 -050078 {
79 return "DDR2_SDRAM_FB_DIMM_PROBE";
80 }
81 if (memoryType ==
82 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR_SGRAM")
83 {
84 return "DDR_SGRAM";
85 }
86 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.ROM")
87 {
88 return "ROM";
89 }
90 if (memoryType ==
91 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.SDRAM")
92 {
93 return "SDRAM";
94 }
95 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.EDO")
96 {
97 return "EDO";
98 }
99 if (memoryType ==
100 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.FastPageMode")
101 {
102 return "FastPageMode";
103 }
104 if (memoryType ==
105 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.PipelinedNibble")
106 {
107 return "PipelinedNibble";
108 }
109 if (memoryType ==
110 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.Logical")
111 {
112 return "Logical";
113 }
114 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.HBM")
115 {
116 return "HBM";
117 }
118 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.HBM2")
119 {
120 return "HBM2";
121 }
122 // This is values like Other or Unknown
123 // Also D-Bus values:
124 // DRAM
125 // EDRAM
126 // VRAM
127 // SRAM
128 // RAM
129 // FLASH
130 // EEPROM
131 // FEPROM
132 // EPROM
133 // CDRAM
134 // ThreeDRAM
135 // RDRAM
136 // FBD2
137 // LPDDR_SDRAM
138 // LPDDR2_SDRAM
Mansi Joshi11a2f0f2021-07-19 14:33:27 +0530139 // LPDDR5_SDRAM
Gunnar Mills313efb12020-10-26 16:05:08 -0500140 return "";
141}
142
Ed Tanous168e20c2021-12-13 14:39:53 -0800143inline void dimmPropToHex(
144 const std::shared_ptr<bmcweb::AsyncResp>& aResp, const char* key,
145 const std::pair<std::string, dbus::utility::DbusVariantType>& property)
James Feistc50e7c62020-07-27 15:39:36 -0700146{
147 const uint16_t* value = std::get_if<uint16_t>(&property.second);
148 if (value == nullptr)
149 {
150 messages::internalError(aResp->res);
151 BMCWEB_LOG_DEBUG << "Invalid property type for " << property.first;
152 return;
153 }
154
Ed Tanousf201ffb2021-10-09 14:49:28 -0700155 aResp->res.jsonValue[key] = "0x" + intToHexString(*value);
James Feistc50e7c62020-07-27 15:39:36 -0700156}
157
zhanghch058d1b46d2021-04-01 11:18:24 +0800158inline void getPersistentMemoryProperties(
159 const std::shared_ptr<bmcweb::AsyncResp>& aResp,
160 const DimmProperties& properties)
James Feistc50e7c62020-07-27 15:39:36 -0700161{
162 for (const auto& property : properties)
163 {
164 if (property.first == "ModuleManufacturerID")
165 {
166 dimmPropToHex(aResp, "ModuleManufacturerID", property);
167 }
168 else if (property.first == "ModuleProductID")
169 {
170 dimmPropToHex(aResp, "ModuleProductID", property);
171 }
172 else if (property.first == "SubsystemVendorID")
173 {
174 dimmPropToHex(aResp, "MemorySubsystemControllerManufacturerID",
175 property);
176 }
177 else if (property.first == "SubsystemDeviceID")
178 {
179 dimmPropToHex(aResp, "MemorySubsystemControllerProductID",
180 property);
181 }
182 else if (property.first == "VolatileRegionSizeLimitInKiB")
183 {
184 const uint64_t* value = std::get_if<uint64_t>(&property.second);
185
186 if (value == nullptr)
187 {
188 messages::internalError(aResp->res);
George Liu0fda0f12021-11-16 10:06:17 +0800189 BMCWEB_LOG_DEBUG
190 << "Invalid property type for VolatileRegionSizeLimitKiB";
Chicago Duan601af5e2021-04-15 16:59:25 +0800191 return;
James Feistc50e7c62020-07-27 15:39:36 -0700192 }
193 aResp->res.jsonValue["VolatileRegionSizeLimitMiB"] = (*value) >> 10;
194 }
195 else if (property.first == "PmRegionSizeLimitInKiB")
196 {
197 const uint64_t* value = std::get_if<uint64_t>(&property.second);
198
199 if (value == nullptr)
200 {
201 messages::internalError(aResp->res);
202 BMCWEB_LOG_DEBUG
203 << "Invalid property type for PmRegioSizeLimitKiB";
Chicago Duan601af5e2021-04-15 16:59:25 +0800204 return;
James Feistc50e7c62020-07-27 15:39:36 -0700205 }
206 aResp->res.jsonValue["PersistentRegionSizeLimitMiB"] =
207 (*value) >> 10;
208 }
209 else if (property.first == "VolatileSizeInKiB")
210 {
211 const uint64_t* value = std::get_if<uint64_t>(&property.second);
212
213 if (value == nullptr)
214 {
215 messages::internalError(aResp->res);
216 BMCWEB_LOG_DEBUG
217 << "Invalid property type for VolatileSizeInKiB";
Chicago Duan601af5e2021-04-15 16:59:25 +0800218 return;
James Feistc50e7c62020-07-27 15:39:36 -0700219 }
220 aResp->res.jsonValue["VolatileSizeMiB"] = (*value) >> 10;
221 }
222 else if (property.first == "PmSizeInKiB")
223 {
224 const uint64_t* value = std::get_if<uint64_t>(&property.second);
225 if (value == nullptr)
226 {
227 messages::internalError(aResp->res);
228 BMCWEB_LOG_DEBUG << "Invalid property type for PmSizeInKiB";
Chicago Duan601af5e2021-04-15 16:59:25 +0800229 return;
James Feistc50e7c62020-07-27 15:39:36 -0700230 }
231 aResp->res.jsonValue["NonVolatileSizeMiB"] = (*value) >> 10;
232 }
233 else if (property.first == "CacheSizeInKB")
234 {
235 const uint64_t* value = std::get_if<uint64_t>(&property.second);
236 if (value == nullptr)
237 {
238 messages::internalError(aResp->res);
239 BMCWEB_LOG_DEBUG << "Invalid property type for CacheSizeInKB";
Chicago Duan601af5e2021-04-15 16:59:25 +0800240 return;
James Feistc50e7c62020-07-27 15:39:36 -0700241 }
242 aResp->res.jsonValue["CacheSizeMiB"] = (*value >> 10);
243 }
244
245 else if (property.first == "VoltaileRegionMaxSizeInKib")
246 {
247 const uint64_t* value = std::get_if<uint64_t>(&property.second);
248
249 if (value == nullptr)
250 {
251 messages::internalError(aResp->res);
George Liu0fda0f12021-11-16 10:06:17 +0800252 BMCWEB_LOG_DEBUG
253 << "Invalid property type for VolatileRegionMaxSizeInKib";
Chicago Duan601af5e2021-04-15 16:59:25 +0800254 return;
James Feistc50e7c62020-07-27 15:39:36 -0700255 }
256 aResp->res.jsonValue["VolatileRegionSizeMaxMiB"] = (*value) >> 10;
257 }
258 else if (property.first == "PmRegionMaxSizeInKiB")
259 {
260 const uint64_t* value = std::get_if<uint64_t>(&property.second);
261
262 if (value == nullptr)
263 {
264 messages::internalError(aResp->res);
265 BMCWEB_LOG_DEBUG
266 << "Invalid property type for PmRegionMaxSizeInKiB";
Chicago Duan601af5e2021-04-15 16:59:25 +0800267 return;
James Feistc50e7c62020-07-27 15:39:36 -0700268 }
269 aResp->res.jsonValue["PersistentRegionSizeMaxMiB"] = (*value) >> 10;
270 }
271 else if (property.first == "AllocationIncrementInKiB")
272 {
273 const uint64_t* value = std::get_if<uint64_t>(&property.second);
274
275 if (value == nullptr)
276 {
277 messages::internalError(aResp->res);
George Liu0fda0f12021-11-16 10:06:17 +0800278 BMCWEB_LOG_DEBUG
279 << "Invalid property type for AllocationIncrementInKiB";
Chicago Duan601af5e2021-04-15 16:59:25 +0800280 return;
James Feistc50e7c62020-07-27 15:39:36 -0700281 }
282 aResp->res.jsonValue["AllocationIncrementMiB"] = (*value) >> 10;
283 }
284 else if (property.first == "AllocationAlignmentInKiB")
285 {
286 const uint64_t* value = std::get_if<uint64_t>(&property.second);
287
288 if (value == nullptr)
289 {
290 messages::internalError(aResp->res);
George Liu0fda0f12021-11-16 10:06:17 +0800291 BMCWEB_LOG_DEBUG
292 << "Invalid property type for AllocationAlignmentInKiB";
Chicago Duan601af5e2021-04-15 16:59:25 +0800293 return;
James Feistc50e7c62020-07-27 15:39:36 -0700294 }
295 aResp->res.jsonValue["AllocationAlignmentMiB"] = (*value) >> 10;
296 }
297 else if (property.first == "VolatileRegionNumberLimit")
298 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700299 const uint64_t* value = std::get_if<uint64_t>(&property.second);
300 if (value == nullptr)
301 {
302 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800303 return;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700304 }
305 aResp->res.jsonValue["VolatileRegionNumberLimit"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700306 }
307 else if (property.first == "PmRegionNumberLimit")
308 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700309 const uint64_t* value = std::get_if<uint64_t>(&property.second);
310 if (value == nullptr)
311 {
312 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800313 return;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700314 }
315 aResp->res.jsonValue["PersistentRegionNumberLimit"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700316 }
317 else if (property.first == "SpareDeviceCount")
318 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700319 const uint64_t* value = std::get_if<uint64_t>(&property.second);
320 if (value == nullptr)
321 {
322 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800323 return;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700324 }
325 aResp->res.jsonValue["SpareDeviceCount"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700326 }
327 else if (property.first == "IsSpareDeviceInUse")
328 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700329 const bool* value = std::get_if<bool>(&property.second);
330 if (value == nullptr)
331 {
332 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800333 return;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700334 }
335 aResp->res.jsonValue["IsSpareDeviceEnabled"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700336 }
337 else if (property.first == "IsRankSpareEnabled")
338 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700339 const bool* value = std::get_if<bool>(&property.second);
340 if (value == nullptr)
341 {
342 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800343 return;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700344 }
345 aResp->res.jsonValue["IsRankSpareEnabled"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700346 }
347 else if (property.first == "MaxAveragePowerLimitmW")
348 {
349 const auto* value =
350 std::get_if<std::vector<uint32_t>>(&property.second);
351 if (value == nullptr)
352 {
353 messages::internalError(aResp->res);
George Liu0fda0f12021-11-16 10:06:17 +0800354 BMCWEB_LOG_DEBUG
355 << "Invalid property type for MaxAveragePowerLimitmW";
Chicago Duan601af5e2021-04-15 16:59:25 +0800356 return;
James Feistc50e7c62020-07-27 15:39:36 -0700357 }
358 aResp->res.jsonValue["MaxTDPMilliWatts"] = *value;
359 }
James Feistc50e7c62020-07-27 15:39:36 -0700360 else if (property.first == "ConfigurationLocked")
361 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700362 const bool* value = std::get_if<bool>(&property.second);
363 if (value == nullptr)
364 {
365 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800366 return;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700367 }
368 aResp->res.jsonValue["ConfigurationLocked"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700369 }
370 else if (property.first == "AllowedMemoryModes")
371 {
372 const std::string* value =
373 std::get_if<std::string>(&property.second);
374 if (value == nullptr)
375 {
376 messages::internalError(aResp->res);
377 BMCWEB_LOG_DEBUG << "Invalid property type for FormFactor";
Chicago Duan601af5e2021-04-15 16:59:25 +0800378 return;
James Feistc50e7c62020-07-27 15:39:36 -0700379 }
380 constexpr const std::array<const char*, 3> values{"Volatile",
381 "PMEM", "Block"};
382
383 for (const char* v : values)
384 {
385 if (boost::ends_with(*value, v))
386 {
387 aResp->res.jsonValue["OperatingMemoryModes "] = v;
388 break;
389 }
390 }
391 }
392 else if (property.first == "MemoryMedia")
393 {
394 const std::string* value =
395 std::get_if<std::string>(&property.second);
396 if (value == nullptr)
397 {
398 messages::internalError(aResp->res);
399 BMCWEB_LOG_DEBUG << "Invalid property type for MemoryMedia";
Chicago Duan601af5e2021-04-15 16:59:25 +0800400 return;
James Feistc50e7c62020-07-27 15:39:36 -0700401 }
402 constexpr const std::array<const char*, 3> values{"DRAM", "NAND",
403 "Intel3DXPoint"};
404
405 for (const char* v : values)
406 {
407 if (boost::ends_with(*value, v))
408 {
409 aResp->res.jsonValue["MemoryMedia"] = v;
410 break;
411 }
412 }
413 }
James Feistc50e7c62020-07-27 15:39:36 -0700414 // PersistantMemory.SecurityCapabilites interface
415 else if (property.first == "ConfigurationLockCapable" ||
416 property.first == "DataLockCapable" ||
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700417 property.first == "PassphraseCapable")
418 {
419 const bool* value = std::get_if<bool>(&property.second);
420 if (value == nullptr)
421 {
422 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800423 return;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700424 }
425 aResp->res.jsonValue["SecurityCapabilities"][property.first] =
426 *value;
427 }
428 else if (property.first == "MaxPassphraseCount" ||
James Feistc50e7c62020-07-27 15:39:36 -0700429 property.first == "PassphraseLockLimit")
430 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700431 const uint64_t* value = std::get_if<uint64_t>(&property.second);
432 if (value == nullptr)
433 {
434 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800435 return;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700436 }
James Feistc50e7c62020-07-27 15:39:36 -0700437 aResp->res.jsonValue["SecurityCapabilities"][property.first] =
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700438 *value;
James Feistc50e7c62020-07-27 15:39:36 -0700439 }
440 }
441}
442
zhanghch058d1b46d2021-04-01 11:18:24 +0800443inline void getDimmDataByService(std::shared_ptr<bmcweb::AsyncResp> aResp,
Ed Tanous80789c82020-08-19 09:19:09 -0700444 const std::string& dimmId,
445 const std::string& service,
446 const std::string& objPath)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200447{
James Feist35e257a2020-06-05 13:30:51 -0700448 auto health = std::make_shared<HealthPopulate>(aResp);
449 health->selfPath = objPath;
450 health->populate();
451
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200452 BMCWEB_LOG_DEBUG << "Get available system components.";
453 crow::connections::systemBus->async_method_call(
James Feistc50e7c62020-07-27 15:39:36 -0700454 [dimmId, aResp{std::move(aResp)}](const boost::system::error_code ec,
455 const DimmProperties& properties) {
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200456 if (ec)
457 {
458 BMCWEB_LOG_DEBUG << "DBUS response error";
459 messages::internalError(aResp->res);
460
461 return;
462 }
463 aResp->res.jsonValue["Id"] = dimmId;
464 aResp->res.jsonValue["Name"] = "DIMM Slot";
465
466 const auto memorySizeProperty = properties.find("MemorySizeInKB");
Gunnar Millsaceb7fc2018-12-10 15:17:20 -0600467 if (memorySizeProperty != properties.end())
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200468 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500469 const uint32_t* memorySize =
Ed Tanousabf2add2019-01-22 16:40:12 -0800470 std::get_if<uint32_t>(&memorySizeProperty->second);
Gunnar Millsaceb7fc2018-12-10 15:17:20 -0600471 if (memorySize == nullptr)
472 {
473 // Important property not in desired type
474 messages::internalError(aResp->res);
Gunnar Millsaceb7fc2018-12-10 15:17:20 -0600475 return;
476 }
477 aResp->res.jsonValue["CapacityMiB"] = (*memorySize >> 10);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200478 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200479 aResp->res.jsonValue["Status"]["State"] = "Enabled";
480 aResp->res.jsonValue["Status"]["Health"] = "OK";
481
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500482 for (const auto& property : properties)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200483 {
484 if (property.first == "MemoryDataWidth")
485 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700486 const uint16_t* value =
487 std::get_if<uint16_t>(&property.second);
488 if (value == nullptr)
489 {
490 continue;
491 }
492 aResp->res.jsonValue["DataWidthBits"] = *value;
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200493 }
Manojkiran Eda7e236ca2019-06-25 23:06:32 +0530494 else if (property.first == "PartNumber")
495 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700496 const std::string* value =
497 std::get_if<std::string>(&property.second);
498 if (value == nullptr)
499 {
500 continue;
501 }
502 aResp->res.jsonValue["PartNumber"] = *value;
Manojkiran Eda7e236ca2019-06-25 23:06:32 +0530503 }
504 else if (property.first == "SerialNumber")
505 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700506 const std::string* value =
507 std::get_if<std::string>(&property.second);
508 if (value == nullptr)
509 {
510 continue;
511 }
512 aResp->res.jsonValue["SerialNumber"] = *value;
Manojkiran Eda7e236ca2019-06-25 23:06:32 +0530513 }
514 else if (property.first == "Manufacturer")
515 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700516 const std::string* value =
517 std::get_if<std::string>(&property.second);
518 if (value == nullptr)
519 {
520 continue;
521 }
522 aResp->res.jsonValue["Manufacturer"] = *value;
Manojkiran Eda7e236ca2019-06-25 23:06:32 +0530523 }
James Feistc50e7c62020-07-27 15:39:36 -0700524 else if (property.first == "RevisionCode")
525 {
526 const uint16_t* value =
527 std::get_if<uint16_t>(&property.second);
528
529 if (value == nullptr)
530 {
531 messages::internalError(aResp->res);
532 BMCWEB_LOG_DEBUG
533 << "Invalid property type for RevisionCode";
Chicago Duan601af5e2021-04-15 16:59:25 +0800534 return;
James Feistc50e7c62020-07-27 15:39:36 -0700535 }
536 aResp->res.jsonValue["FirmwareRevision"] =
537 std::to_string(*value);
538 }
Joshi-Mansi9a128eb2021-03-19 03:30:17 +0530539 else if (property.first == "Present")
540 {
541 const bool* value = std::get_if<bool>(&property.second);
542 if (value == nullptr)
543 {
544 messages::internalError(aResp->res);
545 BMCWEB_LOG_DEBUG
546 << "Invalid property type for Dimm Presence";
547 return;
548 }
Ed Tanouse05aec52022-01-25 10:28:56 -0800549 if (!*value)
Joshi-Mansi9a128eb2021-03-19 03:30:17 +0530550 {
551 aResp->res.jsonValue["Status"]["State"] = "Absent";
552 }
553 }
James Feistc50e7c62020-07-27 15:39:36 -0700554 else if (property.first == "MemoryTotalWidth")
555 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700556 const uint16_t* value =
557 std::get_if<uint16_t>(&property.second);
558 if (value == nullptr)
559 {
560 continue;
561 }
562 aResp->res.jsonValue["BusWidthBits"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700563 }
564 else if (property.first == "ECC")
565 {
566 const std::string* value =
567 std::get_if<std::string>(&property.second);
568 if (value == nullptr)
569 {
570 messages::internalError(aResp->res);
571 BMCWEB_LOG_DEBUG << "Invalid property type for ECC";
Chicago Duan601af5e2021-04-15 16:59:25 +0800572 return;
James Feistc50e7c62020-07-27 15:39:36 -0700573 }
574 constexpr const std::array<const char*, 4> values{
575 "NoECC", "SingleBitECC", "MultiBitECC",
576 "AddressParity"};
577
578 for (const char* v : values)
579 {
580 if (boost::ends_with(*value, v))
581 {
582 aResp->res.jsonValue["ErrorCorrection"] = v;
583 break;
584 }
585 }
586 }
587 else if (property.first == "FormFactor")
588 {
589 const std::string* value =
590 std::get_if<std::string>(&property.second);
591 if (value == nullptr)
592 {
593 messages::internalError(aResp->res);
594 BMCWEB_LOG_DEBUG
595 << "Invalid property type for FormFactor";
Chicago Duan601af5e2021-04-15 16:59:25 +0800596 return;
James Feistc50e7c62020-07-27 15:39:36 -0700597 }
598 constexpr const std::array<const char*, 11> values{
599 "RDIMM", "UDIMM", "SO_DIMM",
600 "LRDIMM", "Mini_RDIMM", "Mini_UDIMM",
601 "SO_RDIMM_72b", "SO_UDIMM_72b", "SO_DIMM_16b",
602 "SO_DIMM_32b", "Die"};
603
604 for (const char* v : values)
605 {
606 if (boost::ends_with(*value, v))
607 {
608 aResp->res.jsonValue["BaseModuleType"] = v;
609 break;
610 }
611 }
612 }
613 else if (property.first == "AllowedSpeedsMT")
614 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700615 const std::vector<uint16_t>* value =
616 std::get_if<std::vector<uint16_t>>(&property.second);
617 if (value == nullptr)
618 {
619 continue;
620 }
621 nlohmann::json& jValue =
622 aResp->res.jsonValue["AllowedSpeedsMHz"];
623 jValue = nlohmann::json::array();
624 for (uint16_t subVal : *value)
625 {
626 jValue.push_back(subVal);
627 }
James Feistc50e7c62020-07-27 15:39:36 -0700628 }
629 else if (property.first == "MemoryAttributes")
630 {
631 const uint8_t* value =
632 std::get_if<uint8_t>(&property.second);
633
634 if (value == nullptr)
635 {
636 messages::internalError(aResp->res);
637 BMCWEB_LOG_DEBUG
638 << "Invalid property type for MemoryAttributes";
Chicago Duan601af5e2021-04-15 16:59:25 +0800639 return;
James Feistc50e7c62020-07-27 15:39:36 -0700640 }
641 aResp->res.jsonValue["RankCount"] =
642 static_cast<uint64_t>(*value);
643 }
644 else if (property.first == "MemoryConfiguredSpeedInMhz")
645 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700646 const uint16_t* value =
647 std::get_if<uint16_t>(&property.second);
648 if (value == nullptr)
649 {
650 continue;
651 }
652 aResp->res.jsonValue["OperatingSpeedMhz"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700653 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200654 else if (property.first == "MemoryType")
655 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500656 const auto* value =
Ed Tanousabf2add2019-01-22 16:40:12 -0800657 std::get_if<std::string>(&property.second);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200658 if (value != nullptr)
659 {
Gunnar Mills313efb12020-10-26 16:05:08 -0500660 std::string memoryDeviceType =
661 translateMemoryTypeToRedfish(*value);
662 // Values like "Unknown" or "Other" will return empty
663 // so just leave off
664 if (!memoryDeviceType.empty())
James Feistc50e7c62020-07-27 15:39:36 -0700665 {
Gunnar Mills313efb12020-10-26 16:05:08 -0500666 aResp->res.jsonValue["MemoryDeviceType"] =
667 memoryDeviceType;
James Feistc50e7c62020-07-27 15:39:36 -0700668 }
James Feistc50e7c62020-07-27 15:39:36 -0700669 if (value->find("DDR") != std::string::npos)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200670 {
671 aResp->res.jsonValue["MemoryType"] = "DRAM";
672 }
James Feistc50e7c62020-07-27 15:39:36 -0700673 else if (boost::ends_with(*value, "Logical"))
674 {
675 aResp->res.jsonValue["MemoryType"] = "IntelOptane";
676 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200677 }
678 }
James Feistc50e7c62020-07-27 15:39:36 -0700679 // memory location interface
680 else if (property.first == "Channel" ||
681 property.first == "MemoryController" ||
682 property.first == "Slot" || property.first == "Socket")
683 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700684 const std::string* value =
685 std::get_if<std::string>(&property.second);
686 if (value == nullptr)
687 {
688 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800689 return;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700690 }
James Feistc50e7c62020-07-27 15:39:36 -0700691 aResp->res.jsonValue["MemoryLocation"][property.first] =
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700692 *value;
James Feistc50e7c62020-07-27 15:39:36 -0700693 }
SunnySrivastava1984ee135e22020-12-15 12:42:19 -0600694 else if (property.first == "SparePartNumber")
695 {
696 const std::string* value =
697 std::get_if<std::string>(&property.second);
698 if (value == nullptr)
699 {
700 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800701 return;
SunnySrivastava1984ee135e22020-12-15 12:42:19 -0600702 }
703 aResp->res.jsonValue["SparePartNumber"] = *value;
704 }
705 else if (property.first == "Model")
706 {
707 const std::string* value =
708 std::get_if<std::string>(&property.second);
709 if (value == nullptr)
710 {
711 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800712 return;
SunnySrivastava1984ee135e22020-12-15 12:42:19 -0600713 }
714 aResp->res.jsonValue["Model"] = *value;
715 }
716 else if (property.first == "LocationCode")
717 {
718 const std::string* value =
719 std::get_if<std::string>(&property.second);
720 if (value == nullptr)
721 {
722 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800723 return;
SunnySrivastava1984ee135e22020-12-15 12:42:19 -0600724 }
725 aResp->res
726 .jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
727 *value;
728 }
James Feistc50e7c62020-07-27 15:39:36 -0700729 else
730 {
731 getPersistentMemoryProperties(aResp, properties);
732 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200733 }
734 },
735 service, objPath, "org.freedesktop.DBus.Properties", "GetAll", "");
736}
737
zhanghch058d1b46d2021-04-01 11:18:24 +0800738inline void getDimmPartitionData(std::shared_ptr<bmcweb::AsyncResp> aResp,
Ed Tanous23a21a12020-07-25 04:45:05 +0000739 const std::string& service,
740 const std::string& path)
James Feist45094ad2020-04-29 14:02:30 -0700741{
742 crow::connections::systemBus->async_method_call(
743 [aResp{std::move(aResp)}](
744 const boost::system::error_code ec,
745 const boost::container::flat_map<
Ed Tanous168e20c2021-12-13 14:39:53 -0800746 std::string, dbus::utility::DbusVariantType>& properties) {
James Feist45094ad2020-04-29 14:02:30 -0700747 if (ec)
748 {
749 BMCWEB_LOG_DEBUG << "DBUS response error";
750 messages::internalError(aResp->res);
751
752 return;
753 }
754
755 nlohmann::json& partition =
756 aResp->res.jsonValue["Regions"].emplace_back(
757 nlohmann::json::object());
758 for (const auto& [key, val] : properties)
759 {
760 if (key == "MemoryClassification")
761 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700762 const std::string* value = std::get_if<std::string>(&val);
763 if (value == nullptr)
764 {
765 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800766 return;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700767 }
768 partition[key] = *value;
James Feist45094ad2020-04-29 14:02:30 -0700769 }
770 else if (key == "OffsetInKiB")
771 {
772 const uint64_t* value = std::get_if<uint64_t>(&val);
773 if (value == nullptr)
774 {
775 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800776 return;
James Feist45094ad2020-04-29 14:02:30 -0700777 }
778
779 partition["OffsetMiB"] = (*value >> 10);
780 }
781 else if (key == "PartitionId")
782 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700783 const std::string* value = std::get_if<std::string>(&val);
784 if (value == nullptr)
785 {
786 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800787 return;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700788 }
789 partition["RegionId"] = *value;
James Feist45094ad2020-04-29 14:02:30 -0700790 }
791
792 else if (key == "PassphraseState")
793 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700794 const bool* value = std::get_if<bool>(&val);
795 if (value == nullptr)
796 {
797 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800798 return;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700799 }
800 partition["PassphraseEnabled"] = *value;
James Feist45094ad2020-04-29 14:02:30 -0700801 }
802 else if (key == "SizeInKiB")
803 {
804 const uint64_t* value = std::get_if<uint64_t>(&val);
805 if (value == nullptr)
806 {
807 messages::internalError(aResp->res);
808 BMCWEB_LOG_DEBUG
809 << "Invalid property type for SizeInKiB";
Chicago Duan601af5e2021-04-15 16:59:25 +0800810 return;
James Feist45094ad2020-04-29 14:02:30 -0700811 }
812 partition["SizeMiB"] = (*value >> 10);
813 }
814 }
815 },
816
817 service, path, "org.freedesktop.DBus.Properties", "GetAll",
818 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition");
819}
820
zhanghch058d1b46d2021-04-01 11:18:24 +0800821inline void getDimmData(std::shared_ptr<bmcweb::AsyncResp> aResp,
Ed Tanous23a21a12020-07-25 04:45:05 +0000822 const std::string& dimmId)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200823{
824 BMCWEB_LOG_DEBUG << "Get available system dimm resources.";
825 crow::connections::systemBus->async_method_call(
Ed Tanous029573d2019-02-01 10:57:49 -0800826 [dimmId, aResp{std::move(aResp)}](
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200827 const boost::system::error_code ec,
828 const boost::container::flat_map<
829 std::string, boost::container::flat_map<
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500830 std::string, std::vector<std::string>>>&
831 subtree) {
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200832 if (ec)
833 {
834 BMCWEB_LOG_DEBUG << "DBUS response error";
835 messages::internalError(aResp->res);
836
837 return;
838 }
James Feist45094ad2020-04-29 14:02:30 -0700839 bool found = false;
840 for (const auto& [path, object] : subtree)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200841 {
James Feist45094ad2020-04-29 14:02:30 -0700842 if (path.find(dimmId) != std::string::npos)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200843 {
James Feist45094ad2020-04-29 14:02:30 -0700844 for (const auto& [service, interfaces] : object)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200845 {
James Feist45094ad2020-04-29 14:02:30 -0700846 if (!found &&
847 (std::find(
848 interfaces.begin(), interfaces.end(),
849 "xyz.openbmc_project.Inventory.Item.Dimm") !=
850 interfaces.end()))
851 {
852 getDimmDataByService(aResp, dimmId, service, path);
853 found = true;
854 }
855
856 // partitions are separate as there can be multiple per
857 // device, i.e.
858 // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition1
859 // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition2
George Liu0fda0f12021-11-16 10:06:17 +0800860 if (std::find(
861 interfaces.begin(), interfaces.end(),
862 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition") !=
James Feist45094ad2020-04-29 14:02:30 -0700863 interfaces.end())
864 {
865 getDimmPartitionData(aResp, service, path);
866 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200867 }
868 }
869 }
870 // Object not found
James Feist45094ad2020-04-29 14:02:30 -0700871 if (!found)
872 {
873 messages::resourceNotFound(aResp->res, "Memory", dimmId);
874 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200875 return;
876 },
877 "xyz.openbmc_project.ObjectMapper",
878 "/xyz/openbmc_project/object_mapper",
879 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous271584a2019-07-09 16:24:22 -0700880 "/xyz/openbmc_project/inventory", 0,
James Feist45094ad2020-04-29 14:02:30 -0700881 std::array<const char*, 2>{
882 "xyz.openbmc_project.Inventory.Item.Dimm",
883 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition"});
Ed Tanous271584a2019-07-09 16:24:22 -0700884}
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200885
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700886inline void requestRoutesMemoryCollection(App& app)
Ed Tanous029573d2019-02-01 10:57:49 -0800887{
Ed Tanous029573d2019-02-01 10:57:49 -0800888 /**
889 * Functions triggers appropriate requests on DBus
890 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700891 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Memory/")
Ed Tanoused398212021-06-09 17:05:54 -0700892 .privileges(redfish::privileges::getMemoryCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700893 .methods(boost::beast::http::verb::get)(
894 [](const crow::Request&,
895 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
896 asyncResp->res.jsonValue["@odata.type"] =
897 "#MemoryCollection.MemoryCollection";
898 asyncResp->res.jsonValue["Name"] = "Memory Module Collection";
899 asyncResp->res.jsonValue["@odata.id"] =
900 "/redfish/v1/Systems/system/Memory";
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200901
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700902 collection_util::getCollectionMembers(
903 asyncResp, "/redfish/v1/Systems/system/Memory",
904 {"xyz.openbmc_project.Inventory.Item.Dimm"});
905 });
906}
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200907
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700908inline void requestRoutesMemory(App& app)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200909{
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200910 /**
911 * Functions triggers appropriate requests on DBus
912 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700913 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Memory/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700914 .privileges(redfish::privileges::getMemory)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700915 .methods(boost::beast::http::verb::get)(
916 [](const crow::Request&,
917 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
918 const std::string& dimmId) {
919 asyncResp->res.jsonValue["@odata.type"] =
920 "#Memory.v1_11_0.Memory";
921 asyncResp->res.jsonValue["@odata.id"] =
922 "/redfish/v1/Systems/system/Memory/" + dimmId;
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200923
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700924 getDimmData(asyncResp, dimmId);
925 });
926}
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200927
928} // namespace redfish