blob: 4e9b4b7e86bbcb6ce88f0f0ea11c114fe62f358c [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>
Ed Tanous168e20c2021-12-13 14:39:53 -080021#include <dbus_utility.hpp>
Ed Tanous45ca1b82022-03-25 13:07:27 -070022#include <query.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
Gunnar Mills313efb12020-10-26 16:05:08 -050031inline std::string translateMemoryTypeToRedfish(const std::string& memoryType)
32{
33 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR")
34 {
35 return "DDR";
36 }
37 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR2")
38 {
39 return "DDR2";
40 }
41 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR3")
42 {
43 return "DDR3";
44 }
45 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR4")
46 {
47 return "DDR4";
48 }
49 if (memoryType ==
50 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR4E_SDRAM")
51 {
52 return "DDR4E_SDRAM";
53 }
Mansi Joshi11a2f0f2021-07-19 14:33:27 +053054 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR5")
55 {
56 return "DDR5";
57 }
Gunnar Mills313efb12020-10-26 16:05:08 -050058 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 }
George Liu0fda0f12021-11-16 10:06:17 +080073 if (memoryType ==
74 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR2_SDRAM_FB_DIMM_PROB")
Gunnar Mills313efb12020-10-26 16:05:08 -050075 {
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
Mansi Joshi11a2f0f2021-07-19 14:33:27 +0530136 // LPDDR5_SDRAM
Gunnar Mills313efb12020-10-26 16:05:08 -0500137 return "";
138}
139
Ed Tanous168e20c2021-12-13 14:39:53 -0800140inline void dimmPropToHex(
141 const std::shared_ptr<bmcweb::AsyncResp>& aResp, const char* key,
142 const std::pair<std::string, dbus::utility::DbusVariantType>& 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
Ed Tanous866e4862022-02-17 11:40:25 -0800152 aResp->res.jsonValue[key] = "0x" + intToHexString(*value, 4);
James Feistc50e7c62020-07-27 15:39:36 -0700153}
154
zhanghch058d1b46d2021-04-01 11:18:24 +0800155inline void getPersistentMemoryProperties(
156 const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800157 const std::pair<std::string, dbus::utility::DbusVariantType>& property)
James Feistc50e7c62020-07-27 15:39:36 -0700158{
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800159 if (property.first == "ModuleManufacturerID")
James Feistc50e7c62020-07-27 15:39:36 -0700160 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800161 dimmPropToHex(aResp, "ModuleManufacturerID", property);
162 }
163 else if (property.first == "ModuleProductID")
164 {
165 dimmPropToHex(aResp, "ModuleProductID", property);
166 }
167 else if (property.first == "SubsystemVendorID")
168 {
169 dimmPropToHex(aResp, "MemorySubsystemControllerManufacturerID",
170 property);
171 }
172 else if (property.first == "SubsystemDeviceID")
173 {
174 dimmPropToHex(aResp, "MemorySubsystemControllerProductID", property);
175 }
176 else if (property.first == "VolatileRegionSizeLimitInKiB")
177 {
178 const uint64_t* value = std::get_if<uint64_t>(&property.second);
James Feistc50e7c62020-07-27 15:39:36 -0700179
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800180 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700181 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800182 messages::internalError(aResp->res);
183 BMCWEB_LOG_DEBUG
184 << "Invalid property type for VolatileRegionSizeLimitKiB";
185 return;
186 }
187 aResp->res.jsonValue["VolatileRegionSizeLimitMiB"] = (*value) >> 10;
188 }
189 else if (property.first == "PmRegionSizeLimitInKiB")
190 {
191 const uint64_t* value = std::get_if<uint64_t>(&property.second);
James Feistc50e7c62020-07-27 15:39:36 -0700192
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800193 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700194 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800195 messages::internalError(aResp->res);
196 BMCWEB_LOG_DEBUG << "Invalid property type for PmRegioSizeLimitKiB";
197 return;
198 }
199 aResp->res.jsonValue["PersistentRegionSizeLimitMiB"] = (*value) >> 10;
200 }
201 else if (property.first == "VolatileSizeInKiB")
202 {
203 const uint64_t* value = std::get_if<uint64_t>(&property.second);
James Feistc50e7c62020-07-27 15:39:36 -0700204
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800205 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700206 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800207 messages::internalError(aResp->res);
208 BMCWEB_LOG_DEBUG << "Invalid property type for VolatileSizeInKiB";
209 return;
James Feistc50e7c62020-07-27 15:39:36 -0700210 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800211 aResp->res.jsonValue["VolatileSizeMiB"] = (*value) >> 10;
212 }
213 else if (property.first == "PmSizeInKiB")
214 {
215 const uint64_t* value = std::get_if<uint64_t>(&property.second);
216 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700217 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800218 messages::internalError(aResp->res);
219 BMCWEB_LOG_DEBUG << "Invalid property type for PmSizeInKiB";
220 return;
James Feistc50e7c62020-07-27 15:39:36 -0700221 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800222 aResp->res.jsonValue["NonVolatileSizeMiB"] = (*value) >> 10;
223 }
224 else if (property.first == "CacheSizeInKB")
225 {
226 const uint64_t* value = std::get_if<uint64_t>(&property.second);
227 if (value == nullptr)
228 {
229 messages::internalError(aResp->res);
230 BMCWEB_LOG_DEBUG << "Invalid property type for CacheSizeInKB";
231 return;
232 }
233 aResp->res.jsonValue["CacheSizeMiB"] = (*value >> 10);
234 }
James Feistc50e7c62020-07-27 15:39:36 -0700235
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800236 else if (property.first == "VoltaileRegionMaxSizeInKib")
237 {
238 const uint64_t* value = std::get_if<uint64_t>(&property.second);
James Feistc50e7c62020-07-27 15:39:36 -0700239
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800240 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700241 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800242 messages::internalError(aResp->res);
243 BMCWEB_LOG_DEBUG
244 << "Invalid property type for VolatileRegionMaxSizeInKib";
245 return;
246 }
247 aResp->res.jsonValue["VolatileRegionSizeMaxMiB"] = (*value) >> 10;
248 }
249 else if (property.first == "PmRegionMaxSizeInKiB")
250 {
251 const uint64_t* value = std::get_if<uint64_t>(&property.second);
James Feistc50e7c62020-07-27 15:39:36 -0700252
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800253 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700254 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800255 messages::internalError(aResp->res);
256 BMCWEB_LOG_DEBUG
257 << "Invalid property type for PmRegionMaxSizeInKiB";
258 return;
259 }
260 aResp->res.jsonValue["PersistentRegionSizeMaxMiB"] = (*value) >> 10;
261 }
262 else if (property.first == "AllocationIncrementInKiB")
263 {
264 const uint64_t* value = std::get_if<uint64_t>(&property.second);
James Feistc50e7c62020-07-27 15:39:36 -0700265
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800266 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700267 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800268 messages::internalError(aResp->res);
269 BMCWEB_LOG_DEBUG
270 << "Invalid property type for AllocationIncrementInKiB";
271 return;
272 }
273 aResp->res.jsonValue["AllocationIncrementMiB"] = (*value) >> 10;
274 }
275 else if (property.first == "AllocationAlignmentInKiB")
276 {
277 const uint64_t* value = std::get_if<uint64_t>(&property.second);
James Feistc50e7c62020-07-27 15:39:36 -0700278
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800279 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700280 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800281 messages::internalError(aResp->res);
282 BMCWEB_LOG_DEBUG
283 << "Invalid property type for AllocationAlignmentInKiB";
284 return;
James Feistc50e7c62020-07-27 15:39:36 -0700285 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800286 aResp->res.jsonValue["AllocationAlignmentMiB"] = (*value) >> 10;
287 }
288 else if (property.first == "VolatileRegionNumberLimit")
289 {
290 const uint64_t* value = std::get_if<uint64_t>(&property.second);
291 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700292 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800293 messages::internalError(aResp->res);
294 return;
James Feistc50e7c62020-07-27 15:39:36 -0700295 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800296 aResp->res.jsonValue["VolatileRegionNumberLimit"] = *value;
297 }
298 else if (property.first == "PmRegionNumberLimit")
299 {
300 const uint64_t* value = std::get_if<uint64_t>(&property.second);
301 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700302 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800303 messages::internalError(aResp->res);
304 return;
James Feistc50e7c62020-07-27 15:39:36 -0700305 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800306 aResp->res.jsonValue["PersistentRegionNumberLimit"] = *value;
307 }
308 else if (property.first == "SpareDeviceCount")
309 {
310 const uint64_t* value = std::get_if<uint64_t>(&property.second);
311 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700312 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800313 messages::internalError(aResp->res);
314 return;
James Feistc50e7c62020-07-27 15:39:36 -0700315 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800316 aResp->res.jsonValue["SpareDeviceCount"] = *value;
317 }
318 else if (property.first == "IsSpareDeviceInUse")
319 {
320 const bool* value = std::get_if<bool>(&property.second);
321 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700322 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800323 messages::internalError(aResp->res);
324 return;
James Feistc50e7c62020-07-27 15:39:36 -0700325 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800326 aResp->res.jsonValue["IsSpareDeviceEnabled"] = *value;
327 }
328 else if (property.first == "IsRankSpareEnabled")
329 {
330 const bool* value = std::get_if<bool>(&property.second);
331 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700332 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800333 messages::internalError(aResp->res);
334 return;
James Feistc50e7c62020-07-27 15:39:36 -0700335 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800336 aResp->res.jsonValue["IsRankSpareEnabled"] = *value;
337 }
338 else if (property.first == "MaxAveragePowerLimitmW")
339 {
340 const auto* value =
341 std::get_if<std::vector<uint32_t>>(&property.second);
342 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700343 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800344 messages::internalError(aResp->res);
345 BMCWEB_LOG_DEBUG
346 << "Invalid property type for MaxAveragePowerLimitmW";
347 return;
James Feistc50e7c62020-07-27 15:39:36 -0700348 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800349 aResp->res.jsonValue["MaxTDPMilliWatts"] = *value;
350 }
351 else if (property.first == "ConfigurationLocked")
352 {
353 const bool* value = std::get_if<bool>(&property.second);
354 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700355 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800356 messages::internalError(aResp->res);
357 return;
358 }
359 aResp->res.jsonValue["ConfigurationLocked"] = *value;
360 }
361 else if (property.first == "AllowedMemoryModes")
362 {
363 const std::string* value = std::get_if<std::string>(&property.second);
364 if (value == nullptr)
365 {
366 messages::internalError(aResp->res);
367 BMCWEB_LOG_DEBUG << "Invalid property type for FormFactor";
368 return;
369 }
370 constexpr const std::array<const char*, 3> values{"Volatile", "PMEM",
371 "Block"};
James Feistc50e7c62020-07-27 15:39:36 -0700372
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800373 for (const char* v : values)
374 {
375 if (boost::ends_with(*value, v))
James Feistc50e7c62020-07-27 15:39:36 -0700376 {
Jiaqing Zhao1e04f3b2022-03-18 17:24:32 +0800377 aResp->res.jsonValue["OperatingMemoryModes"].push_back(v);
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800378 break;
James Feistc50e7c62020-07-27 15:39:36 -0700379 }
380 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800381 }
382 else if (property.first == "MemoryMedia")
383 {
384 const std::string* value = std::get_if<std::string>(&property.second);
385 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700386 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800387 messages::internalError(aResp->res);
388 BMCWEB_LOG_DEBUG << "Invalid property type for MemoryMedia";
389 return;
390 }
391 constexpr const std::array<const char*, 3> values{"DRAM", "NAND",
392 "Intel3DXPoint"};
James Feistc50e7c62020-07-27 15:39:36 -0700393
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800394 for (const char* v : values)
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700395 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800396 if (boost::ends_with(*value, v))
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700397 {
Jiaqing Zhao1e04f3b2022-03-18 17:24:32 +0800398 aResp->res.jsonValue["MemoryMedia"].push_back(v);
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800399 break;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700400 }
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700401 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800402 }
403 // PersistantMemory.SecurityCapabilites interface
404 else if (property.first == "ConfigurationLockCapable" ||
405 property.first == "DataLockCapable" ||
406 property.first == "PassphraseCapable")
407 {
408 const bool* value = std::get_if<bool>(&property.second);
409 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700410 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800411 messages::internalError(aResp->res);
412 return;
James Feistc50e7c62020-07-27 15:39:36 -0700413 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800414 aResp->res.jsonValue["SecurityCapabilities"][property.first] = *value;
415 }
416 else if (property.first == "MaxPassphraseCount" ||
417 property.first == "PassphraseLockLimit")
418 {
419 const uint64_t* value = std::get_if<uint64_t>(&property.second);
420 if (value == nullptr)
421 {
422 messages::internalError(aResp->res);
423 return;
424 }
425 aResp->res.jsonValue["SecurityCapabilities"][property.first] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700426 }
427}
428
Nan Zhou9a5acea2022-05-17 21:12:43 +0000429inline void
430 assembleDimmProperties(std::string_view dimmId,
431 const std::shared_ptr<bmcweb::AsyncResp>& aResp,
432 const dbus::utility::DBusPropertiesMap& properties)
433{
434 aResp->res.jsonValue["Id"] = dimmId;
435 aResp->res.jsonValue["Name"] = "DIMM Slot";
436 aResp->res.jsonValue["Status"]["State"] = "Enabled";
437 aResp->res.jsonValue["Status"]["Health"] = "OK";
438
439 for (const auto& property : properties)
440 {
441 if (property.first == "MemoryDataWidth")
442 {
443 const uint16_t* value = std::get_if<uint16_t>(&property.second);
444 if (value == nullptr)
445 {
446 continue;
447 }
448 aResp->res.jsonValue["DataWidthBits"] = *value;
449 }
450 else if (property.first == "MemorySizeInKB")
451 {
452 const size_t* memorySize = std::get_if<size_t>(&property.second);
453 if (memorySize == nullptr)
454 {
455 // Important property not in desired type
456 messages::internalError(aResp->res);
457 return;
458 }
459 aResp->res.jsonValue["CapacityMiB"] = (*memorySize >> 10);
460 }
461 else if (property.first == "PartNumber")
462 {
463 const std::string* value =
464 std::get_if<std::string>(&property.second);
465 if (value == nullptr)
466 {
467 continue;
468 }
469 aResp->res.jsonValue["PartNumber"] = *value;
470 }
471 else if (property.first == "SerialNumber")
472 {
473 const std::string* value =
474 std::get_if<std::string>(&property.second);
475 if (value == nullptr)
476 {
477 continue;
478 }
479 aResp->res.jsonValue["SerialNumber"] = *value;
480 }
481 else if (property.first == "Manufacturer")
482 {
483 const std::string* value =
484 std::get_if<std::string>(&property.second);
485 if (value == nullptr)
486 {
487 continue;
488 }
489 aResp->res.jsonValue["Manufacturer"] = *value;
490 }
491 else if (property.first == "RevisionCode")
492 {
493 const uint16_t* value = std::get_if<uint16_t>(&property.second);
494
495 if (value == nullptr)
496 {
497 messages::internalError(aResp->res);
498 BMCWEB_LOG_DEBUG << "Invalid property type for RevisionCode";
499 return;
500 }
501 aResp->res.jsonValue["FirmwareRevision"] = std::to_string(*value);
502 }
503 else if (property.first == "Present")
504 {
505 const bool* value = std::get_if<bool>(&property.second);
506 if (value == nullptr)
507 {
508 messages::internalError(aResp->res);
509 BMCWEB_LOG_DEBUG << "Invalid property type for Dimm Presence";
510 return;
511 }
512 if (!*value)
513 {
514 aResp->res.jsonValue["Status"]["State"] = "Absent";
515 }
516 }
517 else if (property.first == "MemoryTotalWidth")
518 {
519 const uint16_t* value = std::get_if<uint16_t>(&property.second);
520 if (value == nullptr)
521 {
522 continue;
523 }
524 aResp->res.jsonValue["BusWidthBits"] = *value;
525 }
526 else if (property.first == "ECC")
527 {
528 const std::string* value =
529 std::get_if<std::string>(&property.second);
530 if (value == nullptr)
531 {
532 messages::internalError(aResp->res);
533 BMCWEB_LOG_DEBUG << "Invalid property type for ECC";
534 return;
535 }
536 constexpr const std::array<const char*, 4> values{
537 "NoECC", "SingleBitECC", "MultiBitECC", "AddressParity"};
538
539 for (const char* v : values)
540 {
541 if (boost::ends_with(*value, v))
542 {
543 aResp->res.jsonValue["ErrorCorrection"] = v;
544 break;
545 }
546 }
547 }
548 else if (property.first == "FormFactor")
549 {
550 const std::string* value =
551 std::get_if<std::string>(&property.second);
552 if (value == nullptr)
553 {
554 messages::internalError(aResp->res);
555 BMCWEB_LOG_DEBUG << "Invalid property type for FormFactor";
556 return;
557 }
558 constexpr const std::array<const char*, 11> values{
559 "RDIMM", "UDIMM", "SO_DIMM", "LRDIMM",
560 "Mini_RDIMM", "Mini_UDIMM", "SO_RDIMM_72b", "SO_UDIMM_72b",
561 "SO_DIMM_16b", "SO_DIMM_32b", "Die"};
562
563 for (const char* v : values)
564 {
565 if (boost::ends_with(*value, v))
566 {
567 aResp->res.jsonValue["BaseModuleType"] = v;
568 break;
569 }
570 }
571 }
572 else if (property.first == "AllowedSpeedsMT")
573 {
574 const std::vector<uint16_t>* value =
575 std::get_if<std::vector<uint16_t>>(&property.second);
576 if (value == nullptr)
577 {
578 continue;
579 }
580 nlohmann::json& jValue = aResp->res.jsonValue["AllowedSpeedsMHz"];
581 jValue = nlohmann::json::array();
582 for (uint16_t subVal : *value)
583 {
584 jValue.push_back(subVal);
585 }
586 }
587 else if (property.first == "MemoryAttributes")
588 {
589 const uint8_t* value = std::get_if<uint8_t>(&property.second);
590
591 if (value == nullptr)
592 {
593 messages::internalError(aResp->res);
594 BMCWEB_LOG_DEBUG
595 << "Invalid property type for MemoryAttributes";
596 return;
597 }
598 aResp->res.jsonValue["RankCount"] = static_cast<uint64_t>(*value);
599 }
600 else if (property.first == "MemoryConfiguredSpeedInMhz")
601 {
602 const uint16_t* value = std::get_if<uint16_t>(&property.second);
603 if (value == nullptr)
604 {
605 continue;
606 }
607 aResp->res.jsonValue["OperatingSpeedMhz"] = *value;
608 }
609 else if (property.first == "MemoryType")
610 {
611 const auto* value = std::get_if<std::string>(&property.second);
612 if (value != nullptr)
613 {
614 std::string memoryDeviceType =
615 translateMemoryTypeToRedfish(*value);
616 // Values like "Unknown" or "Other" will return empty
617 // so just leave off
618 if (!memoryDeviceType.empty())
619 {
620 aResp->res.jsonValue["MemoryDeviceType"] = memoryDeviceType;
621 }
622 if (value->find("DDR") != std::string::npos)
623 {
624 aResp->res.jsonValue["MemoryType"] = "DRAM";
625 }
626 else if (boost::ends_with(*value, "Logical"))
627 {
628 aResp->res.jsonValue["MemoryType"] = "IntelOptane";
629 }
630 }
631 }
632 // memory location interface
633 else if (property.first == "Channel" ||
634 property.first == "MemoryController" ||
635 property.first == "Slot" || property.first == "Socket")
636 {
637 const std::string* value =
638 std::get_if<std::string>(&property.second);
639 if (value == nullptr)
640 {
641 messages::internalError(aResp->res);
642 return;
643 }
644 aResp->res.jsonValue["MemoryLocation"][property.first] = *value;
645 }
646 else if (property.first == "SparePartNumber")
647 {
648 const std::string* value =
649 std::get_if<std::string>(&property.second);
650 if (value == nullptr)
651 {
652 messages::internalError(aResp->res);
653 return;
654 }
655 aResp->res.jsonValue["SparePartNumber"] = *value;
656 }
657 else if (property.first == "Model")
658 {
659 const std::string* value =
660 std::get_if<std::string>(&property.second);
661 if (value == nullptr)
662 {
663 messages::internalError(aResp->res);
664 return;
665 }
666 aResp->res.jsonValue["Model"] = *value;
667 }
668 else if (property.first == "LocationCode")
669 {
670 const std::string* value =
671 std::get_if<std::string>(&property.second);
672 if (value == nullptr)
673 {
674 messages::internalError(aResp->res);
675 return;
676 }
677 aResp->res.jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
678 *value;
679 }
680 else
681 {
682 getPersistentMemoryProperties(aResp, property);
683 }
684 }
685}
686
zhanghch058d1b46d2021-04-01 11:18:24 +0800687inline void getDimmDataByService(std::shared_ptr<bmcweb::AsyncResp> aResp,
Ed Tanous80789c82020-08-19 09:19:09 -0700688 const std::string& dimmId,
689 const std::string& service,
690 const std::string& objPath)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200691{
James Feist35e257a2020-06-05 13:30:51 -0700692 auto health = std::make_shared<HealthPopulate>(aResp);
693 health->selfPath = objPath;
694 health->populate();
695
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200696 BMCWEB_LOG_DEBUG << "Get available system components.";
697 crow::connections::systemBus->async_method_call(
Ed Tanousb9d36b42022-02-26 21:42:46 -0800698 [dimmId, aResp{std::move(aResp)}](
699 const boost::system::error_code ec,
700 const dbus::utility::DBusPropertiesMap& properties) {
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200701 if (ec)
702 {
703 BMCWEB_LOG_DEBUG << "DBUS response error";
704 messages::internalError(aResp->res);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200705 return;
706 }
Nan Zhou9a5acea2022-05-17 21:12:43 +0000707 assembleDimmProperties(dimmId, aResp, properties);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200708 },
709 service, objPath, "org.freedesktop.DBus.Properties", "GetAll", "");
710}
711
Nan Zhouef00d7d2022-05-20 21:22:32 +0000712inline void assembleDimmPartitionData(
713 const std::shared_ptr<bmcweb::AsyncResp>& aResp,
714 const dbus::utility::DBusPropertiesMap& properties)
715{
716 nlohmann::json& partition =
717 aResp->res.jsonValue["Regions"].emplace_back(nlohmann::json::object());
718 for (const auto& [key, val] : properties)
719 {
720 if (key == "MemoryClassification")
721 {
722 const std::string* value = std::get_if<std::string>(&val);
723 if (value == nullptr)
724 {
725 messages::internalError(aResp->res);
726 return;
727 }
728 partition[key] = *value;
729 }
730 else if (key == "OffsetInKiB")
731 {
732 const uint64_t* value = std::get_if<uint64_t>(&val);
733 if (value == nullptr)
734 {
735 messages::internalError(aResp->res);
736 return;
737 }
738
739 partition["OffsetMiB"] = (*value >> 10);
740 }
741 else if (key == "PartitionId")
742 {
743 const std::string* value = std::get_if<std::string>(&val);
744 if (value == nullptr)
745 {
746 messages::internalError(aResp->res);
747 return;
748 }
749 partition["RegionId"] = *value;
750 }
751
752 else if (key == "PassphraseState")
753 {
754 const bool* value = std::get_if<bool>(&val);
755 if (value == nullptr)
756 {
757 messages::internalError(aResp->res);
758 return;
759 }
760 partition["PassphraseEnabled"] = *value;
761 }
762 else if (key == "SizeInKiB")
763 {
764 const uint64_t* value = std::get_if<uint64_t>(&val);
765 if (value == nullptr)
766 {
767 messages::internalError(aResp->res);
768 BMCWEB_LOG_DEBUG << "Invalid property type for SizeInKiB";
769 return;
770 }
771 partition["SizeMiB"] = (*value >> 10);
772 }
773 }
774}
775
zhanghch058d1b46d2021-04-01 11:18:24 +0800776inline void getDimmPartitionData(std::shared_ptr<bmcweb::AsyncResp> aResp,
Ed Tanous23a21a12020-07-25 04:45:05 +0000777 const std::string& service,
778 const std::string& path)
James Feist45094ad2020-04-29 14:02:30 -0700779{
780 crow::connections::systemBus->async_method_call(
781 [aResp{std::move(aResp)}](
782 const boost::system::error_code ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800783 const dbus::utility::DBusPropertiesMap& properties) {
James Feist45094ad2020-04-29 14:02:30 -0700784 if (ec)
785 {
786 BMCWEB_LOG_DEBUG << "DBUS response error";
787 messages::internalError(aResp->res);
788
789 return;
790 }
Nan Zhouef00d7d2022-05-20 21:22:32 +0000791 assembleDimmPartitionData(aResp, properties);
James Feist45094ad2020-04-29 14:02:30 -0700792 },
793
794 service, path, "org.freedesktop.DBus.Properties", "GetAll",
795 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition");
796}
797
zhanghch058d1b46d2021-04-01 11:18:24 +0800798inline void getDimmData(std::shared_ptr<bmcweb::AsyncResp> aResp,
Ed Tanous23a21a12020-07-25 04:45:05 +0000799 const std::string& dimmId)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200800{
801 BMCWEB_LOG_DEBUG << "Get available system dimm resources.";
802 crow::connections::systemBus->async_method_call(
Ed Tanous029573d2019-02-01 10:57:49 -0800803 [dimmId, aResp{std::move(aResp)}](
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200804 const boost::system::error_code ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800805 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200806 if (ec)
807 {
808 BMCWEB_LOG_DEBUG << "DBUS response error";
809 messages::internalError(aResp->res);
810
811 return;
812 }
James Feist45094ad2020-04-29 14:02:30 -0700813 bool found = false;
814 for (const auto& [path, object] : subtree)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200815 {
James Feist45094ad2020-04-29 14:02:30 -0700816 if (path.find(dimmId) != std::string::npos)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200817 {
James Feist45094ad2020-04-29 14:02:30 -0700818 for (const auto& [service, interfaces] : object)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200819 {
Ed Tanousb9d36b42022-02-26 21:42:46 -0800820 for (const auto& interface : interfaces)
James Feist45094ad2020-04-29 14:02:30 -0700821 {
Ed Tanousb9d36b42022-02-26 21:42:46 -0800822 if (interface ==
823 "xyz.openbmc_project.Inventory.Item.Dimm")
824 {
825 getDimmDataByService(aResp, dimmId, service,
826 path);
827 found = true;
828 }
James Feist45094ad2020-04-29 14:02:30 -0700829
Ed Tanousb9d36b42022-02-26 21:42:46 -0800830 // partitions are separate as there can be multiple
831 // per
832 // device, i.e.
833 // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition1
834 // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition2
835 if (interface ==
836 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition")
837 {
838 getDimmPartitionData(aResp, service, path);
839 }
James Feist45094ad2020-04-29 14:02:30 -0700840 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200841 }
842 }
843 }
844 // Object not found
James Feist45094ad2020-04-29 14:02:30 -0700845 if (!found)
846 {
847 messages::resourceNotFound(aResp->res, "Memory", dimmId);
848 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200849 return;
850 },
851 "xyz.openbmc_project.ObjectMapper",
852 "/xyz/openbmc_project/object_mapper",
853 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous271584a2019-07-09 16:24:22 -0700854 "/xyz/openbmc_project/inventory", 0,
James Feist45094ad2020-04-29 14:02:30 -0700855 std::array<const char*, 2>{
856 "xyz.openbmc_project.Inventory.Item.Dimm",
857 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition"});
Ed Tanous271584a2019-07-09 16:24:22 -0700858}
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200859
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700860inline void requestRoutesMemoryCollection(App& app)
Ed Tanous029573d2019-02-01 10:57:49 -0800861{
Ed Tanous029573d2019-02-01 10:57:49 -0800862 /**
863 * Functions triggers appropriate requests on DBus
864 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700865 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Memory/")
Ed Tanoused398212021-06-09 17:05:54 -0700866 .privileges(redfish::privileges::getMemoryCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700867 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700868 [&app](const crow::Request& req,
869 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
870 if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
871 {
872 return;
873 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700874 asyncResp->res.jsonValue["@odata.type"] =
875 "#MemoryCollection.MemoryCollection";
876 asyncResp->res.jsonValue["Name"] = "Memory Module Collection";
877 asyncResp->res.jsonValue["@odata.id"] =
878 "/redfish/v1/Systems/system/Memory";
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200879
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700880 collection_util::getCollectionMembers(
881 asyncResp, "/redfish/v1/Systems/system/Memory",
882 {"xyz.openbmc_project.Inventory.Item.Dimm"});
883 });
884}
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200885
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700886inline void requestRoutesMemory(App& app)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200887{
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200888 /**
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/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700892 .privileges(redfish::privileges::getMemory)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700893 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700894 [&app](const crow::Request& req,
895 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
896 const std::string& dimmId) {
897 if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
898 {
899 return;
900 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700901 asyncResp->res.jsonValue["@odata.type"] =
902 "#Memory.v1_11_0.Memory";
903 asyncResp->res.jsonValue["@odata.id"] =
904 "/redfish/v1/Systems/system/Memory/" + dimmId;
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200905
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700906 getDimmData(asyncResp, dimmId);
907 });
908}
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200909
910} // namespace redfish