blob: 395d6a0743dd216b96edefd27a3dc14de90dbd3f [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
George Liu7a1dbc42022-12-07 16:03:22 +080031#include <array>
32#include <string_view>
33
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +020034namespace redfish
35{
36
Gunnar Mills313efb12020-10-26 16:05:08 -050037inline std::string translateMemoryTypeToRedfish(const std::string& memoryType)
38{
39 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR")
40 {
41 return "DDR";
42 }
43 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR2")
44 {
45 return "DDR2";
46 }
47 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR3")
48 {
49 return "DDR3";
50 }
51 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR4")
52 {
53 return "DDR4";
54 }
55 if (memoryType ==
56 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR4E_SDRAM")
57 {
58 return "DDR4E_SDRAM";
59 }
Mansi Joshi11a2f0f2021-07-19 14:33:27 +053060 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR5")
61 {
62 return "DDR5";
63 }
Gunnar Mills313efb12020-10-26 16:05:08 -050064 if (memoryType ==
65 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.LPDDR4_SDRAM")
66 {
67 return "LPDDR4_SDRAM";
68 }
69 if (memoryType ==
70 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.LPDDR3_SDRAM")
71 {
72 return "LPDDR3_SDRAM";
73 }
74 if (memoryType ==
75 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR2_SDRAM_FB_DIMM")
76 {
77 return "DDR2_SDRAM_FB_DIMM";
78 }
George Liu0fda0f12021-11-16 10:06:17 +080079 if (memoryType ==
80 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR2_SDRAM_FB_DIMM_PROB")
Gunnar Mills313efb12020-10-26 16:05:08 -050081 {
82 return "DDR2_SDRAM_FB_DIMM_PROBE";
83 }
84 if (memoryType ==
85 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR_SGRAM")
86 {
87 return "DDR_SGRAM";
88 }
89 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.ROM")
90 {
91 return "ROM";
92 }
93 if (memoryType ==
94 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.SDRAM")
95 {
96 return "SDRAM";
97 }
98 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.EDO")
99 {
100 return "EDO";
101 }
102 if (memoryType ==
103 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.FastPageMode")
104 {
105 return "FastPageMode";
106 }
107 if (memoryType ==
108 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.PipelinedNibble")
109 {
110 return "PipelinedNibble";
111 }
112 if (memoryType ==
113 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.Logical")
114 {
115 return "Logical";
116 }
117 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.HBM")
118 {
119 return "HBM";
120 }
121 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.HBM2")
122 {
123 return "HBM2";
124 }
Tyson Tuckerbearce34d512022-09-13 16:26:15 -0700125 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.HBM3")
126 {
127 return "HBM3";
128 }
Gunnar Mills313efb12020-10-26 16:05:08 -0500129 // This is values like Other or Unknown
130 // Also D-Bus values:
131 // DRAM
132 // EDRAM
133 // VRAM
134 // SRAM
135 // RAM
136 // FLASH
137 // EEPROM
138 // FEPROM
139 // EPROM
140 // CDRAM
141 // ThreeDRAM
142 // RDRAM
143 // FBD2
144 // LPDDR_SDRAM
145 // LPDDR2_SDRAM
Mansi Joshi11a2f0f2021-07-19 14:33:27 +0530146 // LPDDR5_SDRAM
Gunnar Mills313efb12020-10-26 16:05:08 -0500147 return "";
148}
149
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200150inline void dimmPropToHex(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
151 const char* key, const uint16_t* value,
152 const nlohmann::json::json_pointer& jsonPtr)
James Feistc50e7c62020-07-27 15:39:36 -0700153{
James Feistc50e7c62020-07-27 15:39:36 -0700154 if (value == nullptr)
155 {
James Feistc50e7c62020-07-27 15:39:36 -0700156 return;
157 }
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000158 aResp->res.jsonValue[jsonPtr][key] = "0x" + intToHexString(*value, 4);
James Feistc50e7c62020-07-27 15:39:36 -0700159}
160
zhanghch058d1b46d2021-04-01 11:18:24 +0800161inline void getPersistentMemoryProperties(
162 const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200163 const dbus::utility::DBusPropertiesMap& properties,
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000164 const nlohmann::json::json_pointer& jsonPtr)
James Feistc50e7c62020-07-27 15:39:36 -0700165{
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200166 const uint16_t* moduleManufacturerID = nullptr;
167 const uint16_t* moduleProductID = nullptr;
168 const uint16_t* subsystemVendorID = nullptr;
169 const uint16_t* subsystemDeviceID = nullptr;
170 const uint64_t* volatileRegionSizeLimitInKiB = nullptr;
171 const uint64_t* pmRegionSizeLimitInKiB = nullptr;
172 const uint64_t* volatileSizeInKiB = nullptr;
173 const uint64_t* pmSizeInKiB = nullptr;
174 const uint64_t* cacheSizeInKB = nullptr;
175 const uint64_t* voltaileRegionMaxSizeInKib = nullptr;
176 const uint64_t* pmRegionMaxSizeInKiB = nullptr;
177 const uint64_t* allocationIncrementInKiB = nullptr;
178 const uint64_t* allocationAlignmentInKiB = nullptr;
179 const uint64_t* volatileRegionNumberLimit = nullptr;
180 const uint64_t* pmRegionNumberLimit = nullptr;
181 const uint64_t* spareDeviceCount = nullptr;
182 const bool* isSpareDeviceInUse = nullptr;
183 const bool* isRankSpareEnabled = nullptr;
184 const std::vector<uint32_t>* maxAveragePowerLimitmW = nullptr;
185 const bool* configurationLocked = nullptr;
186 const std::string* allowedMemoryModes = nullptr;
187 const std::string* memoryMedia = nullptr;
188 const bool* configurationLockCapable = nullptr;
189 const bool* dataLockCapable = nullptr;
190 const bool* passphraseCapable = nullptr;
191 const uint64_t* maxPassphraseCount = nullptr;
192 const uint64_t* passphraseLockLimit = nullptr;
James Feistc50e7c62020-07-27 15:39:36 -0700193
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200194 const bool success = sdbusplus::unpackPropertiesNoThrow(
195 dbus_utils::UnpackErrorPrinter(), properties, "ModuleManufacturerID",
196 moduleManufacturerID, "ModuleProductID", moduleProductID,
197 "SubsystemVendorID", subsystemVendorID, "SubsystemDeviceID",
198 subsystemDeviceID, "VolatileRegionSizeLimitInKiB",
199 volatileRegionSizeLimitInKiB, "PmRegionSizeLimitInKiB",
200 pmRegionSizeLimitInKiB, "VolatileSizeInKiB", volatileSizeInKiB,
201 "PmSizeInKiB", pmSizeInKiB, "CacheSizeInKB", cacheSizeInKB,
202 "VoltaileRegionMaxSizeInKib", voltaileRegionMaxSizeInKib,
203 "PmRegionMaxSizeInKiB", pmRegionMaxSizeInKiB,
204 "AllocationIncrementInKiB", allocationIncrementInKiB,
205 "AllocationAlignmentInKiB", allocationAlignmentInKiB,
206 "VolatileRegionNumberLimit", volatileRegionNumberLimit,
207 "PmRegionNumberLimit", pmRegionNumberLimit, "SpareDeviceCount",
208 spareDeviceCount, "IsSpareDeviceInUse", isSpareDeviceInUse,
209 "IsRankSpareEnabled", isRankSpareEnabled, "MaxAveragePowerLimitmW",
210 maxAveragePowerLimitmW, "ConfigurationLocked", configurationLocked,
211 "AllowedMemoryModes", allowedMemoryModes, "MemoryMedia", memoryMedia,
212 "ConfigurationLockCapable", configurationLockCapable, "DataLockCapable",
213 dataLockCapable, "PassphraseCapable", passphraseCapable,
214 "MaxPassphraseCount", maxPassphraseCount, "PassphraseLockLimit",
215 passphraseLockLimit);
216
217 if (!success)
218 {
219 messages::internalError(aResp->res);
220 return;
221 }
222
223 dimmPropToHex(aResp, "ModuleManufacturerID", moduleManufacturerID, jsonPtr);
224 dimmPropToHex(aResp, "ModuleProductID", moduleProductID, jsonPtr);
225 dimmPropToHex(aResp, "MemorySubsystemControllerManufacturerID",
226 subsystemVendorID, jsonPtr);
227 dimmPropToHex(aResp, "MemorySubsystemControllerProductID",
228 subsystemDeviceID, jsonPtr);
229
230 if (volatileRegionSizeLimitInKiB != nullptr)
231 {
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000232 aResp->res.jsonValue[jsonPtr]["VolatileRegionSizeLimitMiB"] =
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200233 (*volatileRegionSizeLimitInKiB) >> 10;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800234 }
James Feistc50e7c62020-07-27 15:39:36 -0700235
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200236 if (pmRegionSizeLimitInKiB != nullptr)
237 {
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000238 aResp->res.jsonValue[jsonPtr]["PersistentRegionSizeLimitMiB"] =
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200239 (*pmRegionSizeLimitInKiB) >> 10;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800240 }
James Feistc50e7c62020-07-27 15:39:36 -0700241
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200242 if (volatileSizeInKiB != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800243 {
James Feistc50e7c62020-07-27 15:39:36 -0700244
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200245 aResp->res.jsonValue[jsonPtr]["VolatileSizeMiB"] =
246 (*volatileSizeInKiB) >> 10;
247 }
248
249 if (pmSizeInKiB != nullptr)
250 {
251 aResp->res.jsonValue[jsonPtr]["NonVolatileSizeMiB"] =
252 (*pmSizeInKiB) >> 10;
253 }
254
255 if (cacheSizeInKB != nullptr)
256 {
257 aResp->res.jsonValue[jsonPtr]["CacheSizeMiB"] = (*cacheSizeInKB >> 10);
258 }
259
260 if (voltaileRegionMaxSizeInKib != nullptr)
261 {
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000262 aResp->res.jsonValue[jsonPtr]["VolatileRegionSizeMaxMiB"] =
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200263 (*voltaileRegionMaxSizeInKib) >> 10;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800264 }
James Feistc50e7c62020-07-27 15:39:36 -0700265
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200266 if (pmRegionMaxSizeInKiB != nullptr)
267 {
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000268 aResp->res.jsonValue[jsonPtr]["PersistentRegionSizeMaxMiB"] =
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200269 (*pmRegionMaxSizeInKiB) >> 10;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800270 }
James Feistc50e7c62020-07-27 15:39:36 -0700271
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200272 if (allocationIncrementInKiB != nullptr)
273 {
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000274 aResp->res.jsonValue[jsonPtr]["AllocationIncrementMiB"] =
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200275 (*allocationIncrementInKiB) >> 10;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800276 }
James Feistc50e7c62020-07-27 15:39:36 -0700277
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200278 if (allocationAlignmentInKiB != nullptr)
279 {
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000280 aResp->res.jsonValue[jsonPtr]["AllocationAlignmentMiB"] =
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200281 (*allocationAlignmentInKiB) >> 10;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800282 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200283
284 if (volatileRegionNumberLimit != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800285 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200286 aResp->res.jsonValue[jsonPtr]["VolatileRegionNumberLimit"] =
287 *volatileRegionNumberLimit;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800288 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200289
290 if (pmRegionNumberLimit != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800291 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200292 aResp->res.jsonValue[jsonPtr]["PersistentRegionNumberLimit"] =
293 *pmRegionNumberLimit;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800294 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200295
296 if (spareDeviceCount != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800297 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200298 aResp->res.jsonValue[jsonPtr]["SpareDeviceCount"] = *spareDeviceCount;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800299 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200300
301 if (isSpareDeviceInUse != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800302 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200303 aResp->res.jsonValue[jsonPtr]["IsSpareDeviceEnabled"] =
304 *isSpareDeviceInUse;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800305 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200306
307 if (isRankSpareEnabled != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800308 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200309 aResp->res.jsonValue[jsonPtr]["IsRankSpareEnabled"] =
310 *isRankSpareEnabled;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800311 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200312
313 if (maxAveragePowerLimitmW != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800314 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200315 aResp->res.jsonValue[jsonPtr]["MaxTDPMilliWatts"] =
316 *maxAveragePowerLimitmW;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800317 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200318
319 if (configurationLocked != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800320 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200321 aResp->res.jsonValue[jsonPtr]["ConfigurationLocked"] =
322 *configurationLocked;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800323 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200324
325 if (allowedMemoryModes != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800326 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800327 constexpr const std::array<const char*, 3> values{"Volatile", "PMEM",
328 "Block"};
James Feistc50e7c62020-07-27 15:39:36 -0700329
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800330 for (const char* v : values)
331 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200332 if (allowedMemoryModes->ends_with(v))
James Feistc50e7c62020-07-27 15:39:36 -0700333 {
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000334 aResp->res.jsonValue[jsonPtr]["OperatingMemoryModes"].push_back(
335 v);
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800336 break;
James Feistc50e7c62020-07-27 15:39:36 -0700337 }
338 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800339 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200340
341 if (memoryMedia != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800342 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800343 constexpr const std::array<const char*, 3> values{"DRAM", "NAND",
344 "Intel3DXPoint"};
James Feistc50e7c62020-07-27 15:39:36 -0700345
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800346 for (const char* v : values)
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700347 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200348 if (memoryMedia->ends_with(v))
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700349 {
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000350 aResp->res.jsonValue[jsonPtr]["MemoryMedia"].push_back(v);
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800351 break;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700352 }
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700353 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800354 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200355
356 if (configurationLockCapable != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800357 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200358 aResp->res.jsonValue[jsonPtr]["SecurityCapabilities"]
359 ["ConfigurationLockCapable"] =
360 *configurationLockCapable;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800361 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200362
363 if (dataLockCapable != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800364 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200365 aResp->res
366 .jsonValue[jsonPtr]["SecurityCapabilities"]["DataLockCapable"] =
367 *dataLockCapable;
368 }
369
370 if (passphraseCapable != nullptr)
371 {
372 aResp->res
373 .jsonValue[jsonPtr]["SecurityCapabilities"]["PassphraseCapable"] =
374 *passphraseCapable;
375 }
376
377 if (maxPassphraseCount != nullptr)
378 {
379 aResp->res
380 .jsonValue[jsonPtr]["SecurityCapabilities"]["MaxPassphraseCount"] =
381 *maxPassphraseCount;
382 }
383
384 if (passphraseLockLimit != nullptr)
385 {
386 aResp->res
387 .jsonValue[jsonPtr]["SecurityCapabilities"]["PassphraseLockLimit"] =
388 *passphraseLockLimit;
James Feistc50e7c62020-07-27 15:39:36 -0700389 }
390}
391
Nan Zhou9a5acea2022-05-17 21:12:43 +0000392inline void
393 assembleDimmProperties(std::string_view dimmId,
394 const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000395 const dbus::utility::DBusPropertiesMap& properties,
396 const nlohmann::json::json_pointer& jsonPtr)
Nan Zhou9a5acea2022-05-17 21:12:43 +0000397{
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000398 aResp->res.jsonValue[jsonPtr]["Id"] = dimmId;
399 aResp->res.jsonValue[jsonPtr]["Name"] = "DIMM Slot";
400 aResp->res.jsonValue[jsonPtr]["Status"]["State"] = "Enabled";
401 aResp->res.jsonValue[jsonPtr]["Status"]["Health"] = "OK";
Nan Zhou9a5acea2022-05-17 21:12:43 +0000402
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200403 const uint16_t* memoryDataWidth = nullptr;
404 const size_t* memorySizeInKB = nullptr;
405 const std::string* partNumber = nullptr;
406 const std::string* serialNumber = nullptr;
407 const std::string* manufacturer = nullptr;
408 const uint16_t* revisionCode = nullptr;
409 const bool* present = nullptr;
410 const uint16_t* memoryTotalWidth = nullptr;
411 const std::string* ecc = nullptr;
412 const std::string* formFactor = nullptr;
413 const std::vector<uint16_t>* allowedSpeedsMT = nullptr;
414 const uint8_t* memoryAttributes = nullptr;
415 const uint16_t* memoryConfiguredSpeedInMhz = nullptr;
416 const std::string* memoryType = nullptr;
417 const std::string* channel = nullptr;
418 const std::string* memoryController = nullptr;
419 const std::string* slot = nullptr;
420 const std::string* socket = nullptr;
421 const std::string* sparePartNumber = nullptr;
422 const std::string* model = nullptr;
423 const std::string* locationCode = nullptr;
424
425 const bool success = sdbusplus::unpackPropertiesNoThrow(
426 dbus_utils::UnpackErrorPrinter(), properties, "MemoryDataWidth",
427 memoryDataWidth, "MemorySizeInKB", memorySizeInKB, "PartNumber",
Nikhil Namjoshi656472d2022-09-13 20:54:44 +0000428 partNumber, "SerialNumber", serialNumber, "Manufacturer", manufacturer,
429 "RevisionCode", revisionCode, "Present", present, "MemoryTotalWidth",
430 memoryTotalWidth, "ECC", ecc, "FormFactor", formFactor,
431 "AllowedSpeedsMT", allowedSpeedsMT, "MemoryAttributes",
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200432 memoryAttributes, "MemoryConfiguredSpeedInMhz",
433 memoryConfiguredSpeedInMhz, "MemoryType", memoryType, "Channel",
434 channel, "MemoryController", memoryController, "Slot", slot, "Socket",
435 socket, "SparePartNumber", sparePartNumber, "Model", model,
436 "LocationCode", locationCode);
437
438 if (!success)
Nan Zhou9a5acea2022-05-17 21:12:43 +0000439 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200440 messages::internalError(aResp->res);
441 return;
442 }
Nan Zhou9a5acea2022-05-17 21:12:43 +0000443
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200444 if (memoryDataWidth != nullptr)
445 {
446 aResp->res.jsonValue[jsonPtr]["DataWidthBits"] = *memoryDataWidth;
447 }
Nan Zhou9a5acea2022-05-17 21:12:43 +0000448
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200449 if (memorySizeInKB != nullptr)
450 {
451 aResp->res.jsonValue[jsonPtr]["CapacityMiB"] = (*memorySizeInKB >> 10);
452 }
Nan Zhou9a5acea2022-05-17 21:12:43 +0000453
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200454 if (partNumber != nullptr)
455 {
456 aResp->res.jsonValue[jsonPtr]["PartNumber"] = *partNumber;
457 }
Nan Zhou9a5acea2022-05-17 21:12:43 +0000458
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200459 if (serialNumber != nullptr)
460 {
461 aResp->res.jsonValue[jsonPtr]["SerialNumber"] = *serialNumber;
462 }
463
464 if (manufacturer != nullptr)
465 {
466 aResp->res.jsonValue[jsonPtr]["Manufacturer"] = *manufacturer;
467 }
468
469 if (revisionCode != nullptr)
470 {
471 aResp->res.jsonValue[jsonPtr]["FirmwareRevision"] =
472 std::to_string(*revisionCode);
473 }
474
475 if (present != nullptr && !*present)
476 {
477 aResp->res.jsonValue[jsonPtr]["Status"]["State"] = "Absent";
478 }
479
480 if (memoryTotalWidth != nullptr)
481 {
482 aResp->res.jsonValue[jsonPtr]["BusWidthBits"] = *memoryTotalWidth;
483 }
484
485 if (ecc != nullptr)
486 {
487 constexpr const std::array<const char*, 4> values{
488 "NoECC", "SingleBitECC", "MultiBitECC", "AddressParity"};
489
490 for (const char* v : values)
Nan Zhou9a5acea2022-05-17 21:12:43 +0000491 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200492 if (ecc->ends_with(v))
Nan Zhou9a5acea2022-05-17 21:12:43 +0000493 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200494 aResp->res.jsonValue[jsonPtr]["ErrorCorrection"] = v;
495 break;
Nan Zhou9a5acea2022-05-17 21:12:43 +0000496 }
Nan Zhou9a5acea2022-05-17 21:12:43 +0000497 }
498 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200499
500 if (formFactor != nullptr)
501 {
502 constexpr const std::array<const char*, 11> values{
503 "RDIMM", "UDIMM", "SO_DIMM", "LRDIMM",
504 "Mini_RDIMM", "Mini_UDIMM", "SO_RDIMM_72b", "SO_UDIMM_72b",
505 "SO_DIMM_16b", "SO_DIMM_32b", "Die"};
506
507 for (const char* v : values)
508 {
509 if (formFactor->ends_with(v))
510 {
511 aResp->res.jsonValue[jsonPtr]["BaseModuleType"] = v;
512 break;
513 }
514 }
515 }
516
517 if (allowedSpeedsMT != nullptr)
518 {
519 nlohmann::json& jValue =
520 aResp->res.jsonValue[jsonPtr]["AllowedSpeedsMHz"];
521 jValue = nlohmann::json::array();
522 for (uint16_t subVal : *allowedSpeedsMT)
523 {
524 jValue.push_back(subVal);
525 }
526 }
527
528 if (memoryAttributes != nullptr)
529 {
530 aResp->res.jsonValue[jsonPtr]["RankCount"] =
531 static_cast<uint64_t>(*memoryAttributes);
532 }
533
534 if (memoryConfiguredSpeedInMhz != nullptr)
535 {
536 aResp->res.jsonValue[jsonPtr]["OperatingSpeedMhz"] =
537 *memoryConfiguredSpeedInMhz;
538 }
539
540 if (memoryType != nullptr)
541 {
542 std::string memoryDeviceType =
543 translateMemoryTypeToRedfish(*memoryType);
544 // Values like "Unknown" or "Other" will return empty
545 // so just leave off
546 if (!memoryDeviceType.empty())
547 {
548 aResp->res.jsonValue[jsonPtr]["MemoryDeviceType"] =
549 memoryDeviceType;
550 }
551 if (memoryType->find("DDR") != std::string::npos)
552 {
553 aResp->res.jsonValue[jsonPtr]["MemoryType"] = "DRAM";
554 }
555 else if (memoryType->ends_with("Logical"))
556 {
557 aResp->res.jsonValue[jsonPtr]["MemoryType"] = "IntelOptane";
558 }
559 }
560
561 if (channel != nullptr)
562 {
563 aResp->res.jsonValue[jsonPtr]["MemoryLocation"]["Channel"] = *channel;
564 }
565
566 if (memoryController != nullptr)
567 {
568 aResp->res.jsonValue[jsonPtr]["MemoryLocation"]["MemoryController"] =
569 *memoryController;
570 }
571
572 if (slot != nullptr)
573 {
574 aResp->res.jsonValue[jsonPtr]["MemoryLocation"]["Slot"] = *slot;
575 }
576
577 if (socket != nullptr)
578 {
579 aResp->res.jsonValue[jsonPtr]["MemoryLocation"]["Socket"] = *socket;
580 }
581
582 if (sparePartNumber != nullptr)
583 {
584 aResp->res.jsonValue[jsonPtr]["SparePartNumber"] = *sparePartNumber;
585 }
586
587 if (model != nullptr)
588 {
589 aResp->res.jsonValue[jsonPtr]["Model"] = *model;
590 }
591
592 if (locationCode != nullptr)
593 {
594 aResp->res
595 .jsonValue[jsonPtr]["Location"]["PartLocation"]["ServiceLabel"] =
596 *locationCode;
597 }
598
599 getPersistentMemoryProperties(aResp, properties, jsonPtr);
Nan Zhou9a5acea2022-05-17 21:12:43 +0000600}
601
zhanghch058d1b46d2021-04-01 11:18:24 +0800602inline void getDimmDataByService(std::shared_ptr<bmcweb::AsyncResp> aResp,
Ed Tanous80789c82020-08-19 09:19:09 -0700603 const std::string& dimmId,
604 const std::string& service,
605 const std::string& objPath)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200606{
James Feist35e257a2020-06-05 13:30:51 -0700607 auto health = std::make_shared<HealthPopulate>(aResp);
608 health->selfPath = objPath;
609 health->populate();
610
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200611 BMCWEB_LOG_DEBUG << "Get available system components.";
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200612 sdbusplus::asio::getAllProperties(
613 *crow::connections::systemBus, service, objPath, "",
Ed Tanousb9d36b42022-02-26 21:42:46 -0800614 [dimmId, aResp{std::move(aResp)}](
615 const boost::system::error_code ec,
616 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700617 if (ec)
618 {
619 BMCWEB_LOG_DEBUG << "DBUS response error";
620 messages::internalError(aResp->res);
621 return;
622 }
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000623 assembleDimmProperties(dimmId, aResp, properties, ""_json_pointer);
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200624 });
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200625}
626
Nan Zhouef00d7d2022-05-20 21:22:32 +0000627inline void assembleDimmPartitionData(
628 const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000629 const dbus::utility::DBusPropertiesMap& properties,
630 const nlohmann::json::json_pointer& regionPtr)
Nan Zhouef00d7d2022-05-20 21:22:32 +0000631{
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200632 const std::string* memoryClassification = nullptr;
633 const uint64_t* offsetInKiB = nullptr;
634 const std::string* partitionId = nullptr;
635 const bool* passphraseState = nullptr;
636 const uint64_t* sizeInKiB = nullptr;
637
638 const bool success = sdbusplus::unpackPropertiesNoThrow(
639 dbus_utils::UnpackErrorPrinter(), properties, "MemoryClassification",
640 memoryClassification, "OffsetInKiB", offsetInKiB, "PartitionId",
641 partitionId, "PassphraseState", passphraseState, "SizeInKiB",
642 sizeInKiB);
643
644 if (!success)
Nan Zhouef00d7d2022-05-20 21:22:32 +0000645 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200646 messages::internalError(aResp->res);
647 return;
Nan Zhouef00d7d2022-05-20 21:22:32 +0000648 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200649
650 nlohmann::json::object_t partition;
651
652 if (memoryClassification != nullptr)
653 {
654 partition["MemoryClassification"] = *memoryClassification;
655 }
656
657 if (offsetInKiB != nullptr)
658 {
659 partition["OffsetMiB"] = (*offsetInKiB >> 10);
660 }
661
662 if (partitionId != nullptr)
663 {
664 partition["RegionId"] = *partitionId;
665 }
666
667 if (passphraseState != nullptr)
668 {
669 partition["PassphraseEnabled"] = *passphraseState;
670 }
671
672 if (sizeInKiB != nullptr)
673 {
674 partition["SizeMiB"] = (*sizeInKiB >> 10);
675 }
676
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000677 aResp->res.jsonValue[regionPtr].emplace_back(std::move(partition));
Nan Zhouef00d7d2022-05-20 21:22:32 +0000678}
679
zhanghch058d1b46d2021-04-01 11:18:24 +0800680inline void getDimmPartitionData(std::shared_ptr<bmcweb::AsyncResp> aResp,
Ed Tanous23a21a12020-07-25 04:45:05 +0000681 const std::string& service,
682 const std::string& path)
James Feist45094ad2020-04-29 14:02:30 -0700683{
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200684 sdbusplus::asio::getAllProperties(
685 *crow::connections::systemBus, service, path,
686 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition",
James Feist45094ad2020-04-29 14:02:30 -0700687 [aResp{std::move(aResp)}](
688 const boost::system::error_code ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800689 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700690 if (ec)
691 {
692 BMCWEB_LOG_DEBUG << "DBUS response error";
693 messages::internalError(aResp->res);
James Feist45094ad2020-04-29 14:02:30 -0700694
Ed Tanous002d39b2022-05-31 08:59:27 -0700695 return;
696 }
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000697 nlohmann::json::json_pointer regionPtr = "/Regions"_json_pointer;
698 assembleDimmPartitionData(aResp, properties, regionPtr);
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200699 }
James Feist45094ad2020-04-29 14:02:30 -0700700
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200701 );
James Feist45094ad2020-04-29 14:02:30 -0700702}
703
zhanghch058d1b46d2021-04-01 11:18:24 +0800704inline void getDimmData(std::shared_ptr<bmcweb::AsyncResp> aResp,
Ed Tanous23a21a12020-07-25 04:45:05 +0000705 const std::string& dimmId)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200706{
707 BMCWEB_LOG_DEBUG << "Get available system dimm resources.";
708 crow::connections::systemBus->async_method_call(
Ed Tanous029573d2019-02-01 10:57:49 -0800709 [dimmId, aResp{std::move(aResp)}](
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200710 const boost::system::error_code ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800711 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700712 if (ec)
713 {
714 BMCWEB_LOG_DEBUG << "DBUS response error";
715 messages::internalError(aResp->res);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200716
Ed Tanous002d39b2022-05-31 08:59:27 -0700717 return;
718 }
719 bool found = false;
Nan Zhou76686dc2022-06-17 23:01:51 +0000720 for (const auto& [rawPath, object] : subtree)
Ed Tanous002d39b2022-05-31 08:59:27 -0700721 {
Nan Zhou76686dc2022-06-17 23:01:51 +0000722 sdbusplus::message::object_path path(rawPath);
723 for (const auto& [service, interfaces] : object)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200724 {
Nan Zhou76686dc2022-06-17 23:01:51 +0000725 for (const auto& interface : interfaces)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200726 {
Nan Zhou76686dc2022-06-17 23:01:51 +0000727 if (interface ==
728 "xyz.openbmc_project.Inventory.Item.Dimm" &&
729 path.filename() == dimmId)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200730 {
Nan Zhou76686dc2022-06-17 23:01:51 +0000731 getDimmDataByService(aResp, dimmId, service, rawPath);
732 found = true;
733 }
James Feist45094ad2020-04-29 14:02:30 -0700734
Nan Zhou76686dc2022-06-17 23:01:51 +0000735 // partitions are separate as there can be multiple
736 // per
737 // device, i.e.
738 // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition1
739 // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition2
740 if (interface ==
741 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition" &&
742 path.parent_path().filename() == dimmId)
743 {
744 getDimmPartitionData(aResp, service, rawPath);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200745 }
746 }
747 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700748 }
749 // Object not found
750 if (!found)
751 {
752 messages::resourceNotFound(aResp->res, "Memory", dimmId);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200753 return;
Ed Tanous002d39b2022-05-31 08:59:27 -0700754 }
755 // Set @odata only if object is found
756 aResp->res.jsonValue["@odata.type"] = "#Memory.v1_11_0.Memory";
757 aResp->res.jsonValue["@odata.id"] =
758 "/redfish/v1/Systems/system/Memory/" + dimmId;
759 return;
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200760 },
761 "xyz.openbmc_project.ObjectMapper",
762 "/xyz/openbmc_project/object_mapper",
763 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous271584a2019-07-09 16:24:22 -0700764 "/xyz/openbmc_project/inventory", 0,
James Feist45094ad2020-04-29 14:02:30 -0700765 std::array<const char*, 2>{
766 "xyz.openbmc_project.Inventory.Item.Dimm",
767 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition"});
Ed Tanous271584a2019-07-09 16:24:22 -0700768}
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200769
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700770inline void requestRoutesMemoryCollection(App& app)
Ed Tanous029573d2019-02-01 10:57:49 -0800771{
Ed Tanous029573d2019-02-01 10:57:49 -0800772 /**
773 * Functions triggers appropriate requests on DBus
774 */
Ed Tanous22d268c2022-05-19 09:39:07 -0700775 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Memory/")
Ed Tanoused398212021-06-09 17:05:54 -0700776 .privileges(redfish::privileges::getMemoryCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700777 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700778 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -0700779 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
780 const std::string& systemName) {
Carson Labrado3ba00072022-06-06 19:40:56 +0000781 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -0700782 {
783 return;
784 }
Ed Tanous22d268c2022-05-19 09:39:07 -0700785 if (systemName != "system")
786 {
787 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
788 systemName);
789 return;
790 }
791
Ed Tanous002d39b2022-05-31 08:59:27 -0700792 asyncResp->res.jsonValue["@odata.type"] =
793 "#MemoryCollection.MemoryCollection";
794 asyncResp->res.jsonValue["Name"] = "Memory Module Collection";
795 asyncResp->res.jsonValue["@odata.id"] =
796 "/redfish/v1/Systems/system/Memory";
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200797
George Liu7a1dbc42022-12-07 16:03:22 +0800798 constexpr std::array<std::string_view, 1> interfaces{
799 "xyz.openbmc_project.Inventory.Item.Dimm"};
Ed Tanous002d39b2022-05-31 08:59:27 -0700800 collection_util::getCollectionMembers(
Willy Tuae9031f2022-09-27 05:48:07 +0000801 asyncResp, boost::urls::url("/redfish/v1/Systems/system/Memory"),
George Liu7a1dbc42022-12-07 16:03:22 +0800802 interfaces);
Ed Tanous002d39b2022-05-31 08:59:27 -0700803 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700804}
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200805
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700806inline void requestRoutesMemory(App& app)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200807{
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200808 /**
809 * Functions triggers appropriate requests on DBus
810 */
Ed Tanous22d268c2022-05-19 09:39:07 -0700811 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Memory/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700812 .privileges(redfish::privileges::getMemory)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700813 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700814 [&app](const crow::Request& req,
815 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous22d268c2022-05-19 09:39:07 -0700816 const std::string& systemName, const std::string& dimmId) {
Carson Labrado3ba00072022-06-06 19:40:56 +0000817 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -0700818 {
819 return;
820 }
Ed Tanous22d268c2022-05-19 09:39:07 -0700821 if (systemName != "system")
822 {
823 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
824 systemName);
825 return;
826 }
827
Ed Tanous002d39b2022-05-31 08:59:27 -0700828 getDimmData(asyncResp, dimmId);
829 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700830}
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200831
832} // namespace redfish