blob: 79ccdac1fac7d43b1434208f2b2862fc75bdd2a0 [file] [log] [blame]
Ed Tanous40e9b922024-09-10 13:50:16 -07001// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright OpenBMC Authors
3// SPDX-FileCopyrightText: Copyright 2018 Intel Corporation
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02004#pragma once
5
Willy Tu13451e32023-05-24 16:08:18 -07006#include "bmcweb_config.h"
7
Ed Tanous3ccb3ad2023-01-13 17:40:03 -08008#include "app.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -08009#include "async_resp.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080010#include "dbus_utility.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -080011#include "error_messages.hpp"
Ed Tanous539d8c62024-06-19 14:38:27 -070012#include "generated/enums/memory.hpp"
13#include "generated/enums/resource.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -080014#include "http_request.hpp"
George Liu69800112020-10-10 11:41:08 +080015#include "led.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -080016#include "logging.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080017#include "query.hpp"
18#include "registries/privilege_registry.hpp"
19#include "utils/collection.hpp"
20#include "utils/dbus_utils.hpp"
21#include "utils/hex_utils.hpp"
George Liu69800112020-10-10 11:41:08 +080022#include "utils/json_utils.hpp"
23
24#include <asm-generic/errno.h>
James Feist35e257a2020-06-05 13:30:51 -070025
Ed Tanousd7857202025-01-28 15:32:26 -080026#include <boost/beast/http/verb.hpp>
George Liue99073f2022-12-09 11:06:16 +080027#include <boost/system/error_code.hpp>
Ed Tanousef4c65b2023-04-24 15:28:50 -070028#include <boost/url/format.hpp>
Nan Zhoud7f04fd2022-05-01 01:11:07 +000029#include <nlohmann/json.hpp>
Ed Tanousd7857202025-01-28 15:32:26 -080030#include <sdbusplus/message/native_types.hpp>
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +020031#include <sdbusplus/unpack_properties.hpp>
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +020032
George Liu7a1dbc42022-12-07 16:03:22 +080033#include <array>
Ed Tanousd7857202025-01-28 15:32:26 -080034#include <cstddef>
35#include <cstdint>
George Liu69800112020-10-10 11:41:08 +080036#include <functional>
Ed Tanousd7857202025-01-28 15:32:26 -080037#include <memory>
George Liu69800112020-10-10 11:41:08 +080038#include <optional>
Ed Tanousd7857202025-01-28 15:32:26 -080039#include <string>
George Liu7a1dbc42022-12-07 16:03:22 +080040#include <string_view>
Ed Tanousd7857202025-01-28 15:32:26 -080041#include <utility>
42#include <vector>
George Liu7a1dbc42022-12-07 16:03:22 +080043
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +020044namespace redfish
45{
46
Gunnar Mills313efb12020-10-26 16:05:08 -050047inline std::string translateMemoryTypeToRedfish(const std::string& memoryType)
48{
49 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR")
50 {
51 return "DDR";
52 }
53 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR2")
54 {
55 return "DDR2";
56 }
57 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR3")
58 {
59 return "DDR3";
60 }
61 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR4")
62 {
63 return "DDR4";
64 }
65 if (memoryType ==
66 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR4E_SDRAM")
67 {
68 return "DDR4E_SDRAM";
69 }
Mansi Joshi11a2f0f2021-07-19 14:33:27 +053070 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR5")
71 {
72 return "DDR5";
73 }
Gunnar Mills313efb12020-10-26 16:05:08 -050074 if (memoryType ==
75 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.LPDDR4_SDRAM")
76 {
77 return "LPDDR4_SDRAM";
78 }
79 if (memoryType ==
80 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.LPDDR3_SDRAM")
81 {
82 return "LPDDR3_SDRAM";
83 }
84 if (memoryType ==
85 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR2_SDRAM_FB_DIMM")
86 {
87 return "DDR2_SDRAM_FB_DIMM";
88 }
George Liu0fda0f12021-11-16 10:06:17 +080089 if (memoryType ==
90 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR2_SDRAM_FB_DIMM_PROB")
Gunnar Mills313efb12020-10-26 16:05:08 -050091 {
92 return "DDR2_SDRAM_FB_DIMM_PROBE";
93 }
94 if (memoryType ==
95 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR_SGRAM")
96 {
97 return "DDR_SGRAM";
98 }
99 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.ROM")
100 {
101 return "ROM";
102 }
103 if (memoryType ==
104 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.SDRAM")
105 {
106 return "SDRAM";
107 }
108 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.EDO")
109 {
110 return "EDO";
111 }
112 if (memoryType ==
113 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.FastPageMode")
114 {
115 return "FastPageMode";
116 }
117 if (memoryType ==
118 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.PipelinedNibble")
119 {
120 return "PipelinedNibble";
121 }
122 if (memoryType ==
123 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.Logical")
124 {
125 return "Logical";
126 }
127 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.HBM")
128 {
129 return "HBM";
130 }
131 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.HBM2")
132 {
133 return "HBM2";
134 }
Tyson Tuckerbearce34d512022-09-13 16:26:15 -0700135 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.HBM3")
136 {
137 return "HBM3";
138 }
Gunnar Mills313efb12020-10-26 16:05:08 -0500139 // This is values like Other or Unknown
140 // Also D-Bus values:
141 // DRAM
142 // EDRAM
143 // VRAM
144 // SRAM
145 // RAM
146 // FLASH
147 // EEPROM
148 // FEPROM
149 // EPROM
150 // CDRAM
151 // ThreeDRAM
152 // RDRAM
153 // FBD2
154 // LPDDR_SDRAM
155 // LPDDR2_SDRAM
Mansi Joshi11a2f0f2021-07-19 14:33:27 +0530156 // LPDDR5_SDRAM
Gunnar Mills313efb12020-10-26 16:05:08 -0500157 return "";
158}
159
Ed Tanousac106bf2023-06-07 09:24:59 -0700160inline void dimmPropToHex(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200161 const char* key, const uint16_t* value,
162 const nlohmann::json::json_pointer& jsonPtr)
James Feistc50e7c62020-07-27 15:39:36 -0700163{
James Feistc50e7c62020-07-27 15:39:36 -0700164 if (value == nullptr)
165 {
James Feistc50e7c62020-07-27 15:39:36 -0700166 return;
167 }
Ed Tanousac106bf2023-06-07 09:24:59 -0700168 asyncResp->res.jsonValue[jsonPtr][key] = "0x" + intToHexString(*value, 4);
James Feistc50e7c62020-07-27 15:39:36 -0700169}
170
zhanghch058d1b46d2021-04-01 11:18:24 +0800171inline void getPersistentMemoryProperties(
Ed Tanousac106bf2023-06-07 09:24:59 -0700172 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200173 const dbus::utility::DBusPropertiesMap& properties,
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000174 const nlohmann::json::json_pointer& jsonPtr)
James Feistc50e7c62020-07-27 15:39:36 -0700175{
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200176 const uint16_t* moduleManufacturerID = nullptr;
177 const uint16_t* moduleProductID = nullptr;
178 const uint16_t* subsystemVendorID = nullptr;
179 const uint16_t* subsystemDeviceID = nullptr;
180 const uint64_t* volatileRegionSizeLimitInKiB = nullptr;
181 const uint64_t* pmRegionSizeLimitInKiB = nullptr;
182 const uint64_t* volatileSizeInKiB = nullptr;
183 const uint64_t* pmSizeInKiB = nullptr;
184 const uint64_t* cacheSizeInKB = nullptr;
185 const uint64_t* voltaileRegionMaxSizeInKib = nullptr;
186 const uint64_t* pmRegionMaxSizeInKiB = nullptr;
187 const uint64_t* allocationIncrementInKiB = nullptr;
188 const uint64_t* allocationAlignmentInKiB = nullptr;
189 const uint64_t* volatileRegionNumberLimit = nullptr;
190 const uint64_t* pmRegionNumberLimit = nullptr;
191 const uint64_t* spareDeviceCount = nullptr;
192 const bool* isSpareDeviceInUse = nullptr;
193 const bool* isRankSpareEnabled = nullptr;
194 const std::vector<uint32_t>* maxAveragePowerLimitmW = nullptr;
195 const bool* configurationLocked = nullptr;
196 const std::string* allowedMemoryModes = nullptr;
197 const std::string* memoryMedia = nullptr;
198 const bool* configurationLockCapable = nullptr;
199 const bool* dataLockCapable = nullptr;
200 const bool* passphraseCapable = nullptr;
201 const uint64_t* maxPassphraseCount = nullptr;
202 const uint64_t* passphraseLockLimit = nullptr;
James Feistc50e7c62020-07-27 15:39:36 -0700203
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200204 const bool success = sdbusplus::unpackPropertiesNoThrow(
205 dbus_utils::UnpackErrorPrinter(), properties, "ModuleManufacturerID",
206 moduleManufacturerID, "ModuleProductID", moduleProductID,
207 "SubsystemVendorID", subsystemVendorID, "SubsystemDeviceID",
208 subsystemDeviceID, "VolatileRegionSizeLimitInKiB",
209 volatileRegionSizeLimitInKiB, "PmRegionSizeLimitInKiB",
210 pmRegionSizeLimitInKiB, "VolatileSizeInKiB", volatileSizeInKiB,
211 "PmSizeInKiB", pmSizeInKiB, "CacheSizeInKB", cacheSizeInKB,
212 "VoltaileRegionMaxSizeInKib", voltaileRegionMaxSizeInKib,
213 "PmRegionMaxSizeInKiB", pmRegionMaxSizeInKiB,
214 "AllocationIncrementInKiB", allocationIncrementInKiB,
215 "AllocationAlignmentInKiB", allocationAlignmentInKiB,
216 "VolatileRegionNumberLimit", volatileRegionNumberLimit,
217 "PmRegionNumberLimit", pmRegionNumberLimit, "SpareDeviceCount",
218 spareDeviceCount, "IsSpareDeviceInUse", isSpareDeviceInUse,
219 "IsRankSpareEnabled", isRankSpareEnabled, "MaxAveragePowerLimitmW",
220 maxAveragePowerLimitmW, "ConfigurationLocked", configurationLocked,
221 "AllowedMemoryModes", allowedMemoryModes, "MemoryMedia", memoryMedia,
222 "ConfigurationLockCapable", configurationLockCapable, "DataLockCapable",
223 dataLockCapable, "PassphraseCapable", passphraseCapable,
224 "MaxPassphraseCount", maxPassphraseCount, "PassphraseLockLimit",
225 passphraseLockLimit);
226
227 if (!success)
228 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700229 messages::internalError(asyncResp->res);
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200230 return;
231 }
232
Ed Tanousac106bf2023-06-07 09:24:59 -0700233 dimmPropToHex(asyncResp, "ModuleManufacturerID", moduleManufacturerID,
234 jsonPtr);
235 dimmPropToHex(asyncResp, "ModuleProductID", moduleProductID, jsonPtr);
236 dimmPropToHex(asyncResp, "MemorySubsystemControllerManufacturerID",
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200237 subsystemVendorID, jsonPtr);
Ed Tanousac106bf2023-06-07 09:24:59 -0700238 dimmPropToHex(asyncResp, "MemorySubsystemControllerProductID",
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200239 subsystemDeviceID, jsonPtr);
240
241 if (volatileRegionSizeLimitInKiB != nullptr)
242 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700243 asyncResp->res.jsonValue[jsonPtr]["VolatileRegionSizeLimitMiB"] =
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200244 (*volatileRegionSizeLimitInKiB) >> 10;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800245 }
James Feistc50e7c62020-07-27 15:39:36 -0700246
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200247 if (pmRegionSizeLimitInKiB != nullptr)
248 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700249 asyncResp->res.jsonValue[jsonPtr]["PersistentRegionSizeLimitMiB"] =
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200250 (*pmRegionSizeLimitInKiB) >> 10;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800251 }
James Feistc50e7c62020-07-27 15:39:36 -0700252
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200253 if (volatileSizeInKiB != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800254 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700255 asyncResp->res.jsonValue[jsonPtr]["VolatileSizeMiB"] =
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200256 (*volatileSizeInKiB) >> 10;
257 }
258
259 if (pmSizeInKiB != nullptr)
260 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700261 asyncResp->res.jsonValue[jsonPtr]["NonVolatileSizeMiB"] =
262 (*pmSizeInKiB) >> 10;
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200263 }
264
265 if (cacheSizeInKB != nullptr)
266 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700267 asyncResp->res.jsonValue[jsonPtr]["CacheSizeMiB"] =
268 (*cacheSizeInKB >> 10);
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200269 }
270
271 if (voltaileRegionMaxSizeInKib != nullptr)
272 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700273 asyncResp->res.jsonValue[jsonPtr]["VolatileRegionSizeMaxMiB"] =
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200274 (*voltaileRegionMaxSizeInKib) >> 10;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800275 }
James Feistc50e7c62020-07-27 15:39:36 -0700276
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200277 if (pmRegionMaxSizeInKiB != nullptr)
278 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700279 asyncResp->res.jsonValue[jsonPtr]["PersistentRegionSizeMaxMiB"] =
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200280 (*pmRegionMaxSizeInKiB) >> 10;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800281 }
James Feistc50e7c62020-07-27 15:39:36 -0700282
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200283 if (allocationIncrementInKiB != nullptr)
284 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700285 asyncResp->res.jsonValue[jsonPtr]["AllocationIncrementMiB"] =
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200286 (*allocationIncrementInKiB) >> 10;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800287 }
James Feistc50e7c62020-07-27 15:39:36 -0700288
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200289 if (allocationAlignmentInKiB != nullptr)
290 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700291 asyncResp->res.jsonValue[jsonPtr]["AllocationAlignmentMiB"] =
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200292 (*allocationAlignmentInKiB) >> 10;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800293 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200294
295 if (volatileRegionNumberLimit != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800296 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700297 asyncResp->res.jsonValue[jsonPtr]["VolatileRegionNumberLimit"] =
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200298 *volatileRegionNumberLimit;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800299 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200300
301 if (pmRegionNumberLimit != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800302 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700303 asyncResp->res.jsonValue[jsonPtr]["PersistentRegionNumberLimit"] =
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200304 *pmRegionNumberLimit;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800305 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200306
307 if (spareDeviceCount != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800308 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700309 asyncResp->res.jsonValue[jsonPtr]["SpareDeviceCount"] =
310 *spareDeviceCount;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800311 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200312
313 if (isSpareDeviceInUse != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800314 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700315 asyncResp->res.jsonValue[jsonPtr]["IsSpareDeviceEnabled"] =
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200316 *isSpareDeviceInUse;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800317 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200318
319 if (isRankSpareEnabled != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800320 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700321 asyncResp->res.jsonValue[jsonPtr]["IsRankSpareEnabled"] =
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200322 *isRankSpareEnabled;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800323 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200324
325 if (maxAveragePowerLimitmW != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800326 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700327 asyncResp->res.jsonValue[jsonPtr]["MaxTDPMilliWatts"] =
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200328 *maxAveragePowerLimitmW;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800329 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200330
331 if (configurationLocked != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800332 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700333 asyncResp->res.jsonValue[jsonPtr]["ConfigurationLocked"] =
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200334 *configurationLocked;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800335 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200336
337 if (allowedMemoryModes != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800338 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800339 constexpr const std::array<const char*, 3> values{"Volatile", "PMEM",
340 "Block"};
James Feistc50e7c62020-07-27 15:39:36 -0700341
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800342 for (const char* v : values)
343 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200344 if (allowedMemoryModes->ends_with(v))
James Feistc50e7c62020-07-27 15:39:36 -0700345 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700346 asyncResp->res.jsonValue[jsonPtr]["OperatingMemoryModes"]
347 .push_back(v);
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800348 break;
James Feistc50e7c62020-07-27 15:39:36 -0700349 }
350 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800351 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200352
353 if (memoryMedia != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800354 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800355 constexpr const std::array<const char*, 3> values{"DRAM", "NAND",
356 "Intel3DXPoint"};
James Feistc50e7c62020-07-27 15:39:36 -0700357
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800358 for (const char* v : values)
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700359 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200360 if (memoryMedia->ends_with(v))
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700361 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700362 asyncResp->res.jsonValue[jsonPtr]["MemoryMedia"].push_back(v);
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800363 break;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700364 }
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700365 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800366 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200367
368 if (configurationLockCapable != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800369 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700370 asyncResp->res.jsonValue[jsonPtr]["SecurityCapabilities"]
371 ["ConfigurationLockCapable"] =
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200372 *configurationLockCapable;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800373 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200374
375 if (dataLockCapable != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800376 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400377 asyncResp->res
378 .jsonValue[jsonPtr]["SecurityCapabilities"]["DataLockCapable"] =
379 *dataLockCapable;
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200380 }
381
382 if (passphraseCapable != nullptr)
383 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400384 asyncResp->res
385 .jsonValue[jsonPtr]["SecurityCapabilities"]["PassphraseCapable"] =
386 *passphraseCapable;
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200387 }
388
389 if (maxPassphraseCount != nullptr)
390 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400391 asyncResp->res
392 .jsonValue[jsonPtr]["SecurityCapabilities"]["MaxPassphraseCount"] =
393 *maxPassphraseCount;
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200394 }
395
396 if (passphraseLockLimit != nullptr)
397 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400398 asyncResp->res
399 .jsonValue[jsonPtr]["SecurityCapabilities"]["PassphraseLockLimit"] =
400 *passphraseLockLimit;
James Feistc50e7c62020-07-27 15:39:36 -0700401 }
402}
403
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400404inline void assembleDimmProperties(
405 std::string_view dimmId,
406 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
407 const dbus::utility::DBusPropertiesMap& properties,
408 const nlohmann::json::json_pointer& jsonPtr)
Nan Zhou9a5acea2022-05-17 21:12:43 +0000409{
Ed Tanousac106bf2023-06-07 09:24:59 -0700410 asyncResp->res.jsonValue[jsonPtr]["Id"] = dimmId;
411 asyncResp->res.jsonValue[jsonPtr]["Name"] = "DIMM Slot";
Ed Tanous539d8c62024-06-19 14:38:27 -0700412 asyncResp->res.jsonValue[jsonPtr]["Status"]["State"] =
413 resource::State::Enabled;
414 asyncResp->res.jsonValue[jsonPtr]["Status"]["Health"] =
415 resource::Health::OK;
Nan Zhou9a5acea2022-05-17 21:12:43 +0000416
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200417 const uint16_t* memoryDataWidth = nullptr;
418 const size_t* memorySizeInKB = nullptr;
419 const std::string* partNumber = nullptr;
420 const std::string* serialNumber = nullptr;
421 const std::string* manufacturer = nullptr;
422 const uint16_t* revisionCode = nullptr;
423 const bool* present = nullptr;
424 const uint16_t* memoryTotalWidth = nullptr;
425 const std::string* ecc = nullptr;
426 const std::string* formFactor = nullptr;
427 const std::vector<uint16_t>* allowedSpeedsMT = nullptr;
George Liu6995c1c2023-06-15 08:53:11 +0800428 const size_t* memoryAttributes = nullptr;
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200429 const uint16_t* memoryConfiguredSpeedInMhz = nullptr;
430 const std::string* memoryType = nullptr;
Jayaprakash Mutyala6fde5972023-06-15 07:56:58 +0000431 const std::uint8_t* channel = nullptr;
432 const std::uint8_t* memoryController = nullptr;
433 const std::uint8_t* slot = nullptr;
434 const std::uint8_t* socket = nullptr;
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200435 const std::string* sparePartNumber = nullptr;
436 const std::string* model = nullptr;
437 const std::string* locationCode = nullptr;
George Liu7fe6d532024-03-06 09:01:37 +0800438 const bool* functional = nullptr;
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200439
440 const bool success = sdbusplus::unpackPropertiesNoThrow(
441 dbus_utils::UnpackErrorPrinter(), properties, "MemoryDataWidth",
442 memoryDataWidth, "MemorySizeInKB", memorySizeInKB, "PartNumber",
Nikhil Namjoshi656472d2022-09-13 20:54:44 +0000443 partNumber, "SerialNumber", serialNumber, "Manufacturer", manufacturer,
444 "RevisionCode", revisionCode, "Present", present, "MemoryTotalWidth",
445 memoryTotalWidth, "ECC", ecc, "FormFactor", formFactor,
446 "AllowedSpeedsMT", allowedSpeedsMT, "MemoryAttributes",
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200447 memoryAttributes, "MemoryConfiguredSpeedInMhz",
448 memoryConfiguredSpeedInMhz, "MemoryType", memoryType, "Channel",
449 channel, "MemoryController", memoryController, "Slot", slot, "Socket",
450 socket, "SparePartNumber", sparePartNumber, "Model", model,
George Liu7fe6d532024-03-06 09:01:37 +0800451 "LocationCode", locationCode, "Functional", functional);
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200452
453 if (!success)
Nan Zhou9a5acea2022-05-17 21:12:43 +0000454 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700455 messages::internalError(asyncResp->res);
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200456 return;
457 }
Nan Zhou9a5acea2022-05-17 21:12:43 +0000458
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200459 if (memoryDataWidth != nullptr)
460 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700461 asyncResp->res.jsonValue[jsonPtr]["DataWidthBits"] = *memoryDataWidth;
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200462 }
Nan Zhou9a5acea2022-05-17 21:12:43 +0000463
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200464 if (memorySizeInKB != nullptr)
465 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700466 asyncResp->res.jsonValue[jsonPtr]["CapacityMiB"] =
467 (*memorySizeInKB >> 10);
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200468 }
Nan Zhou9a5acea2022-05-17 21:12:43 +0000469
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200470 if (partNumber != nullptr)
471 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700472 asyncResp->res.jsonValue[jsonPtr]["PartNumber"] = *partNumber;
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200473 }
Nan Zhou9a5acea2022-05-17 21:12:43 +0000474
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200475 if (serialNumber != nullptr)
476 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700477 asyncResp->res.jsonValue[jsonPtr]["SerialNumber"] = *serialNumber;
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200478 }
479
480 if (manufacturer != nullptr)
481 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700482 asyncResp->res.jsonValue[jsonPtr]["Manufacturer"] = *manufacturer;
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200483 }
484
485 if (revisionCode != nullptr)
486 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700487 asyncResp->res.jsonValue[jsonPtr]["FirmwareRevision"] =
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200488 std::to_string(*revisionCode);
489 }
490
491 if (present != nullptr && !*present)
492 {
Ed Tanous539d8c62024-06-19 14:38:27 -0700493 asyncResp->res.jsonValue[jsonPtr]["Status"]["State"] =
494 resource::State::Absent;
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200495 }
496
George Liu7fe6d532024-03-06 09:01:37 +0800497 if (functional != nullptr)
498 {
499 if (!*functional)
500 {
501 asyncResp->res.jsonValue[jsonPtr]["Status"]["Health"] =
502 resource::Health::Critical;
503 }
504 }
505
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200506 if (memoryTotalWidth != nullptr)
507 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700508 asyncResp->res.jsonValue[jsonPtr]["BusWidthBits"] = *memoryTotalWidth;
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200509 }
510
511 if (ecc != nullptr)
512 {
513 constexpr const std::array<const char*, 4> values{
514 "NoECC", "SingleBitECC", "MultiBitECC", "AddressParity"};
515
516 for (const char* v : values)
Nan Zhou9a5acea2022-05-17 21:12:43 +0000517 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200518 if (ecc->ends_with(v))
Nan Zhou9a5acea2022-05-17 21:12:43 +0000519 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700520 asyncResp->res.jsonValue[jsonPtr]["ErrorCorrection"] = v;
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200521 break;
Nan Zhou9a5acea2022-05-17 21:12:43 +0000522 }
Nan Zhou9a5acea2022-05-17 21:12:43 +0000523 }
524 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200525
526 if (formFactor != nullptr)
527 {
528 constexpr const std::array<const char*, 11> values{
529 "RDIMM", "UDIMM", "SO_DIMM", "LRDIMM",
530 "Mini_RDIMM", "Mini_UDIMM", "SO_RDIMM_72b", "SO_UDIMM_72b",
531 "SO_DIMM_16b", "SO_DIMM_32b", "Die"};
532
533 for (const char* v : values)
534 {
535 if (formFactor->ends_with(v))
536 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700537 asyncResp->res.jsonValue[jsonPtr]["BaseModuleType"] = v;
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200538 break;
539 }
540 }
541 }
542
543 if (allowedSpeedsMT != nullptr)
544 {
545 nlohmann::json& jValue =
Ed Tanousac106bf2023-06-07 09:24:59 -0700546 asyncResp->res.jsonValue[jsonPtr]["AllowedSpeedsMHz"];
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200547 jValue = nlohmann::json::array();
548 for (uint16_t subVal : *allowedSpeedsMT)
549 {
550 jValue.push_back(subVal);
551 }
552 }
553
554 if (memoryAttributes != nullptr)
555 {
George Liu6995c1c2023-06-15 08:53:11 +0800556 asyncResp->res.jsonValue[jsonPtr]["RankCount"] = *memoryAttributes;
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200557 }
558
559 if (memoryConfiguredSpeedInMhz != nullptr)
560 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700561 asyncResp->res.jsonValue[jsonPtr]["OperatingSpeedMhz"] =
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200562 *memoryConfiguredSpeedInMhz;
563 }
564
565 if (memoryType != nullptr)
566 {
567 std::string memoryDeviceType =
568 translateMemoryTypeToRedfish(*memoryType);
569 // Values like "Unknown" or "Other" will return empty
570 // so just leave off
571 if (!memoryDeviceType.empty())
572 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700573 asyncResp->res.jsonValue[jsonPtr]["MemoryDeviceType"] =
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200574 memoryDeviceType;
575 }
576 if (memoryType->find("DDR") != std::string::npos)
577 {
Ed Tanous539d8c62024-06-19 14:38:27 -0700578 asyncResp->res.jsonValue[jsonPtr]["MemoryType"] =
579 memory::MemoryType::DRAM;
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200580 }
581 else if (memoryType->ends_with("Logical"))
582 {
Ed Tanous539d8c62024-06-19 14:38:27 -0700583 asyncResp->res.jsonValue[jsonPtr]["MemoryType"] =
584 memory::MemoryType::IntelOptane;
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200585 }
586 }
587
588 if (channel != nullptr)
589 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700590 asyncResp->res.jsonValue[jsonPtr]["MemoryLocation"]["Channel"] =
591 *channel;
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200592 }
593
594 if (memoryController != nullptr)
595 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400596 asyncResp->res
597 .jsonValue[jsonPtr]["MemoryLocation"]["MemoryController"] =
598 *memoryController;
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200599 }
600
601 if (slot != nullptr)
602 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700603 asyncResp->res.jsonValue[jsonPtr]["MemoryLocation"]["Slot"] = *slot;
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200604 }
605
606 if (socket != nullptr)
607 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700608 asyncResp->res.jsonValue[jsonPtr]["MemoryLocation"]["Socket"] = *socket;
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200609 }
610
611 if (sparePartNumber != nullptr)
612 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700613 asyncResp->res.jsonValue[jsonPtr]["SparePartNumber"] = *sparePartNumber;
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200614 }
615
616 if (model != nullptr)
617 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700618 asyncResp->res.jsonValue[jsonPtr]["Model"] = *model;
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200619 }
620
621 if (locationCode != nullptr)
622 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400623 asyncResp->res
624 .jsonValue[jsonPtr]["Location"]["PartLocation"]["ServiceLabel"] =
625 *locationCode;
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200626 }
627
Ed Tanousac106bf2023-06-07 09:24:59 -0700628 getPersistentMemoryProperties(asyncResp, properties, jsonPtr);
Nan Zhou9a5acea2022-05-17 21:12:43 +0000629}
630
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400631inline void getDimmDataByService(
632 std::shared_ptr<bmcweb::AsyncResp> asyncResp, const std::string& dimmId,
633 const std::string& service, const std::string& objPath)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200634{
Ed Tanous62598e32023-07-17 17:06:25 -0700635 BMCWEB_LOG_DEBUG("Get available system components.");
Ed Tanousdeae6a72024-11-11 21:58:57 -0800636 dbus::utility::getAllProperties(
637 service, objPath, "",
Ed Tanousac106bf2023-06-07 09:24:59 -0700638 [dimmId, asyncResp{std::move(asyncResp)}](
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800639 const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800640 const dbus::utility::DBusPropertiesMap& properties) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400641 if (ec)
642 {
643 BMCWEB_LOG_DEBUG("DBUS response error");
644 messages::internalError(asyncResp->res);
645 return;
646 }
647 assembleDimmProperties(dimmId, asyncResp, properties,
648 ""_json_pointer);
649 });
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200650}
651
Nan Zhouef00d7d2022-05-20 21:22:32 +0000652inline void assembleDimmPartitionData(
Ed Tanousac106bf2023-06-07 09:24:59 -0700653 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000654 const dbus::utility::DBusPropertiesMap& properties,
655 const nlohmann::json::json_pointer& regionPtr)
Nan Zhouef00d7d2022-05-20 21:22:32 +0000656{
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200657 const std::string* memoryClassification = nullptr;
658 const uint64_t* offsetInKiB = nullptr;
659 const std::string* partitionId = nullptr;
660 const bool* passphraseState = nullptr;
661 const uint64_t* sizeInKiB = nullptr;
662
663 const bool success = sdbusplus::unpackPropertiesNoThrow(
664 dbus_utils::UnpackErrorPrinter(), properties, "MemoryClassification",
665 memoryClassification, "OffsetInKiB", offsetInKiB, "PartitionId",
666 partitionId, "PassphraseState", passphraseState, "SizeInKiB",
667 sizeInKiB);
668
669 if (!success)
Nan Zhouef00d7d2022-05-20 21:22:32 +0000670 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700671 messages::internalError(asyncResp->res);
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200672 return;
Nan Zhouef00d7d2022-05-20 21:22:32 +0000673 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200674
675 nlohmann::json::object_t partition;
676
677 if (memoryClassification != nullptr)
678 {
679 partition["MemoryClassification"] = *memoryClassification;
680 }
681
682 if (offsetInKiB != nullptr)
683 {
684 partition["OffsetMiB"] = (*offsetInKiB >> 10);
685 }
686
687 if (partitionId != nullptr)
688 {
689 partition["RegionId"] = *partitionId;
690 }
691
692 if (passphraseState != nullptr)
693 {
694 partition["PassphraseEnabled"] = *passphraseState;
695 }
696
697 if (sizeInKiB != nullptr)
698 {
699 partition["SizeMiB"] = (*sizeInKiB >> 10);
700 }
701
Ed Tanousac106bf2023-06-07 09:24:59 -0700702 asyncResp->res.jsonValue[regionPtr].emplace_back(std::move(partition));
Nan Zhouef00d7d2022-05-20 21:22:32 +0000703}
704
Ed Tanousac106bf2023-06-07 09:24:59 -0700705inline void getDimmPartitionData(std::shared_ptr<bmcweb::AsyncResp> asyncResp,
Ed Tanous23a21a12020-07-25 04:45:05 +0000706 const std::string& service,
707 const std::string& path)
James Feist45094ad2020-04-29 14:02:30 -0700708{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800709 dbus::utility::getAllProperties(
710 service, path,
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200711 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition",
Ed Tanousac106bf2023-06-07 09:24:59 -0700712 [asyncResp{std::move(asyncResp)}](
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800713 const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800714 const dbus::utility::DBusPropertiesMap& properties) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400715 if (ec)
716 {
717 BMCWEB_LOG_DEBUG("DBUS response error");
718 messages::internalError(asyncResp->res);
James Feist45094ad2020-04-29 14:02:30 -0700719
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400720 return;
721 }
722 nlohmann::json::json_pointer regionPtr = "/Regions"_json_pointer;
723 assembleDimmPartitionData(asyncResp, properties, regionPtr);
Ed Tanous002d39b2022-05-31 08:59:27 -0700724 }
James Feist45094ad2020-04-29 14:02:30 -0700725
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200726 );
James Feist45094ad2020-04-29 14:02:30 -0700727}
728
George Liu69800112020-10-10 11:41:08 +0800729inline void afterGetDimmData(
730 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
731 const std::string& dimmId, const boost::system::error_code& ec,
732 const dbus::utility::MapperGetSubTreeResponse& subtree)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200733{
George Liu69800112020-10-10 11:41:08 +0800734 if (ec)
735 {
736 if (ec.value() != EBADR)
737 {
738 BMCWEB_LOG_ERROR("DBUS response error: {}", ec.value());
739 messages::internalError(asyncResp->res);
740 }
741 return;
742 }
James Feist45094ad2020-04-29 14:02:30 -0700743
George Liu69800112020-10-10 11:41:08 +0800744 bool found = false;
745 for (const auto& [objectPath, serviceMap] : subtree)
746 {
747 sdbusplus::message::object_path path(objectPath);
748
749 bool dimmInterface = false;
750 bool associationInterface = false;
751 /* Note: Multiple D-Bus objects can provide details for the Memory
752 * object: 1) Dimm is the primary object 2) Additional partitions could
753 * exist per Dimm. Only consider the object found if the Dimm is found.
754 */
755 for (const auto& [serviceName, interfaceList] : serviceMap)
756 {
757 for (const auto& interface : interfaceList)
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400758 {
George Liu69800112020-10-10 11:41:08 +0800759 if (interface == "xyz.openbmc_project.Inventory.Item.Dimm" &&
760 path.filename() == dimmId)
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400761 {
George Liu69800112020-10-10 11:41:08 +0800762 // Found the single Dimm
763 getDimmDataByService(asyncResp, dimmId, serviceName,
764 objectPath);
765 dimmInterface = true;
766 found = true;
767 }
768 else if (interface ==
769 "xyz.openbmc_project.Association.Definitions")
770 {
771 /* Object has associations. If this object is also a Dimm
772 * then the association might provide the LED state
773 * information. After all interfaces for this object have
774 * been checked the LED information will be gathered if the
775 * object was a Dimm
776 */
777 associationInterface = true;
778 }
779 else if (
780 interface ==
781 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition" &&
782 path.parent_path().filename() == dimmId)
783 {
784 // partitions are separate as there can be multiple per
785 // device, i.e.
786 // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition1
787 // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition2
788 getDimmPartitionData(asyncResp, serviceName, objectPath);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200789 }
790 }
George Liu69800112020-10-10 11:41:08 +0800791 }
792
793 /* If a Dimm has an Association check if it has a LED */
794 if (associationInterface && dimmInterface)
795 {
796 getLocationIndicatorActive(asyncResp, objectPath);
797 }
798 }
799
800 if (!found)
801 {
802 // Dimm object not found
803 messages::resourceNotFound(asyncResp->res, "Memory", dimmId);
804 return;
805 }
806 // Set @odata only if object is found
807 asyncResp->res.jsonValue["@odata.type"] = "#Memory.v1_11_0.Memory";
808 asyncResp->res.jsonValue["@odata.id"] =
809 boost::urls::format("/redfish/v1/Systems/{}/Memory/{}",
810 BMCWEB_REDFISH_SYSTEM_URI_NAME, dimmId);
811}
812
813inline void getDimmData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
814 const std::string& dimmId)
815{
816 BMCWEB_LOG_DEBUG("Get dimm path for {}", dimmId);
817 constexpr std::array<std::string_view, 2> interfaces = {
818 "xyz.openbmc_project.Inventory.Item.Dimm",
819 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition"};
820
821 dbus::utility::getSubTree(
822 "/xyz/openbmc_project/inventory", 0, interfaces,
823 [asyncResp,
824 dimmId](const boost::system::error_code& ec,
825 const dbus::utility::MapperGetSubTreeResponse& subtree) {
826 afterGetDimmData(asyncResp, dimmId, ec, subtree);
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400827 });
Ed Tanous271584a2019-07-09 16:24:22 -0700828}
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200829
George Liu69800112020-10-10 11:41:08 +0800830inline void handleSetDimmData(
831 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
832 bool locationIndicatorActive, const std::string& dimmPath)
833{
834 setLocationIndicatorActive(asyncResp, dimmPath, locationIndicatorActive);
835}
836
837inline void afterGetValidDimmPath(
838 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
839 const std::string& dimmId, const boost::system::error_code& ec,
840 const dbus::utility::MapperGetSubTreePathsResponse& subtree,
841 const std::function<void(const std::string& dimmPath)>& callback)
842{
843 if (ec)
844 {
845 if (ec.value() == EBADR)
846 {
847 /* Need to report error for PATCH */
848 BMCWEB_LOG_WARNING("Dimm not found in inventory");
849 messages::resourceNotFound(asyncResp->res, "Memory", dimmId);
850 }
851 else
852 {
853 BMCWEB_LOG_ERROR("DBUS response error: {}", ec.value());
854 messages::internalError(asyncResp->res);
855 }
856 return;
857 }
858
859 for (const auto& objectPath : subtree)
860 {
861 // Ignore any objects which don't end with our desired dimm name
862 sdbusplus::message::object_path path(objectPath);
863 if (path.filename() == dimmId)
864 {
865 callback(path);
866 return;
867 }
868 }
869
870 // Object not found
871 messages::resourceNotFound(asyncResp->res, "Memory", dimmId);
872}
873
874inline void getValidDimmPath(
875 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
876 const std::string& dimmId,
877 std::function<void(const std::string& dimmPath)>&& callback)
878{
879 BMCWEB_LOG_DEBUG("Get dimm path for {}", dimmId);
880 constexpr std::array<std::string_view, 1> interfaces = {
881 "xyz.openbmc_project.Inventory.Item.Dimm"};
882
883 dbus::utility::getSubTreePaths(
884 "/xyz/openbmc_project/inventory", 0, interfaces,
885 [asyncResp, dimmId, callback{std::move(callback)}](
886 const boost::system::error_code& ec,
887 const dbus::utility::MapperGetSubTreePathsResponse& subtree) {
888 afterGetValidDimmPath(asyncResp, dimmId, ec, subtree, callback);
889 });
890}
891
892inline void handleMemoryPatch(
893 App& app, const crow::Request& req,
894 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
895 const std::string& systemName, const std::string& dimmId)
896{
897 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
898 {
899 return;
900 }
901
902 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
903 {
904 // Option currently returns no systems. TBD
905 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
906 systemName);
907 return;
908 }
909
910 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
911 {
912 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
913 systemName);
914 return;
915 }
916
917 std::optional<bool> locationIndicatorActive;
918 if (!json_util::readJsonPatch( //
919 req, asyncResp->res, //
920 "LocationIndicatorActive", locationIndicatorActive //
921 ))
922 {
923 return;
924 }
925
926 if (locationIndicatorActive)
927 {
928 getValidDimmPath(asyncResp, dimmId,
929 std::bind_front(handleSetDimmData, asyncResp,
930 *locationIndicatorActive));
931 }
932}
933
934inline void handleMemoryGet(App& app, const crow::Request& req,
935 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
936 const std::string& systemName,
937 const std::string& dimmId)
938{
939 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
940 {
941 return;
942 }
943
944 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
945 {
946 // Option currently returns no systems. TBD
947 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
948 systemName);
949 return;
950 }
951
952 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
953 {
954 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
955 systemName);
956 return;
957 }
958
959 getDimmData(asyncResp, dimmId);
960}
961
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700962inline void requestRoutesMemoryCollection(App& app)
Ed Tanous029573d2019-02-01 10:57:49 -0800963{
Ed Tanous029573d2019-02-01 10:57:49 -0800964 /**
965 * Functions triggers appropriate requests on DBus
966 */
Ed Tanous22d268c2022-05-19 09:39:07 -0700967 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Memory/")
Ed Tanoused398212021-06-09 17:05:54 -0700968 .privileges(redfish::privileges::getMemoryCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700969 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700970 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -0700971 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
972 const std::string& systemName) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400973 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
974 {
975 return;
976 }
977 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
978 {
979 // Option currently returns no systems. TBD
980 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
981 systemName);
982 return;
983 }
984 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
985 {
986 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
987 systemName);
988 return;
989 }
Ed Tanous22d268c2022-05-19 09:39:07 -0700990
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400991 asyncResp->res.jsonValue["@odata.type"] =
992 "#MemoryCollection.MemoryCollection";
993 asyncResp->res.jsonValue["Name"] = "Memory Module Collection";
994 asyncResp->res.jsonValue["@odata.id"] =
995 boost::urls::format("/redfish/v1/Systems/{}/Memory",
996 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200997
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400998 constexpr std::array<std::string_view, 1> interfaces{
999 "xyz.openbmc_project.Inventory.Item.Dimm"};
1000 collection_util::getCollectionMembers(
1001 asyncResp,
1002 boost::urls::format("/redfish/v1/Systems/{}/Memory",
1003 BMCWEB_REDFISH_SYSTEM_URI_NAME),
1004 interfaces, "/xyz/openbmc_project/inventory");
1005 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001006}
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001007
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001008inline void requestRoutesMemory(App& app)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001009{
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001010 /**
1011 * Functions triggers appropriate requests on DBus
1012 */
Ed Tanous22d268c2022-05-19 09:39:07 -07001013 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Memory/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001014 .privileges(redfish::privileges::getMemory)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001015 .methods(boost::beast::http::verb::get)(
George Liu69800112020-10-10 11:41:08 +08001016 std::bind_front(handleMemoryGet, std::ref(app)));
Ed Tanous7f3e84a2022-12-28 16:22:54 -08001017
George Liu69800112020-10-10 11:41:08 +08001018 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Memory/<str>/")
1019 .privileges(redfish::privileges::patchMemory)
1020 .methods(boost::beast::http::verb::patch)(
1021 std::bind_front(handleMemoryPatch, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001022}
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001023
1024} // namespace redfish