blob: 20bbfb283c567bfc9b1e770d27c6cdb51efa790a [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
zhanghch058d1b46d2021-04-01 11:18:24 +0800429inline void getDimmDataByService(std::shared_ptr<bmcweb::AsyncResp> aResp,
Ed Tanous80789c82020-08-19 09:19:09 -0700430 const std::string& dimmId,
431 const std::string& service,
432 const std::string& objPath)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200433{
James Feist35e257a2020-06-05 13:30:51 -0700434 auto health = std::make_shared<HealthPopulate>(aResp);
435 health->selfPath = objPath;
436 health->populate();
437
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200438 BMCWEB_LOG_DEBUG << "Get available system components.";
439 crow::connections::systemBus->async_method_call(
Ed Tanousb9d36b42022-02-26 21:42:46 -0800440 [dimmId, aResp{std::move(aResp)}](
441 const boost::system::error_code ec,
442 const dbus::utility::DBusPropertiesMap& properties) {
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200443 if (ec)
444 {
445 BMCWEB_LOG_DEBUG << "DBUS response error";
446 messages::internalError(aResp->res);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200447 return;
448 }
449 aResp->res.jsonValue["Id"] = dimmId;
450 aResp->res.jsonValue["Name"] = "DIMM Slot";
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200451 aResp->res.jsonValue["Status"]["State"] = "Enabled";
452 aResp->res.jsonValue["Status"]["Health"] = "OK";
453
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500454 for (const auto& property : properties)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200455 {
456 if (property.first == "MemoryDataWidth")
457 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700458 const uint16_t* value =
459 std::get_if<uint16_t>(&property.second);
460 if (value == nullptr)
461 {
462 continue;
463 }
464 aResp->res.jsonValue["DataWidthBits"] = *value;
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200465 }
Ed Tanousb9d36b42022-02-26 21:42:46 -0800466 else if (property.first == "MemorySizeInKB")
467 {
468 const uint32_t* memorySize =
469 std::get_if<uint32_t>(&property.second);
470 if (memorySize == nullptr)
471 {
472 // Important property not in desired type
473 messages::internalError(aResp->res);
474 return;
475 }
476 aResp->res.jsonValue["CapacityMiB"] = (*memorySize >> 10);
477 }
Manojkiran Eda7e236ca2019-06-25 23:06:32 +0530478 else if (property.first == "PartNumber")
479 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700480 const std::string* value =
481 std::get_if<std::string>(&property.second);
482 if (value == nullptr)
483 {
484 continue;
485 }
486 aResp->res.jsonValue["PartNumber"] = *value;
Manojkiran Eda7e236ca2019-06-25 23:06:32 +0530487 }
488 else if (property.first == "SerialNumber")
489 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700490 const std::string* value =
491 std::get_if<std::string>(&property.second);
492 if (value == nullptr)
493 {
494 continue;
495 }
496 aResp->res.jsonValue["SerialNumber"] = *value;
Manojkiran Eda7e236ca2019-06-25 23:06:32 +0530497 }
498 else if (property.first == "Manufacturer")
499 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700500 const std::string* value =
501 std::get_if<std::string>(&property.second);
502 if (value == nullptr)
503 {
504 continue;
505 }
506 aResp->res.jsonValue["Manufacturer"] = *value;
Manojkiran Eda7e236ca2019-06-25 23:06:32 +0530507 }
James Feistc50e7c62020-07-27 15:39:36 -0700508 else if (property.first == "RevisionCode")
509 {
510 const uint16_t* value =
511 std::get_if<uint16_t>(&property.second);
512
513 if (value == nullptr)
514 {
515 messages::internalError(aResp->res);
516 BMCWEB_LOG_DEBUG
517 << "Invalid property type for RevisionCode";
Chicago Duan601af5e2021-04-15 16:59:25 +0800518 return;
James Feistc50e7c62020-07-27 15:39:36 -0700519 }
520 aResp->res.jsonValue["FirmwareRevision"] =
521 std::to_string(*value);
522 }
Joshi-Mansi9a128eb2021-03-19 03:30:17 +0530523 else if (property.first == "Present")
524 {
525 const bool* value = std::get_if<bool>(&property.second);
526 if (value == nullptr)
527 {
528 messages::internalError(aResp->res);
529 BMCWEB_LOG_DEBUG
530 << "Invalid property type for Dimm Presence";
531 return;
532 }
Ed Tanouse05aec52022-01-25 10:28:56 -0800533 if (!*value)
Joshi-Mansi9a128eb2021-03-19 03:30:17 +0530534 {
535 aResp->res.jsonValue["Status"]["State"] = "Absent";
536 }
537 }
James Feistc50e7c62020-07-27 15:39:36 -0700538 else if (property.first == "MemoryTotalWidth")
539 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700540 const uint16_t* value =
541 std::get_if<uint16_t>(&property.second);
542 if (value == nullptr)
543 {
544 continue;
545 }
546 aResp->res.jsonValue["BusWidthBits"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700547 }
548 else if (property.first == "ECC")
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 ECC";
Chicago Duan601af5e2021-04-15 16:59:25 +0800556 return;
James Feistc50e7c62020-07-27 15:39:36 -0700557 }
558 constexpr const std::array<const char*, 4> values{
559 "NoECC", "SingleBitECC", "MultiBitECC",
560 "AddressParity"};
561
562 for (const char* v : values)
563 {
564 if (boost::ends_with(*value, v))
565 {
566 aResp->res.jsonValue["ErrorCorrection"] = v;
567 break;
568 }
569 }
570 }
571 else if (property.first == "FormFactor")
572 {
573 const std::string* value =
574 std::get_if<std::string>(&property.second);
575 if (value == nullptr)
576 {
577 messages::internalError(aResp->res);
578 BMCWEB_LOG_DEBUG
579 << "Invalid property type for FormFactor";
Chicago Duan601af5e2021-04-15 16:59:25 +0800580 return;
James Feistc50e7c62020-07-27 15:39:36 -0700581 }
582 constexpr const std::array<const char*, 11> values{
583 "RDIMM", "UDIMM", "SO_DIMM",
584 "LRDIMM", "Mini_RDIMM", "Mini_UDIMM",
585 "SO_RDIMM_72b", "SO_UDIMM_72b", "SO_DIMM_16b",
586 "SO_DIMM_32b", "Die"};
587
588 for (const char* v : values)
589 {
590 if (boost::ends_with(*value, v))
591 {
592 aResp->res.jsonValue["BaseModuleType"] = v;
593 break;
594 }
595 }
596 }
597 else if (property.first == "AllowedSpeedsMT")
598 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700599 const std::vector<uint16_t>* value =
600 std::get_if<std::vector<uint16_t>>(&property.second);
601 if (value == nullptr)
602 {
603 continue;
604 }
605 nlohmann::json& jValue =
606 aResp->res.jsonValue["AllowedSpeedsMHz"];
607 jValue = nlohmann::json::array();
608 for (uint16_t subVal : *value)
609 {
610 jValue.push_back(subVal);
611 }
James Feistc50e7c62020-07-27 15:39:36 -0700612 }
613 else if (property.first == "MemoryAttributes")
614 {
615 const uint8_t* value =
616 std::get_if<uint8_t>(&property.second);
617
618 if (value == nullptr)
619 {
620 messages::internalError(aResp->res);
621 BMCWEB_LOG_DEBUG
622 << "Invalid property type for MemoryAttributes";
Chicago Duan601af5e2021-04-15 16:59:25 +0800623 return;
James Feistc50e7c62020-07-27 15:39:36 -0700624 }
625 aResp->res.jsonValue["RankCount"] =
626 static_cast<uint64_t>(*value);
627 }
628 else if (property.first == "MemoryConfiguredSpeedInMhz")
629 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700630 const uint16_t* value =
631 std::get_if<uint16_t>(&property.second);
632 if (value == nullptr)
633 {
634 continue;
635 }
636 aResp->res.jsonValue["OperatingSpeedMhz"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700637 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200638 else if (property.first == "MemoryType")
639 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500640 const auto* value =
Ed Tanousabf2add2019-01-22 16:40:12 -0800641 std::get_if<std::string>(&property.second);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200642 if (value != nullptr)
643 {
Gunnar Mills313efb12020-10-26 16:05:08 -0500644 std::string memoryDeviceType =
645 translateMemoryTypeToRedfish(*value);
646 // Values like "Unknown" or "Other" will return empty
647 // so just leave off
648 if (!memoryDeviceType.empty())
James Feistc50e7c62020-07-27 15:39:36 -0700649 {
Gunnar Mills313efb12020-10-26 16:05:08 -0500650 aResp->res.jsonValue["MemoryDeviceType"] =
651 memoryDeviceType;
James Feistc50e7c62020-07-27 15:39:36 -0700652 }
James Feistc50e7c62020-07-27 15:39:36 -0700653 if (value->find("DDR") != std::string::npos)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200654 {
655 aResp->res.jsonValue["MemoryType"] = "DRAM";
656 }
James Feistc50e7c62020-07-27 15:39:36 -0700657 else if (boost::ends_with(*value, "Logical"))
658 {
659 aResp->res.jsonValue["MemoryType"] = "IntelOptane";
660 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200661 }
662 }
James Feistc50e7c62020-07-27 15:39:36 -0700663 // memory location interface
664 else if (property.first == "Channel" ||
665 property.first == "MemoryController" ||
666 property.first == "Slot" || property.first == "Socket")
667 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700668 const std::string* value =
669 std::get_if<std::string>(&property.second);
670 if (value == nullptr)
671 {
672 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800673 return;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700674 }
James Feistc50e7c62020-07-27 15:39:36 -0700675 aResp->res.jsonValue["MemoryLocation"][property.first] =
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700676 *value;
James Feistc50e7c62020-07-27 15:39:36 -0700677 }
SunnySrivastava1984ee135e22020-12-15 12:42:19 -0600678 else if (property.first == "SparePartNumber")
679 {
680 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;
SunnySrivastava1984ee135e22020-12-15 12:42:19 -0600686 }
687 aResp->res.jsonValue["SparePartNumber"] = *value;
688 }
689 else if (property.first == "Model")
690 {
691 const std::string* value =
692 std::get_if<std::string>(&property.second);
693 if (value == nullptr)
694 {
695 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800696 return;
SunnySrivastava1984ee135e22020-12-15 12:42:19 -0600697 }
698 aResp->res.jsonValue["Model"] = *value;
699 }
700 else if (property.first == "LocationCode")
701 {
702 const std::string* value =
703 std::get_if<std::string>(&property.second);
704 if (value == nullptr)
705 {
706 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800707 return;
SunnySrivastava1984ee135e22020-12-15 12:42:19 -0600708 }
709 aResp->res
710 .jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
711 *value;
712 }
James Feistc50e7c62020-07-27 15:39:36 -0700713 else
714 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800715 getPersistentMemoryProperties(aResp, property);
James Feistc50e7c62020-07-27 15:39:36 -0700716 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200717 }
718 },
719 service, objPath, "org.freedesktop.DBus.Properties", "GetAll", "");
720}
721
zhanghch058d1b46d2021-04-01 11:18:24 +0800722inline void getDimmPartitionData(std::shared_ptr<bmcweb::AsyncResp> aResp,
Ed Tanous23a21a12020-07-25 04:45:05 +0000723 const std::string& service,
724 const std::string& path)
James Feist45094ad2020-04-29 14:02:30 -0700725{
726 crow::connections::systemBus->async_method_call(
727 [aResp{std::move(aResp)}](
728 const boost::system::error_code ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800729 const dbus::utility::DBusPropertiesMap& properties) {
James Feist45094ad2020-04-29 14:02:30 -0700730 if (ec)
731 {
732 BMCWEB_LOG_DEBUG << "DBUS response error";
733 messages::internalError(aResp->res);
734
735 return;
736 }
737
738 nlohmann::json& partition =
739 aResp->res.jsonValue["Regions"].emplace_back(
740 nlohmann::json::object());
741 for (const auto& [key, val] : properties)
742 {
743 if (key == "MemoryClassification")
744 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700745 const std::string* value = std::get_if<std::string>(&val);
746 if (value == nullptr)
747 {
748 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800749 return;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700750 }
751 partition[key] = *value;
James Feist45094ad2020-04-29 14:02:30 -0700752 }
753 else if (key == "OffsetInKiB")
754 {
755 const uint64_t* value = std::get_if<uint64_t>(&val);
756 if (value == nullptr)
757 {
758 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800759 return;
James Feist45094ad2020-04-29 14:02:30 -0700760 }
761
762 partition["OffsetMiB"] = (*value >> 10);
763 }
764 else if (key == "PartitionId")
765 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700766 const std::string* value = std::get_if<std::string>(&val);
767 if (value == nullptr)
768 {
769 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800770 return;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700771 }
772 partition["RegionId"] = *value;
James Feist45094ad2020-04-29 14:02:30 -0700773 }
774
775 else if (key == "PassphraseState")
776 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700777 const bool* value = std::get_if<bool>(&val);
778 if (value == nullptr)
779 {
780 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800781 return;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700782 }
783 partition["PassphraseEnabled"] = *value;
James Feist45094ad2020-04-29 14:02:30 -0700784 }
785 else if (key == "SizeInKiB")
786 {
787 const uint64_t* value = std::get_if<uint64_t>(&val);
788 if (value == nullptr)
789 {
790 messages::internalError(aResp->res);
791 BMCWEB_LOG_DEBUG
792 << "Invalid property type for SizeInKiB";
Chicago Duan601af5e2021-04-15 16:59:25 +0800793 return;
James Feist45094ad2020-04-29 14:02:30 -0700794 }
795 partition["SizeMiB"] = (*value >> 10);
796 }
797 }
798 },
799
800 service, path, "org.freedesktop.DBus.Properties", "GetAll",
801 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition");
802}
803
zhanghch058d1b46d2021-04-01 11:18:24 +0800804inline void getDimmData(std::shared_ptr<bmcweb::AsyncResp> aResp,
Ed Tanous23a21a12020-07-25 04:45:05 +0000805 const std::string& dimmId)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200806{
807 BMCWEB_LOG_DEBUG << "Get available system dimm resources.";
808 crow::connections::systemBus->async_method_call(
Ed Tanous029573d2019-02-01 10:57:49 -0800809 [dimmId, aResp{std::move(aResp)}](
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200810 const boost::system::error_code ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800811 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200812 if (ec)
813 {
814 BMCWEB_LOG_DEBUG << "DBUS response error";
815 messages::internalError(aResp->res);
816
817 return;
818 }
James Feist45094ad2020-04-29 14:02:30 -0700819 bool found = false;
820 for (const auto& [path, object] : subtree)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200821 {
James Feist45094ad2020-04-29 14:02:30 -0700822 if (path.find(dimmId) != std::string::npos)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200823 {
James Feist45094ad2020-04-29 14:02:30 -0700824 for (const auto& [service, interfaces] : object)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200825 {
Ed Tanousb9d36b42022-02-26 21:42:46 -0800826 for (const auto& interface : interfaces)
James Feist45094ad2020-04-29 14:02:30 -0700827 {
Ed Tanousb9d36b42022-02-26 21:42:46 -0800828 if (interface ==
829 "xyz.openbmc_project.Inventory.Item.Dimm")
830 {
831 getDimmDataByService(aResp, dimmId, service,
832 path);
833 found = true;
834 }
James Feist45094ad2020-04-29 14:02:30 -0700835
Ed Tanousb9d36b42022-02-26 21:42:46 -0800836 // partitions are separate as there can be multiple
837 // per
838 // device, i.e.
839 // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition1
840 // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition2
841 if (interface ==
842 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition")
843 {
844 getDimmPartitionData(aResp, service, path);
845 }
James Feist45094ad2020-04-29 14:02:30 -0700846 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200847 }
848 }
849 }
850 // Object not found
James Feist45094ad2020-04-29 14:02:30 -0700851 if (!found)
852 {
853 messages::resourceNotFound(aResp->res, "Memory", dimmId);
854 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200855 return;
856 },
857 "xyz.openbmc_project.ObjectMapper",
858 "/xyz/openbmc_project/object_mapper",
859 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous271584a2019-07-09 16:24:22 -0700860 "/xyz/openbmc_project/inventory", 0,
James Feist45094ad2020-04-29 14:02:30 -0700861 std::array<const char*, 2>{
862 "xyz.openbmc_project.Inventory.Item.Dimm",
863 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition"});
Ed Tanous271584a2019-07-09 16:24:22 -0700864}
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200865
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700866inline void requestRoutesMemoryCollection(App& app)
Ed Tanous029573d2019-02-01 10:57:49 -0800867{
Ed Tanous029573d2019-02-01 10:57:49 -0800868 /**
869 * Functions triggers appropriate requests on DBus
870 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700871 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Memory/")
Ed Tanoused398212021-06-09 17:05:54 -0700872 .privileges(redfish::privileges::getMemoryCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700873 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700874 [&app](const crow::Request& req,
875 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
876 if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
877 {
878 return;
879 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700880 asyncResp->res.jsonValue["@odata.type"] =
881 "#MemoryCollection.MemoryCollection";
882 asyncResp->res.jsonValue["Name"] = "Memory Module Collection";
883 asyncResp->res.jsonValue["@odata.id"] =
884 "/redfish/v1/Systems/system/Memory";
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200885
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700886 collection_util::getCollectionMembers(
887 asyncResp, "/redfish/v1/Systems/system/Memory",
888 {"xyz.openbmc_project.Inventory.Item.Dimm"});
889 });
890}
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200891
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700892inline void requestRoutesMemory(App& app)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200893{
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200894 /**
895 * Functions triggers appropriate requests on DBus
896 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700897 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Memory/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700898 .privileges(redfish::privileges::getMemory)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700899 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700900 [&app](const crow::Request& req,
901 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
902 const std::string& dimmId) {
903 if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
904 {
905 return;
906 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700907 asyncResp->res.jsonValue["@odata.type"] =
908 "#Memory.v1_11_0.Memory";
909 asyncResp->res.jsonValue["@odata.id"] =
910 "/redfish/v1/Systems/system/Memory/" + dimmId;
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200911
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700912 getDimmData(asyncResp, dimmId);
913 });
914}
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200915
916} // namespace redfish