blob: 44784726eff3acd48a34b7c73776dd761cfebf83 [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
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080018#include "app.hpp"
19#include "dbus_utility.hpp"
James Feist35e257a2020-06-05 13:30:51 -070020#include "health.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080021#include "query.hpp"
22#include "registries/privilege_registry.hpp"
23#include "utils/collection.hpp"
24#include "utils/dbus_utils.hpp"
25#include "utils/hex_utils.hpp"
26#include "utils/json_utils.hpp"
James Feist35e257a2020-06-05 13:30:51 -070027
George Liue99073f2022-12-09 11:06:16 +080028#include <boost/system/error_code.hpp>
Nan Zhoud7f04fd2022-05-01 01:11:07 +000029#include <nlohmann/json.hpp>
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +020030#include <sdbusplus/asio/property.hpp>
31#include <sdbusplus/unpack_properties.hpp>
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +020032
George Liu7a1dbc42022-12-07 16:03:22 +080033#include <array>
34#include <string_view>
35
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +020036namespace redfish
37{
38
Gunnar Mills313efb12020-10-26 16:05:08 -050039inline std::string translateMemoryTypeToRedfish(const std::string& memoryType)
40{
41 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR")
42 {
43 return "DDR";
44 }
45 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR2")
46 {
47 return "DDR2";
48 }
49 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR3")
50 {
51 return "DDR3";
52 }
53 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR4")
54 {
55 return "DDR4";
56 }
57 if (memoryType ==
58 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR4E_SDRAM")
59 {
60 return "DDR4E_SDRAM";
61 }
Mansi Joshi11a2f0f2021-07-19 14:33:27 +053062 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR5")
63 {
64 return "DDR5";
65 }
Gunnar Mills313efb12020-10-26 16:05:08 -050066 if (memoryType ==
67 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.LPDDR4_SDRAM")
68 {
69 return "LPDDR4_SDRAM";
70 }
71 if (memoryType ==
72 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.LPDDR3_SDRAM")
73 {
74 return "LPDDR3_SDRAM";
75 }
76 if (memoryType ==
77 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR2_SDRAM_FB_DIMM")
78 {
79 return "DDR2_SDRAM_FB_DIMM";
80 }
George Liu0fda0f12021-11-16 10:06:17 +080081 if (memoryType ==
82 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR2_SDRAM_FB_DIMM_PROB")
Gunnar Mills313efb12020-10-26 16:05:08 -050083 {
84 return "DDR2_SDRAM_FB_DIMM_PROBE";
85 }
86 if (memoryType ==
87 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR_SGRAM")
88 {
89 return "DDR_SGRAM";
90 }
91 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.ROM")
92 {
93 return "ROM";
94 }
95 if (memoryType ==
96 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.SDRAM")
97 {
98 return "SDRAM";
99 }
100 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.EDO")
101 {
102 return "EDO";
103 }
104 if (memoryType ==
105 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.FastPageMode")
106 {
107 return "FastPageMode";
108 }
109 if (memoryType ==
110 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.PipelinedNibble")
111 {
112 return "PipelinedNibble";
113 }
114 if (memoryType ==
115 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.Logical")
116 {
117 return "Logical";
118 }
119 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.HBM")
120 {
121 return "HBM";
122 }
123 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.HBM2")
124 {
125 return "HBM2";
126 }
Tyson Tuckerbearce34d512022-09-13 16:26:15 -0700127 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.HBM3")
128 {
129 return "HBM3";
130 }
Gunnar Mills313efb12020-10-26 16:05:08 -0500131 // This is values like Other or Unknown
132 // Also D-Bus values:
133 // DRAM
134 // EDRAM
135 // VRAM
136 // SRAM
137 // RAM
138 // FLASH
139 // EEPROM
140 // FEPROM
141 // EPROM
142 // CDRAM
143 // ThreeDRAM
144 // RDRAM
145 // FBD2
146 // LPDDR_SDRAM
147 // LPDDR2_SDRAM
Mansi Joshi11a2f0f2021-07-19 14:33:27 +0530148 // LPDDR5_SDRAM
Gunnar Mills313efb12020-10-26 16:05:08 -0500149 return "";
150}
151
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200152inline void dimmPropToHex(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
153 const char* key, const uint16_t* value,
154 const nlohmann::json::json_pointer& jsonPtr)
James Feistc50e7c62020-07-27 15:39:36 -0700155{
James Feistc50e7c62020-07-27 15:39:36 -0700156 if (value == nullptr)
157 {
James Feistc50e7c62020-07-27 15:39:36 -0700158 return;
159 }
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000160 aResp->res.jsonValue[jsonPtr][key] = "0x" + intToHexString(*value, 4);
James Feistc50e7c62020-07-27 15:39:36 -0700161}
162
zhanghch058d1b46d2021-04-01 11:18:24 +0800163inline void getPersistentMemoryProperties(
164 const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200165 const dbus::utility::DBusPropertiesMap& properties,
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000166 const nlohmann::json::json_pointer& jsonPtr)
James Feistc50e7c62020-07-27 15:39:36 -0700167{
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200168 const uint16_t* moduleManufacturerID = nullptr;
169 const uint16_t* moduleProductID = nullptr;
170 const uint16_t* subsystemVendorID = nullptr;
171 const uint16_t* subsystemDeviceID = nullptr;
172 const uint64_t* volatileRegionSizeLimitInKiB = nullptr;
173 const uint64_t* pmRegionSizeLimitInKiB = nullptr;
174 const uint64_t* volatileSizeInKiB = nullptr;
175 const uint64_t* pmSizeInKiB = nullptr;
176 const uint64_t* cacheSizeInKB = nullptr;
177 const uint64_t* voltaileRegionMaxSizeInKib = nullptr;
178 const uint64_t* pmRegionMaxSizeInKiB = nullptr;
179 const uint64_t* allocationIncrementInKiB = nullptr;
180 const uint64_t* allocationAlignmentInKiB = nullptr;
181 const uint64_t* volatileRegionNumberLimit = nullptr;
182 const uint64_t* pmRegionNumberLimit = nullptr;
183 const uint64_t* spareDeviceCount = nullptr;
184 const bool* isSpareDeviceInUse = nullptr;
185 const bool* isRankSpareEnabled = nullptr;
186 const std::vector<uint32_t>* maxAveragePowerLimitmW = nullptr;
187 const bool* configurationLocked = nullptr;
188 const std::string* allowedMemoryModes = nullptr;
189 const std::string* memoryMedia = nullptr;
190 const bool* configurationLockCapable = nullptr;
191 const bool* dataLockCapable = nullptr;
192 const bool* passphraseCapable = nullptr;
193 const uint64_t* maxPassphraseCount = nullptr;
194 const uint64_t* passphraseLockLimit = nullptr;
James Feistc50e7c62020-07-27 15:39:36 -0700195
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200196 const bool success = sdbusplus::unpackPropertiesNoThrow(
197 dbus_utils::UnpackErrorPrinter(), properties, "ModuleManufacturerID",
198 moduleManufacturerID, "ModuleProductID", moduleProductID,
199 "SubsystemVendorID", subsystemVendorID, "SubsystemDeviceID",
200 subsystemDeviceID, "VolatileRegionSizeLimitInKiB",
201 volatileRegionSizeLimitInKiB, "PmRegionSizeLimitInKiB",
202 pmRegionSizeLimitInKiB, "VolatileSizeInKiB", volatileSizeInKiB,
203 "PmSizeInKiB", pmSizeInKiB, "CacheSizeInKB", cacheSizeInKB,
204 "VoltaileRegionMaxSizeInKib", voltaileRegionMaxSizeInKib,
205 "PmRegionMaxSizeInKiB", pmRegionMaxSizeInKiB,
206 "AllocationIncrementInKiB", allocationIncrementInKiB,
207 "AllocationAlignmentInKiB", allocationAlignmentInKiB,
208 "VolatileRegionNumberLimit", volatileRegionNumberLimit,
209 "PmRegionNumberLimit", pmRegionNumberLimit, "SpareDeviceCount",
210 spareDeviceCount, "IsSpareDeviceInUse", isSpareDeviceInUse,
211 "IsRankSpareEnabled", isRankSpareEnabled, "MaxAveragePowerLimitmW",
212 maxAveragePowerLimitmW, "ConfigurationLocked", configurationLocked,
213 "AllowedMemoryModes", allowedMemoryModes, "MemoryMedia", memoryMedia,
214 "ConfigurationLockCapable", configurationLockCapable, "DataLockCapable",
215 dataLockCapable, "PassphraseCapable", passphraseCapable,
216 "MaxPassphraseCount", maxPassphraseCount, "PassphraseLockLimit",
217 passphraseLockLimit);
218
219 if (!success)
220 {
221 messages::internalError(aResp->res);
222 return;
223 }
224
225 dimmPropToHex(aResp, "ModuleManufacturerID", moduleManufacturerID, jsonPtr);
226 dimmPropToHex(aResp, "ModuleProductID", moduleProductID, jsonPtr);
227 dimmPropToHex(aResp, "MemorySubsystemControllerManufacturerID",
228 subsystemVendorID, jsonPtr);
229 dimmPropToHex(aResp, "MemorySubsystemControllerProductID",
230 subsystemDeviceID, jsonPtr);
231
232 if (volatileRegionSizeLimitInKiB != nullptr)
233 {
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000234 aResp->res.jsonValue[jsonPtr]["VolatileRegionSizeLimitMiB"] =
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200235 (*volatileRegionSizeLimitInKiB) >> 10;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800236 }
James Feistc50e7c62020-07-27 15:39:36 -0700237
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200238 if (pmRegionSizeLimitInKiB != nullptr)
239 {
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000240 aResp->res.jsonValue[jsonPtr]["PersistentRegionSizeLimitMiB"] =
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200241 (*pmRegionSizeLimitInKiB) >> 10;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800242 }
James Feistc50e7c62020-07-27 15:39:36 -0700243
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200244 if (volatileSizeInKiB != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800245 {
James Feistc50e7c62020-07-27 15:39:36 -0700246
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200247 aResp->res.jsonValue[jsonPtr]["VolatileSizeMiB"] =
248 (*volatileSizeInKiB) >> 10;
249 }
250
251 if (pmSizeInKiB != nullptr)
252 {
253 aResp->res.jsonValue[jsonPtr]["NonVolatileSizeMiB"] =
254 (*pmSizeInKiB) >> 10;
255 }
256
257 if (cacheSizeInKB != nullptr)
258 {
259 aResp->res.jsonValue[jsonPtr]["CacheSizeMiB"] = (*cacheSizeInKB >> 10);
260 }
261
262 if (voltaileRegionMaxSizeInKib != nullptr)
263 {
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000264 aResp->res.jsonValue[jsonPtr]["VolatileRegionSizeMaxMiB"] =
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200265 (*voltaileRegionMaxSizeInKib) >> 10;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800266 }
James Feistc50e7c62020-07-27 15:39:36 -0700267
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200268 if (pmRegionMaxSizeInKiB != nullptr)
269 {
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000270 aResp->res.jsonValue[jsonPtr]["PersistentRegionSizeMaxMiB"] =
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200271 (*pmRegionMaxSizeInKiB) >> 10;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800272 }
James Feistc50e7c62020-07-27 15:39:36 -0700273
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200274 if (allocationIncrementInKiB != nullptr)
275 {
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000276 aResp->res.jsonValue[jsonPtr]["AllocationIncrementMiB"] =
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200277 (*allocationIncrementInKiB) >> 10;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800278 }
James Feistc50e7c62020-07-27 15:39:36 -0700279
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200280 if (allocationAlignmentInKiB != nullptr)
281 {
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000282 aResp->res.jsonValue[jsonPtr]["AllocationAlignmentMiB"] =
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200283 (*allocationAlignmentInKiB) >> 10;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800284 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200285
286 if (volatileRegionNumberLimit != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800287 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200288 aResp->res.jsonValue[jsonPtr]["VolatileRegionNumberLimit"] =
289 *volatileRegionNumberLimit;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800290 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200291
292 if (pmRegionNumberLimit != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800293 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200294 aResp->res.jsonValue[jsonPtr]["PersistentRegionNumberLimit"] =
295 *pmRegionNumberLimit;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800296 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200297
298 if (spareDeviceCount != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800299 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200300 aResp->res.jsonValue[jsonPtr]["SpareDeviceCount"] = *spareDeviceCount;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800301 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200302
303 if (isSpareDeviceInUse != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800304 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200305 aResp->res.jsonValue[jsonPtr]["IsSpareDeviceEnabled"] =
306 *isSpareDeviceInUse;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800307 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200308
309 if (isRankSpareEnabled != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800310 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200311 aResp->res.jsonValue[jsonPtr]["IsRankSpareEnabled"] =
312 *isRankSpareEnabled;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800313 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200314
315 if (maxAveragePowerLimitmW != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800316 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200317 aResp->res.jsonValue[jsonPtr]["MaxTDPMilliWatts"] =
318 *maxAveragePowerLimitmW;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800319 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200320
321 if (configurationLocked != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800322 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200323 aResp->res.jsonValue[jsonPtr]["ConfigurationLocked"] =
324 *configurationLocked;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800325 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200326
327 if (allowedMemoryModes != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800328 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800329 constexpr const std::array<const char*, 3> values{"Volatile", "PMEM",
330 "Block"};
James Feistc50e7c62020-07-27 15:39:36 -0700331
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800332 for (const char* v : values)
333 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200334 if (allowedMemoryModes->ends_with(v))
James Feistc50e7c62020-07-27 15:39:36 -0700335 {
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000336 aResp->res.jsonValue[jsonPtr]["OperatingMemoryModes"].push_back(
337 v);
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800338 break;
James Feistc50e7c62020-07-27 15:39:36 -0700339 }
340 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800341 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200342
343 if (memoryMedia != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800344 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800345 constexpr const std::array<const char*, 3> values{"DRAM", "NAND",
346 "Intel3DXPoint"};
James Feistc50e7c62020-07-27 15:39:36 -0700347
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800348 for (const char* v : values)
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700349 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200350 if (memoryMedia->ends_with(v))
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700351 {
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000352 aResp->res.jsonValue[jsonPtr]["MemoryMedia"].push_back(v);
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800353 break;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700354 }
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700355 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800356 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200357
358 if (configurationLockCapable != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800359 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200360 aResp->res.jsonValue[jsonPtr]["SecurityCapabilities"]
361 ["ConfigurationLockCapable"] =
362 *configurationLockCapable;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800363 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200364
365 if (dataLockCapable != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800366 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200367 aResp->res
368 .jsonValue[jsonPtr]["SecurityCapabilities"]["DataLockCapable"] =
369 *dataLockCapable;
370 }
371
372 if (passphraseCapable != nullptr)
373 {
374 aResp->res
375 .jsonValue[jsonPtr]["SecurityCapabilities"]["PassphraseCapable"] =
376 *passphraseCapable;
377 }
378
379 if (maxPassphraseCount != nullptr)
380 {
381 aResp->res
382 .jsonValue[jsonPtr]["SecurityCapabilities"]["MaxPassphraseCount"] =
383 *maxPassphraseCount;
384 }
385
386 if (passphraseLockLimit != nullptr)
387 {
388 aResp->res
389 .jsonValue[jsonPtr]["SecurityCapabilities"]["PassphraseLockLimit"] =
390 *passphraseLockLimit;
James Feistc50e7c62020-07-27 15:39:36 -0700391 }
392}
393
Nan Zhou9a5acea2022-05-17 21:12:43 +0000394inline void
395 assembleDimmProperties(std::string_view dimmId,
396 const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000397 const dbus::utility::DBusPropertiesMap& properties,
398 const nlohmann::json::json_pointer& jsonPtr)
Nan Zhou9a5acea2022-05-17 21:12:43 +0000399{
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000400 aResp->res.jsonValue[jsonPtr]["Id"] = dimmId;
401 aResp->res.jsonValue[jsonPtr]["Name"] = "DIMM Slot";
402 aResp->res.jsonValue[jsonPtr]["Status"]["State"] = "Enabled";
403 aResp->res.jsonValue[jsonPtr]["Status"]["Health"] = "OK";
Nan Zhou9a5acea2022-05-17 21:12:43 +0000404
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200405 const uint16_t* memoryDataWidth = nullptr;
406 const size_t* memorySizeInKB = nullptr;
407 const std::string* partNumber = nullptr;
408 const std::string* serialNumber = nullptr;
409 const std::string* manufacturer = nullptr;
410 const uint16_t* revisionCode = nullptr;
411 const bool* present = nullptr;
412 const uint16_t* memoryTotalWidth = nullptr;
413 const std::string* ecc = nullptr;
414 const std::string* formFactor = nullptr;
415 const std::vector<uint16_t>* allowedSpeedsMT = nullptr;
416 const uint8_t* memoryAttributes = nullptr;
417 const uint16_t* memoryConfiguredSpeedInMhz = nullptr;
418 const std::string* memoryType = nullptr;
419 const std::string* channel = nullptr;
420 const std::string* memoryController = nullptr;
421 const std::string* slot = nullptr;
422 const std::string* socket = nullptr;
423 const std::string* sparePartNumber = nullptr;
424 const std::string* model = nullptr;
425 const std::string* locationCode = nullptr;
426
427 const bool success = sdbusplus::unpackPropertiesNoThrow(
428 dbus_utils::UnpackErrorPrinter(), properties, "MemoryDataWidth",
429 memoryDataWidth, "MemorySizeInKB", memorySizeInKB, "PartNumber",
Nikhil Namjoshi656472d2022-09-13 20:54:44 +0000430 partNumber, "SerialNumber", serialNumber, "Manufacturer", manufacturer,
431 "RevisionCode", revisionCode, "Present", present, "MemoryTotalWidth",
432 memoryTotalWidth, "ECC", ecc, "FormFactor", formFactor,
433 "AllowedSpeedsMT", allowedSpeedsMT, "MemoryAttributes",
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200434 memoryAttributes, "MemoryConfiguredSpeedInMhz",
435 memoryConfiguredSpeedInMhz, "MemoryType", memoryType, "Channel",
436 channel, "MemoryController", memoryController, "Slot", slot, "Socket",
437 socket, "SparePartNumber", sparePartNumber, "Model", model,
438 "LocationCode", locationCode);
439
440 if (!success)
Nan Zhou9a5acea2022-05-17 21:12:43 +0000441 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200442 messages::internalError(aResp->res);
443 return;
444 }
Nan Zhou9a5acea2022-05-17 21:12:43 +0000445
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200446 if (memoryDataWidth != nullptr)
447 {
448 aResp->res.jsonValue[jsonPtr]["DataWidthBits"] = *memoryDataWidth;
449 }
Nan Zhou9a5acea2022-05-17 21:12:43 +0000450
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200451 if (memorySizeInKB != nullptr)
452 {
453 aResp->res.jsonValue[jsonPtr]["CapacityMiB"] = (*memorySizeInKB >> 10);
454 }
Nan Zhou9a5acea2022-05-17 21:12:43 +0000455
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200456 if (partNumber != nullptr)
457 {
458 aResp->res.jsonValue[jsonPtr]["PartNumber"] = *partNumber;
459 }
Nan Zhou9a5acea2022-05-17 21:12:43 +0000460
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200461 if (serialNumber != nullptr)
462 {
463 aResp->res.jsonValue[jsonPtr]["SerialNumber"] = *serialNumber;
464 }
465
466 if (manufacturer != nullptr)
467 {
468 aResp->res.jsonValue[jsonPtr]["Manufacturer"] = *manufacturer;
469 }
470
471 if (revisionCode != nullptr)
472 {
473 aResp->res.jsonValue[jsonPtr]["FirmwareRevision"] =
474 std::to_string(*revisionCode);
475 }
476
477 if (present != nullptr && !*present)
478 {
479 aResp->res.jsonValue[jsonPtr]["Status"]["State"] = "Absent";
480 }
481
482 if (memoryTotalWidth != nullptr)
483 {
484 aResp->res.jsonValue[jsonPtr]["BusWidthBits"] = *memoryTotalWidth;
485 }
486
487 if (ecc != nullptr)
488 {
489 constexpr const std::array<const char*, 4> values{
490 "NoECC", "SingleBitECC", "MultiBitECC", "AddressParity"};
491
492 for (const char* v : values)
Nan Zhou9a5acea2022-05-17 21:12:43 +0000493 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200494 if (ecc->ends_with(v))
Nan Zhou9a5acea2022-05-17 21:12:43 +0000495 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200496 aResp->res.jsonValue[jsonPtr]["ErrorCorrection"] = v;
497 break;
Nan Zhou9a5acea2022-05-17 21:12:43 +0000498 }
Nan Zhou9a5acea2022-05-17 21:12:43 +0000499 }
500 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200501
502 if (formFactor != nullptr)
503 {
504 constexpr const std::array<const char*, 11> values{
505 "RDIMM", "UDIMM", "SO_DIMM", "LRDIMM",
506 "Mini_RDIMM", "Mini_UDIMM", "SO_RDIMM_72b", "SO_UDIMM_72b",
507 "SO_DIMM_16b", "SO_DIMM_32b", "Die"};
508
509 for (const char* v : values)
510 {
511 if (formFactor->ends_with(v))
512 {
513 aResp->res.jsonValue[jsonPtr]["BaseModuleType"] = v;
514 break;
515 }
516 }
517 }
518
519 if (allowedSpeedsMT != nullptr)
520 {
521 nlohmann::json& jValue =
522 aResp->res.jsonValue[jsonPtr]["AllowedSpeedsMHz"];
523 jValue = nlohmann::json::array();
524 for (uint16_t subVal : *allowedSpeedsMT)
525 {
526 jValue.push_back(subVal);
527 }
528 }
529
530 if (memoryAttributes != nullptr)
531 {
532 aResp->res.jsonValue[jsonPtr]["RankCount"] =
533 static_cast<uint64_t>(*memoryAttributes);
534 }
535
536 if (memoryConfiguredSpeedInMhz != nullptr)
537 {
538 aResp->res.jsonValue[jsonPtr]["OperatingSpeedMhz"] =
539 *memoryConfiguredSpeedInMhz;
540 }
541
542 if (memoryType != nullptr)
543 {
544 std::string memoryDeviceType =
545 translateMemoryTypeToRedfish(*memoryType);
546 // Values like "Unknown" or "Other" will return empty
547 // so just leave off
548 if (!memoryDeviceType.empty())
549 {
550 aResp->res.jsonValue[jsonPtr]["MemoryDeviceType"] =
551 memoryDeviceType;
552 }
553 if (memoryType->find("DDR") != std::string::npos)
554 {
555 aResp->res.jsonValue[jsonPtr]["MemoryType"] = "DRAM";
556 }
557 else if (memoryType->ends_with("Logical"))
558 {
559 aResp->res.jsonValue[jsonPtr]["MemoryType"] = "IntelOptane";
560 }
561 }
562
563 if (channel != nullptr)
564 {
565 aResp->res.jsonValue[jsonPtr]["MemoryLocation"]["Channel"] = *channel;
566 }
567
568 if (memoryController != nullptr)
569 {
570 aResp->res.jsonValue[jsonPtr]["MemoryLocation"]["MemoryController"] =
571 *memoryController;
572 }
573
574 if (slot != nullptr)
575 {
576 aResp->res.jsonValue[jsonPtr]["MemoryLocation"]["Slot"] = *slot;
577 }
578
579 if (socket != nullptr)
580 {
581 aResp->res.jsonValue[jsonPtr]["MemoryLocation"]["Socket"] = *socket;
582 }
583
584 if (sparePartNumber != nullptr)
585 {
586 aResp->res.jsonValue[jsonPtr]["SparePartNumber"] = *sparePartNumber;
587 }
588
589 if (model != nullptr)
590 {
591 aResp->res.jsonValue[jsonPtr]["Model"] = *model;
592 }
593
594 if (locationCode != nullptr)
595 {
596 aResp->res
597 .jsonValue[jsonPtr]["Location"]["PartLocation"]["ServiceLabel"] =
598 *locationCode;
599 }
600
601 getPersistentMemoryProperties(aResp, properties, jsonPtr);
Nan Zhou9a5acea2022-05-17 21:12:43 +0000602}
603
zhanghch058d1b46d2021-04-01 11:18:24 +0800604inline void getDimmDataByService(std::shared_ptr<bmcweb::AsyncResp> aResp,
Ed Tanous80789c82020-08-19 09:19:09 -0700605 const std::string& dimmId,
606 const std::string& service,
607 const std::string& objPath)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200608{
James Feist35e257a2020-06-05 13:30:51 -0700609 auto health = std::make_shared<HealthPopulate>(aResp);
610 health->selfPath = objPath;
611 health->populate();
612
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200613 BMCWEB_LOG_DEBUG << "Get available system components.";
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200614 sdbusplus::asio::getAllProperties(
615 *crow::connections::systemBus, service, objPath, "",
Ed Tanousb9d36b42022-02-26 21:42:46 -0800616 [dimmId, aResp{std::move(aResp)}](
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800617 const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800618 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700619 if (ec)
620 {
621 BMCWEB_LOG_DEBUG << "DBUS response error";
622 messages::internalError(aResp->res);
623 return;
624 }
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000625 assembleDimmProperties(dimmId, aResp, properties, ""_json_pointer);
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200626 });
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200627}
628
Nan Zhouef00d7d2022-05-20 21:22:32 +0000629inline void assembleDimmPartitionData(
630 const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000631 const dbus::utility::DBusPropertiesMap& properties,
632 const nlohmann::json::json_pointer& regionPtr)
Nan Zhouef00d7d2022-05-20 21:22:32 +0000633{
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200634 const std::string* memoryClassification = nullptr;
635 const uint64_t* offsetInKiB = nullptr;
636 const std::string* partitionId = nullptr;
637 const bool* passphraseState = nullptr;
638 const uint64_t* sizeInKiB = nullptr;
639
640 const bool success = sdbusplus::unpackPropertiesNoThrow(
641 dbus_utils::UnpackErrorPrinter(), properties, "MemoryClassification",
642 memoryClassification, "OffsetInKiB", offsetInKiB, "PartitionId",
643 partitionId, "PassphraseState", passphraseState, "SizeInKiB",
644 sizeInKiB);
645
646 if (!success)
Nan Zhouef00d7d2022-05-20 21:22:32 +0000647 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200648 messages::internalError(aResp->res);
649 return;
Nan Zhouef00d7d2022-05-20 21:22:32 +0000650 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200651
652 nlohmann::json::object_t partition;
653
654 if (memoryClassification != nullptr)
655 {
656 partition["MemoryClassification"] = *memoryClassification;
657 }
658
659 if (offsetInKiB != nullptr)
660 {
661 partition["OffsetMiB"] = (*offsetInKiB >> 10);
662 }
663
664 if (partitionId != nullptr)
665 {
666 partition["RegionId"] = *partitionId;
667 }
668
669 if (passphraseState != nullptr)
670 {
671 partition["PassphraseEnabled"] = *passphraseState;
672 }
673
674 if (sizeInKiB != nullptr)
675 {
676 partition["SizeMiB"] = (*sizeInKiB >> 10);
677 }
678
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000679 aResp->res.jsonValue[regionPtr].emplace_back(std::move(partition));
Nan Zhouef00d7d2022-05-20 21:22:32 +0000680}
681
zhanghch058d1b46d2021-04-01 11:18:24 +0800682inline void getDimmPartitionData(std::shared_ptr<bmcweb::AsyncResp> aResp,
Ed Tanous23a21a12020-07-25 04:45:05 +0000683 const std::string& service,
684 const std::string& path)
James Feist45094ad2020-04-29 14:02:30 -0700685{
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200686 sdbusplus::asio::getAllProperties(
687 *crow::connections::systemBus, service, path,
688 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition",
James Feist45094ad2020-04-29 14:02:30 -0700689 [aResp{std::move(aResp)}](
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800690 const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800691 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700692 if (ec)
693 {
694 BMCWEB_LOG_DEBUG << "DBUS response error";
695 messages::internalError(aResp->res);
James Feist45094ad2020-04-29 14:02:30 -0700696
Ed Tanous002d39b2022-05-31 08:59:27 -0700697 return;
698 }
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000699 nlohmann::json::json_pointer regionPtr = "/Regions"_json_pointer;
700 assembleDimmPartitionData(aResp, properties, regionPtr);
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200701 }
James Feist45094ad2020-04-29 14:02:30 -0700702
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200703 );
James Feist45094ad2020-04-29 14:02:30 -0700704}
705
zhanghch058d1b46d2021-04-01 11:18:24 +0800706inline void getDimmData(std::shared_ptr<bmcweb::AsyncResp> aResp,
Ed Tanous23a21a12020-07-25 04:45:05 +0000707 const std::string& dimmId)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200708{
709 BMCWEB_LOG_DEBUG << "Get available system dimm resources.";
George Liue99073f2022-12-09 11:06:16 +0800710 constexpr std::array<std::string_view, 2> dimmInterfaces = {
711 "xyz.openbmc_project.Inventory.Item.Dimm",
712 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition"};
713 dbus::utility::getSubTree(
714 "/xyz/openbmc_project/inventory", 0, dimmInterfaces,
Ed Tanous029573d2019-02-01 10:57:49 -0800715 [dimmId, aResp{std::move(aResp)}](
George Liue99073f2022-12-09 11:06:16 +0800716 const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800717 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700718 if (ec)
719 {
720 BMCWEB_LOG_DEBUG << "DBUS response error";
721 messages::internalError(aResp->res);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200722
Ed Tanous002d39b2022-05-31 08:59:27 -0700723 return;
724 }
725 bool found = false;
Nan Zhou76686dc2022-06-17 23:01:51 +0000726 for (const auto& [rawPath, object] : subtree)
Ed Tanous002d39b2022-05-31 08:59:27 -0700727 {
Nan Zhou76686dc2022-06-17 23:01:51 +0000728 sdbusplus::message::object_path path(rawPath);
729 for (const auto& [service, interfaces] : object)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200730 {
Nan Zhou76686dc2022-06-17 23:01:51 +0000731 for (const auto& interface : interfaces)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200732 {
Nan Zhou76686dc2022-06-17 23:01:51 +0000733 if (interface ==
734 "xyz.openbmc_project.Inventory.Item.Dimm" &&
735 path.filename() == dimmId)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200736 {
Nan Zhou76686dc2022-06-17 23:01:51 +0000737 getDimmDataByService(aResp, dimmId, service, rawPath);
738 found = true;
739 }
James Feist45094ad2020-04-29 14:02:30 -0700740
Nan Zhou76686dc2022-06-17 23:01:51 +0000741 // partitions are separate as there can be multiple
742 // per
743 // device, i.e.
744 // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition1
745 // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition2
746 if (interface ==
747 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition" &&
748 path.parent_path().filename() == dimmId)
749 {
750 getDimmPartitionData(aResp, service, rawPath);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200751 }
752 }
753 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700754 }
755 // Object not found
756 if (!found)
757 {
758 messages::resourceNotFound(aResp->res, "Memory", dimmId);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200759 return;
Ed Tanous002d39b2022-05-31 08:59:27 -0700760 }
761 // Set @odata only if object is found
762 aResp->res.jsonValue["@odata.type"] = "#Memory.v1_11_0.Memory";
Willy Tueddfc432022-09-26 16:46:38 +0000763 aResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
764 "redfish", "v1", "Systems", "system", "Memory", dimmId);
Ed Tanous002d39b2022-05-31 08:59:27 -0700765 return;
George Liue99073f2022-12-09 11:06:16 +0800766 });
Ed Tanous271584a2019-07-09 16:24:22 -0700767}
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200768
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700769inline void requestRoutesMemoryCollection(App& app)
Ed Tanous029573d2019-02-01 10:57:49 -0800770{
Ed Tanous029573d2019-02-01 10:57:49 -0800771 /**
772 * Functions triggers appropriate requests on DBus
773 */
Ed Tanous22d268c2022-05-19 09:39:07 -0700774 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Memory/")
Ed Tanoused398212021-06-09 17:05:54 -0700775 .privileges(redfish::privileges::getMemoryCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700776 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700777 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -0700778 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
779 const std::string& systemName) {
Carson Labrado3ba00072022-06-06 19:40:56 +0000780 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -0700781 {
782 return;
783 }
Ed Tanous22d268c2022-05-19 09:39:07 -0700784 if (systemName != "system")
785 {
786 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
787 systemName);
788 return;
789 }
790
Ed Tanous002d39b2022-05-31 08:59:27 -0700791 asyncResp->res.jsonValue["@odata.type"] =
792 "#MemoryCollection.MemoryCollection";
793 asyncResp->res.jsonValue["Name"] = "Memory Module Collection";
794 asyncResp->res.jsonValue["@odata.id"] =
795 "/redfish/v1/Systems/system/Memory";
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200796
George Liu7a1dbc42022-12-07 16:03:22 +0800797 constexpr std::array<std::string_view, 1> interfaces{
798 "xyz.openbmc_project.Inventory.Item.Dimm"};
Ed Tanous002d39b2022-05-31 08:59:27 -0700799 collection_util::getCollectionMembers(
Willy Tuae9031f2022-09-27 05:48:07 +0000800 asyncResp, boost::urls::url("/redfish/v1/Systems/system/Memory"),
George Liu7a1dbc42022-12-07 16:03:22 +0800801 interfaces);
Ed Tanous002d39b2022-05-31 08:59:27 -0700802 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700803}
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200804
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700805inline void requestRoutesMemory(App& app)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200806{
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200807 /**
808 * Functions triggers appropriate requests on DBus
809 */
Ed Tanous22d268c2022-05-19 09:39:07 -0700810 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Memory/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700811 .privileges(redfish::privileges::getMemory)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700812 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700813 [&app](const crow::Request& req,
814 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous22d268c2022-05-19 09:39:07 -0700815 const std::string& systemName, const std::string& dimmId) {
Carson Labrado3ba00072022-06-06 19:40:56 +0000816 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -0700817 {
818 return;
819 }
Ed Tanous22d268c2022-05-19 09:39:07 -0700820 if (systemName != "system")
821 {
822 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
823 systemName);
824 return;
825 }
826
Ed Tanous002d39b2022-05-31 08:59:27 -0700827 getDimmData(asyncResp, dimmId);
828 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700829}
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200830
831} // namespace redfish