blob: feeb102a678045c67bc9495e36d98e93c8ebd574 [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>
Nan Zhoud7f04fd2022-05-01 01:11:07 +000022#include <nlohmann/json.hpp>
Ed Tanous45ca1b82022-03-25 13:07:27 -070023#include <query.hpp>
Ed Tanoused398212021-06-09 17:05:54 -070024#include <registries/privilege_registry.hpp>
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +020025#include <sdbusplus/asio/property.hpp>
26#include <sdbusplus/unpack_properties.hpp>
Gunnar Mills116bcc52020-10-14 15:23:42 -050027#include <utils/collection.hpp>
Ed Tanousf201ffb2021-10-09 14:49:28 -070028#include <utils/hex_utils.hpp>
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +020029#include <utils/json_utils.hpp>
30
31namespace redfish
32{
33
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 }
Tyson Tuckerbearce34d512022-09-13 16:26:15 -0700122 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.HBM3")
123 {
124 return "HBM3";
125 }
Gunnar Mills313efb12020-10-26 16:05:08 -0500126 // This is values like Other or Unknown
127 // Also D-Bus values:
128 // DRAM
129 // EDRAM
130 // VRAM
131 // SRAM
132 // RAM
133 // FLASH
134 // EEPROM
135 // FEPROM
136 // EPROM
137 // CDRAM
138 // ThreeDRAM
139 // RDRAM
140 // FBD2
141 // LPDDR_SDRAM
142 // LPDDR2_SDRAM
Mansi Joshi11a2f0f2021-07-19 14:33:27 +0530143 // LPDDR5_SDRAM
Gunnar Mills313efb12020-10-26 16:05:08 -0500144 return "";
145}
146
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200147inline void dimmPropToHex(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
148 const char* key, const uint16_t* value,
149 const nlohmann::json::json_pointer& jsonPtr)
James Feistc50e7c62020-07-27 15:39:36 -0700150{
James Feistc50e7c62020-07-27 15:39:36 -0700151 if (value == nullptr)
152 {
James Feistc50e7c62020-07-27 15:39:36 -0700153 return;
154 }
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000155 aResp->res.jsonValue[jsonPtr][key] = "0x" + intToHexString(*value, 4);
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,
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200160 const dbus::utility::DBusPropertiesMap& properties,
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000161 const nlohmann::json::json_pointer& jsonPtr)
James Feistc50e7c62020-07-27 15:39:36 -0700162{
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200163 const uint16_t* moduleManufacturerID = nullptr;
164 const uint16_t* moduleProductID = nullptr;
165 const uint16_t* subsystemVendorID = nullptr;
166 const uint16_t* subsystemDeviceID = nullptr;
167 const uint64_t* volatileRegionSizeLimitInKiB = nullptr;
168 const uint64_t* pmRegionSizeLimitInKiB = nullptr;
169 const uint64_t* volatileSizeInKiB = nullptr;
170 const uint64_t* pmSizeInKiB = nullptr;
171 const uint64_t* cacheSizeInKB = nullptr;
172 const uint64_t* voltaileRegionMaxSizeInKib = nullptr;
173 const uint64_t* pmRegionMaxSizeInKiB = nullptr;
174 const uint64_t* allocationIncrementInKiB = nullptr;
175 const uint64_t* allocationAlignmentInKiB = nullptr;
176 const uint64_t* volatileRegionNumberLimit = nullptr;
177 const uint64_t* pmRegionNumberLimit = nullptr;
178 const uint64_t* spareDeviceCount = nullptr;
179 const bool* isSpareDeviceInUse = nullptr;
180 const bool* isRankSpareEnabled = nullptr;
181 const std::vector<uint32_t>* maxAveragePowerLimitmW = nullptr;
182 const bool* configurationLocked = nullptr;
183 const std::string* allowedMemoryModes = nullptr;
184 const std::string* memoryMedia = nullptr;
185 const bool* configurationLockCapable = nullptr;
186 const bool* dataLockCapable = nullptr;
187 const bool* passphraseCapable = nullptr;
188 const uint64_t* maxPassphraseCount = nullptr;
189 const uint64_t* passphraseLockLimit = nullptr;
James Feistc50e7c62020-07-27 15:39:36 -0700190
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200191 const bool success = sdbusplus::unpackPropertiesNoThrow(
192 dbus_utils::UnpackErrorPrinter(), properties, "ModuleManufacturerID",
193 moduleManufacturerID, "ModuleProductID", moduleProductID,
194 "SubsystemVendorID", subsystemVendorID, "SubsystemDeviceID",
195 subsystemDeviceID, "VolatileRegionSizeLimitInKiB",
196 volatileRegionSizeLimitInKiB, "PmRegionSizeLimitInKiB",
197 pmRegionSizeLimitInKiB, "VolatileSizeInKiB", volatileSizeInKiB,
198 "PmSizeInKiB", pmSizeInKiB, "CacheSizeInKB", cacheSizeInKB,
199 "VoltaileRegionMaxSizeInKib", voltaileRegionMaxSizeInKib,
200 "PmRegionMaxSizeInKiB", pmRegionMaxSizeInKiB,
201 "AllocationIncrementInKiB", allocationIncrementInKiB,
202 "AllocationAlignmentInKiB", allocationAlignmentInKiB,
203 "VolatileRegionNumberLimit", volatileRegionNumberLimit,
204 "PmRegionNumberLimit", pmRegionNumberLimit, "SpareDeviceCount",
205 spareDeviceCount, "IsSpareDeviceInUse", isSpareDeviceInUse,
206 "IsRankSpareEnabled", isRankSpareEnabled, "MaxAveragePowerLimitmW",
207 maxAveragePowerLimitmW, "ConfigurationLocked", configurationLocked,
208 "AllowedMemoryModes", allowedMemoryModes, "MemoryMedia", memoryMedia,
209 "ConfigurationLockCapable", configurationLockCapable, "DataLockCapable",
210 dataLockCapable, "PassphraseCapable", passphraseCapable,
211 "MaxPassphraseCount", maxPassphraseCount, "PassphraseLockLimit",
212 passphraseLockLimit);
213
214 if (!success)
215 {
216 messages::internalError(aResp->res);
217 return;
218 }
219
220 dimmPropToHex(aResp, "ModuleManufacturerID", moduleManufacturerID, jsonPtr);
221 dimmPropToHex(aResp, "ModuleProductID", moduleProductID, jsonPtr);
222 dimmPropToHex(aResp, "MemorySubsystemControllerManufacturerID",
223 subsystemVendorID, jsonPtr);
224 dimmPropToHex(aResp, "MemorySubsystemControllerProductID",
225 subsystemDeviceID, jsonPtr);
226
227 if (volatileRegionSizeLimitInKiB != nullptr)
228 {
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000229 aResp->res.jsonValue[jsonPtr]["VolatileRegionSizeLimitMiB"] =
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200230 (*volatileRegionSizeLimitInKiB) >> 10;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800231 }
James Feistc50e7c62020-07-27 15:39:36 -0700232
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200233 if (pmRegionSizeLimitInKiB != nullptr)
234 {
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000235 aResp->res.jsonValue[jsonPtr]["PersistentRegionSizeLimitMiB"] =
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200236 (*pmRegionSizeLimitInKiB) >> 10;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800237 }
James Feistc50e7c62020-07-27 15:39:36 -0700238
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200239 if (volatileSizeInKiB != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800240 {
James Feistc50e7c62020-07-27 15:39:36 -0700241
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200242 aResp->res.jsonValue[jsonPtr]["VolatileSizeMiB"] =
243 (*volatileSizeInKiB) >> 10;
244 }
245
246 if (pmSizeInKiB != nullptr)
247 {
248 aResp->res.jsonValue[jsonPtr]["NonVolatileSizeMiB"] =
249 (*pmSizeInKiB) >> 10;
250 }
251
252 if (cacheSizeInKB != nullptr)
253 {
254 aResp->res.jsonValue[jsonPtr]["CacheSizeMiB"] = (*cacheSizeInKB >> 10);
255 }
256
257 if (voltaileRegionMaxSizeInKib != nullptr)
258 {
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000259 aResp->res.jsonValue[jsonPtr]["VolatileRegionSizeMaxMiB"] =
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200260 (*voltaileRegionMaxSizeInKib) >> 10;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800261 }
James Feistc50e7c62020-07-27 15:39:36 -0700262
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200263 if (pmRegionMaxSizeInKiB != nullptr)
264 {
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000265 aResp->res.jsonValue[jsonPtr]["PersistentRegionSizeMaxMiB"] =
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200266 (*pmRegionMaxSizeInKiB) >> 10;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800267 }
James Feistc50e7c62020-07-27 15:39:36 -0700268
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200269 if (allocationIncrementInKiB != nullptr)
270 {
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000271 aResp->res.jsonValue[jsonPtr]["AllocationIncrementMiB"] =
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200272 (*allocationIncrementInKiB) >> 10;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800273 }
James Feistc50e7c62020-07-27 15:39:36 -0700274
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200275 if (allocationAlignmentInKiB != nullptr)
276 {
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000277 aResp->res.jsonValue[jsonPtr]["AllocationAlignmentMiB"] =
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200278 (*allocationAlignmentInKiB) >> 10;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800279 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200280
281 if (volatileRegionNumberLimit != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800282 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200283 aResp->res.jsonValue[jsonPtr]["VolatileRegionNumberLimit"] =
284 *volatileRegionNumberLimit;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800285 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200286
287 if (pmRegionNumberLimit != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800288 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200289 aResp->res.jsonValue[jsonPtr]["PersistentRegionNumberLimit"] =
290 *pmRegionNumberLimit;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800291 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200292
293 if (spareDeviceCount != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800294 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200295 aResp->res.jsonValue[jsonPtr]["SpareDeviceCount"] = *spareDeviceCount;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800296 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200297
298 if (isSpareDeviceInUse != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800299 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200300 aResp->res.jsonValue[jsonPtr]["IsSpareDeviceEnabled"] =
301 *isSpareDeviceInUse;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800302 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200303
304 if (isRankSpareEnabled != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800305 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200306 aResp->res.jsonValue[jsonPtr]["IsRankSpareEnabled"] =
307 *isRankSpareEnabled;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800308 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200309
310 if (maxAveragePowerLimitmW != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800311 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200312 aResp->res.jsonValue[jsonPtr]["MaxTDPMilliWatts"] =
313 *maxAveragePowerLimitmW;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800314 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200315
316 if (configurationLocked != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800317 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200318 aResp->res.jsonValue[jsonPtr]["ConfigurationLocked"] =
319 *configurationLocked;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800320 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200321
322 if (allowedMemoryModes != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800323 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800324 constexpr const std::array<const char*, 3> values{"Volatile", "PMEM",
325 "Block"};
James Feistc50e7c62020-07-27 15:39:36 -0700326
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800327 for (const char* v : values)
328 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200329 if (allowedMemoryModes->ends_with(v))
James Feistc50e7c62020-07-27 15:39:36 -0700330 {
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000331 aResp->res.jsonValue[jsonPtr]["OperatingMemoryModes"].push_back(
332 v);
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800333 break;
James Feistc50e7c62020-07-27 15:39:36 -0700334 }
335 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800336 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200337
338 if (memoryMedia != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800339 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800340 constexpr const std::array<const char*, 3> values{"DRAM", "NAND",
341 "Intel3DXPoint"};
James Feistc50e7c62020-07-27 15:39:36 -0700342
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800343 for (const char* v : values)
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700344 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200345 if (memoryMedia->ends_with(v))
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700346 {
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000347 aResp->res.jsonValue[jsonPtr]["MemoryMedia"].push_back(v);
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800348 break;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700349 }
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700350 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800351 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200352
353 if (configurationLockCapable != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800354 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200355 aResp->res.jsonValue[jsonPtr]["SecurityCapabilities"]
356 ["ConfigurationLockCapable"] =
357 *configurationLockCapable;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800358 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200359
360 if (dataLockCapable != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800361 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200362 aResp->res
363 .jsonValue[jsonPtr]["SecurityCapabilities"]["DataLockCapable"] =
364 *dataLockCapable;
365 }
366
367 if (passphraseCapable != nullptr)
368 {
369 aResp->res
370 .jsonValue[jsonPtr]["SecurityCapabilities"]["PassphraseCapable"] =
371 *passphraseCapable;
372 }
373
374 if (maxPassphraseCount != nullptr)
375 {
376 aResp->res
377 .jsonValue[jsonPtr]["SecurityCapabilities"]["MaxPassphraseCount"] =
378 *maxPassphraseCount;
379 }
380
381 if (passphraseLockLimit != nullptr)
382 {
383 aResp->res
384 .jsonValue[jsonPtr]["SecurityCapabilities"]["PassphraseLockLimit"] =
385 *passphraseLockLimit;
James Feistc50e7c62020-07-27 15:39:36 -0700386 }
387}
388
Nan Zhou9a5acea2022-05-17 21:12:43 +0000389inline void
390 assembleDimmProperties(std::string_view dimmId,
391 const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000392 const dbus::utility::DBusPropertiesMap& properties,
393 const nlohmann::json::json_pointer& jsonPtr)
Nan Zhou9a5acea2022-05-17 21:12:43 +0000394{
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000395 aResp->res.jsonValue[jsonPtr]["Id"] = dimmId;
396 aResp->res.jsonValue[jsonPtr]["Name"] = "DIMM Slot";
397 aResp->res.jsonValue[jsonPtr]["Status"]["State"] = "Enabled";
398 aResp->res.jsonValue[jsonPtr]["Status"]["Health"] = "OK";
Nan Zhou9a5acea2022-05-17 21:12:43 +0000399
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200400 const uint16_t* memoryDataWidth = nullptr;
401 const size_t* memorySizeInKB = nullptr;
402 const std::string* partNumber = nullptr;
403 const std::string* serialNumber = nullptr;
404 const std::string* manufacturer = nullptr;
405 const uint16_t* revisionCode = nullptr;
406 const bool* present = nullptr;
407 const uint16_t* memoryTotalWidth = nullptr;
408 const std::string* ecc = nullptr;
409 const std::string* formFactor = nullptr;
410 const std::vector<uint16_t>* allowedSpeedsMT = nullptr;
411 const uint8_t* memoryAttributes = nullptr;
412 const uint16_t* memoryConfiguredSpeedInMhz = nullptr;
413 const std::string* memoryType = nullptr;
414 const std::string* channel = nullptr;
415 const std::string* memoryController = nullptr;
416 const std::string* slot = nullptr;
417 const std::string* socket = nullptr;
418 const std::string* sparePartNumber = nullptr;
419 const std::string* model = nullptr;
420 const std::string* locationCode = nullptr;
421
422 const bool success = sdbusplus::unpackPropertiesNoThrow(
423 dbus_utils::UnpackErrorPrinter(), properties, "MemoryDataWidth",
424 memoryDataWidth, "MemorySizeInKB", memorySizeInKB, "PartNumber",
425 partNumber, "SerialNumber", serialNumber, "Present", present,
426 "MemoryTotalWidth", memoryTotalWidth, "ECC", ecc, "FormFactor",
427 formFactor, "AllowedSpeedsMT", allowedSpeedsMT, "MemoryAttributes",
428 memoryAttributes, "MemoryConfiguredSpeedInMhz",
429 memoryConfiguredSpeedInMhz, "MemoryType", memoryType, "Channel",
430 channel, "MemoryController", memoryController, "Slot", slot, "Socket",
431 socket, "SparePartNumber", sparePartNumber, "Model", model,
432 "LocationCode", locationCode);
433
434 if (!success)
Nan Zhou9a5acea2022-05-17 21:12:43 +0000435 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200436 messages::internalError(aResp->res);
437 return;
438 }
Nan Zhou9a5acea2022-05-17 21:12:43 +0000439
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200440 if (memoryDataWidth != nullptr)
441 {
442 aResp->res.jsonValue[jsonPtr]["DataWidthBits"] = *memoryDataWidth;
443 }
Nan Zhou9a5acea2022-05-17 21:12:43 +0000444
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200445 if (memorySizeInKB != nullptr)
446 {
447 aResp->res.jsonValue[jsonPtr]["CapacityMiB"] = (*memorySizeInKB >> 10);
448 }
Nan Zhou9a5acea2022-05-17 21:12:43 +0000449
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200450 if (partNumber != nullptr)
451 {
452 aResp->res.jsonValue[jsonPtr]["PartNumber"] = *partNumber;
453 }
Nan Zhou9a5acea2022-05-17 21:12:43 +0000454
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200455 if (serialNumber != nullptr)
456 {
457 aResp->res.jsonValue[jsonPtr]["SerialNumber"] = *serialNumber;
458 }
459
460 if (manufacturer != nullptr)
461 {
462 aResp->res.jsonValue[jsonPtr]["Manufacturer"] = *manufacturer;
463 }
464
465 if (revisionCode != nullptr)
466 {
467 aResp->res.jsonValue[jsonPtr]["FirmwareRevision"] =
468 std::to_string(*revisionCode);
469 }
470
471 if (present != nullptr && !*present)
472 {
473 aResp->res.jsonValue[jsonPtr]["Status"]["State"] = "Absent";
474 }
475
476 if (memoryTotalWidth != nullptr)
477 {
478 aResp->res.jsonValue[jsonPtr]["BusWidthBits"] = *memoryTotalWidth;
479 }
480
481 if (ecc != nullptr)
482 {
483 constexpr const std::array<const char*, 4> values{
484 "NoECC", "SingleBitECC", "MultiBitECC", "AddressParity"};
485
486 for (const char* v : values)
Nan Zhou9a5acea2022-05-17 21:12:43 +0000487 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200488 if (ecc->ends_with(v))
Nan Zhou9a5acea2022-05-17 21:12:43 +0000489 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200490 aResp->res.jsonValue[jsonPtr]["ErrorCorrection"] = v;
491 break;
Nan Zhou9a5acea2022-05-17 21:12:43 +0000492 }
Nan Zhou9a5acea2022-05-17 21:12:43 +0000493 }
494 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200495
496 if (formFactor != nullptr)
497 {
498 constexpr const std::array<const char*, 11> values{
499 "RDIMM", "UDIMM", "SO_DIMM", "LRDIMM",
500 "Mini_RDIMM", "Mini_UDIMM", "SO_RDIMM_72b", "SO_UDIMM_72b",
501 "SO_DIMM_16b", "SO_DIMM_32b", "Die"};
502
503 for (const char* v : values)
504 {
505 if (formFactor->ends_with(v))
506 {
507 aResp->res.jsonValue[jsonPtr]["BaseModuleType"] = v;
508 break;
509 }
510 }
511 }
512
513 if (allowedSpeedsMT != nullptr)
514 {
515 nlohmann::json& jValue =
516 aResp->res.jsonValue[jsonPtr]["AllowedSpeedsMHz"];
517 jValue = nlohmann::json::array();
518 for (uint16_t subVal : *allowedSpeedsMT)
519 {
520 jValue.push_back(subVal);
521 }
522 }
523
524 if (memoryAttributes != nullptr)
525 {
526 aResp->res.jsonValue[jsonPtr]["RankCount"] =
527 static_cast<uint64_t>(*memoryAttributes);
528 }
529
530 if (memoryConfiguredSpeedInMhz != nullptr)
531 {
532 aResp->res.jsonValue[jsonPtr]["OperatingSpeedMhz"] =
533 *memoryConfiguredSpeedInMhz;
534 }
535
536 if (memoryType != nullptr)
537 {
538 std::string memoryDeviceType =
539 translateMemoryTypeToRedfish(*memoryType);
540 // Values like "Unknown" or "Other" will return empty
541 // so just leave off
542 if (!memoryDeviceType.empty())
543 {
544 aResp->res.jsonValue[jsonPtr]["MemoryDeviceType"] =
545 memoryDeviceType;
546 }
547 if (memoryType->find("DDR") != std::string::npos)
548 {
549 aResp->res.jsonValue[jsonPtr]["MemoryType"] = "DRAM";
550 }
551 else if (memoryType->ends_with("Logical"))
552 {
553 aResp->res.jsonValue[jsonPtr]["MemoryType"] = "IntelOptane";
554 }
555 }
556
557 if (channel != nullptr)
558 {
559 aResp->res.jsonValue[jsonPtr]["MemoryLocation"]["Channel"] = *channel;
560 }
561
562 if (memoryController != nullptr)
563 {
564 aResp->res.jsonValue[jsonPtr]["MemoryLocation"]["MemoryController"] =
565 *memoryController;
566 }
567
568 if (slot != nullptr)
569 {
570 aResp->res.jsonValue[jsonPtr]["MemoryLocation"]["Slot"] = *slot;
571 }
572
573 if (socket != nullptr)
574 {
575 aResp->res.jsonValue[jsonPtr]["MemoryLocation"]["Socket"] = *socket;
576 }
577
578 if (sparePartNumber != nullptr)
579 {
580 aResp->res.jsonValue[jsonPtr]["SparePartNumber"] = *sparePartNumber;
581 }
582
583 if (model != nullptr)
584 {
585 aResp->res.jsonValue[jsonPtr]["Model"] = *model;
586 }
587
588 if (locationCode != nullptr)
589 {
590 aResp->res
591 .jsonValue[jsonPtr]["Location"]["PartLocation"]["ServiceLabel"] =
592 *locationCode;
593 }
594
595 getPersistentMemoryProperties(aResp, properties, jsonPtr);
Nan Zhou9a5acea2022-05-17 21:12:43 +0000596}
597
zhanghch058d1b46d2021-04-01 11:18:24 +0800598inline void getDimmDataByService(std::shared_ptr<bmcweb::AsyncResp> aResp,
Ed Tanous80789c82020-08-19 09:19:09 -0700599 const std::string& dimmId,
600 const std::string& service,
601 const std::string& objPath)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200602{
James Feist35e257a2020-06-05 13:30:51 -0700603 auto health = std::make_shared<HealthPopulate>(aResp);
604 health->selfPath = objPath;
605 health->populate();
606
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200607 BMCWEB_LOG_DEBUG << "Get available system components.";
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200608 sdbusplus::asio::getAllProperties(
609 *crow::connections::systemBus, service, objPath, "",
Ed Tanousb9d36b42022-02-26 21:42:46 -0800610 [dimmId, aResp{std::move(aResp)}](
611 const boost::system::error_code ec,
612 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700613 if (ec)
614 {
615 BMCWEB_LOG_DEBUG << "DBUS response error";
616 messages::internalError(aResp->res);
617 return;
618 }
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000619 assembleDimmProperties(dimmId, aResp, properties, ""_json_pointer);
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200620 });
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200621}
622
Nan Zhouef00d7d2022-05-20 21:22:32 +0000623inline void assembleDimmPartitionData(
624 const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000625 const dbus::utility::DBusPropertiesMap& properties,
626 const nlohmann::json::json_pointer& regionPtr)
Nan Zhouef00d7d2022-05-20 21:22:32 +0000627{
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200628 const std::string* memoryClassification = nullptr;
629 const uint64_t* offsetInKiB = nullptr;
630 const std::string* partitionId = nullptr;
631 const bool* passphraseState = nullptr;
632 const uint64_t* sizeInKiB = nullptr;
633
634 const bool success = sdbusplus::unpackPropertiesNoThrow(
635 dbus_utils::UnpackErrorPrinter(), properties, "MemoryClassification",
636 memoryClassification, "OffsetInKiB", offsetInKiB, "PartitionId",
637 partitionId, "PassphraseState", passphraseState, "SizeInKiB",
638 sizeInKiB);
639
640 if (!success)
Nan Zhouef00d7d2022-05-20 21:22:32 +0000641 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200642 messages::internalError(aResp->res);
643 return;
Nan Zhouef00d7d2022-05-20 21:22:32 +0000644 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200645
646 nlohmann::json::object_t partition;
647
648 if (memoryClassification != nullptr)
649 {
650 partition["MemoryClassification"] = *memoryClassification;
651 }
652
653 if (offsetInKiB != nullptr)
654 {
655 partition["OffsetMiB"] = (*offsetInKiB >> 10);
656 }
657
658 if (partitionId != nullptr)
659 {
660 partition["RegionId"] = *partitionId;
661 }
662
663 if (passphraseState != nullptr)
664 {
665 partition["PassphraseEnabled"] = *passphraseState;
666 }
667
668 if (sizeInKiB != nullptr)
669 {
670 partition["SizeMiB"] = (*sizeInKiB >> 10);
671 }
672
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000673 aResp->res.jsonValue[regionPtr].emplace_back(std::move(partition));
Nan Zhouef00d7d2022-05-20 21:22:32 +0000674}
675
zhanghch058d1b46d2021-04-01 11:18:24 +0800676inline void getDimmPartitionData(std::shared_ptr<bmcweb::AsyncResp> aResp,
Ed Tanous23a21a12020-07-25 04:45:05 +0000677 const std::string& service,
678 const std::string& path)
James Feist45094ad2020-04-29 14:02:30 -0700679{
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200680 sdbusplus::asio::getAllProperties(
681 *crow::connections::systemBus, service, path,
682 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition",
James Feist45094ad2020-04-29 14:02:30 -0700683 [aResp{std::move(aResp)}](
684 const boost::system::error_code ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800685 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700686 if (ec)
687 {
688 BMCWEB_LOG_DEBUG << "DBUS response error";
689 messages::internalError(aResp->res);
James Feist45094ad2020-04-29 14:02:30 -0700690
Ed Tanous002d39b2022-05-31 08:59:27 -0700691 return;
692 }
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000693 nlohmann::json::json_pointer regionPtr = "/Regions"_json_pointer;
694 assembleDimmPartitionData(aResp, properties, regionPtr);
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200695 }
James Feist45094ad2020-04-29 14:02:30 -0700696
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200697 );
James Feist45094ad2020-04-29 14:02:30 -0700698}
699
zhanghch058d1b46d2021-04-01 11:18:24 +0800700inline void getDimmData(std::shared_ptr<bmcweb::AsyncResp> aResp,
Ed Tanous23a21a12020-07-25 04:45:05 +0000701 const std::string& dimmId)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200702{
703 BMCWEB_LOG_DEBUG << "Get available system dimm resources.";
704 crow::connections::systemBus->async_method_call(
Ed Tanous029573d2019-02-01 10:57:49 -0800705 [dimmId, aResp{std::move(aResp)}](
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200706 const boost::system::error_code ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800707 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700708 if (ec)
709 {
710 BMCWEB_LOG_DEBUG << "DBUS response error";
711 messages::internalError(aResp->res);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200712
Ed Tanous002d39b2022-05-31 08:59:27 -0700713 return;
714 }
715 bool found = false;
Nan Zhou76686dc2022-06-17 23:01:51 +0000716 for (const auto& [rawPath, object] : subtree)
Ed Tanous002d39b2022-05-31 08:59:27 -0700717 {
Nan Zhou76686dc2022-06-17 23:01:51 +0000718 sdbusplus::message::object_path path(rawPath);
719 for (const auto& [service, interfaces] : object)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200720 {
Nan Zhou76686dc2022-06-17 23:01:51 +0000721 for (const auto& interface : interfaces)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200722 {
Nan Zhou76686dc2022-06-17 23:01:51 +0000723 if (interface ==
724 "xyz.openbmc_project.Inventory.Item.Dimm" &&
725 path.filename() == dimmId)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200726 {
Nan Zhou76686dc2022-06-17 23:01:51 +0000727 getDimmDataByService(aResp, dimmId, service, rawPath);
728 found = true;
729 }
James Feist45094ad2020-04-29 14:02:30 -0700730
Nan Zhou76686dc2022-06-17 23:01:51 +0000731 // partitions are separate as there can be multiple
732 // per
733 // device, i.e.
734 // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition1
735 // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition2
736 if (interface ==
737 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition" &&
738 path.parent_path().filename() == dimmId)
739 {
740 getDimmPartitionData(aResp, service, rawPath);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200741 }
742 }
743 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700744 }
745 // Object not found
746 if (!found)
747 {
748 messages::resourceNotFound(aResp->res, "Memory", dimmId);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200749 return;
Ed Tanous002d39b2022-05-31 08:59:27 -0700750 }
751 // Set @odata only if object is found
752 aResp->res.jsonValue["@odata.type"] = "#Memory.v1_11_0.Memory";
753 aResp->res.jsonValue["@odata.id"] =
754 "/redfish/v1/Systems/system/Memory/" + dimmId;
755 return;
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200756 },
757 "xyz.openbmc_project.ObjectMapper",
758 "/xyz/openbmc_project/object_mapper",
759 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous271584a2019-07-09 16:24:22 -0700760 "/xyz/openbmc_project/inventory", 0,
James Feist45094ad2020-04-29 14:02:30 -0700761 std::array<const char*, 2>{
762 "xyz.openbmc_project.Inventory.Item.Dimm",
763 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition"});
Ed Tanous271584a2019-07-09 16:24:22 -0700764}
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200765
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700766inline void requestRoutesMemoryCollection(App& app)
Ed Tanous029573d2019-02-01 10:57:49 -0800767{
Ed Tanous029573d2019-02-01 10:57:49 -0800768 /**
769 * Functions triggers appropriate requests on DBus
770 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700771 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Memory/")
Ed Tanoused398212021-06-09 17:05:54 -0700772 .privileges(redfish::privileges::getMemoryCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700773 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700774 [&app](const crow::Request& req,
775 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Carson Labrado3ba00072022-06-06 19:40:56 +0000776 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -0700777 {
778 return;
779 }
780 asyncResp->res.jsonValue["@odata.type"] =
781 "#MemoryCollection.MemoryCollection";
782 asyncResp->res.jsonValue["Name"] = "Memory Module Collection";
783 asyncResp->res.jsonValue["@odata.id"] =
784 "/redfish/v1/Systems/system/Memory";
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200785
Ed Tanous002d39b2022-05-31 08:59:27 -0700786 collection_util::getCollectionMembers(
787 asyncResp, "/redfish/v1/Systems/system/Memory",
788 {"xyz.openbmc_project.Inventory.Item.Dimm"});
789 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700790}
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200791
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700792inline void requestRoutesMemory(App& app)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200793{
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200794 /**
795 * Functions triggers appropriate requests on DBus
796 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700797 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Memory/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700798 .privileges(redfish::privileges::getMemory)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700799 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700800 [&app](const crow::Request& req,
801 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
802 const std::string& dimmId) {
Carson Labrado3ba00072022-06-06 19:40:56 +0000803 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -0700804 {
805 return;
806 }
807 getDimmData(asyncResp, dimmId);
808 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700809}
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200810
811} // namespace redfish