xref: /openbmc/bmcweb/features/redfish/lib/memory.hpp (revision 6980011b042c8706b65af9606d1308e96d919b02)
140e9b92eSEd Tanous // SPDX-License-Identifier: Apache-2.0
240e9b92eSEd Tanous // SPDX-FileCopyrightText: Copyright OpenBMC Authors
340e9b92eSEd Tanous // SPDX-FileCopyrightText: Copyright 2018 Intel Corporation
4ac6a4445SGunnar Mills #pragma once
5ac6a4445SGunnar Mills 
613451e39SWilly Tu #include "bmcweb_config.h"
713451e39SWilly Tu 
83ccb3adbSEd Tanous #include "app.hpp"
9d7857201SEd Tanous #include "async_resp.hpp"
103ccb3adbSEd Tanous #include "dbus_utility.hpp"
11d7857201SEd Tanous #include "error_messages.hpp"
12539d8c6bSEd Tanous #include "generated/enums/memory.hpp"
13539d8c6bSEd Tanous #include "generated/enums/resource.hpp"
14d7857201SEd Tanous #include "http_request.hpp"
15*6980011bSGeorge Liu #include "led.hpp"
16d7857201SEd Tanous #include "logging.hpp"
173ccb3adbSEd Tanous #include "query.hpp"
183ccb3adbSEd Tanous #include "registries/privilege_registry.hpp"
193ccb3adbSEd Tanous #include "utils/collection.hpp"
203ccb3adbSEd Tanous #include "utils/dbus_utils.hpp"
213ccb3adbSEd Tanous #include "utils/hex_utils.hpp"
22*6980011bSGeorge Liu #include "utils/json_utils.hpp"
23*6980011bSGeorge Liu 
24*6980011bSGeorge Liu #include <asm-generic/errno.h>
25ac6a4445SGunnar Mills 
26d7857201SEd Tanous #include <boost/beast/http/verb.hpp>
27e99073f5SGeorge Liu #include <boost/system/error_code.hpp>
28ef4c65b7SEd Tanous #include <boost/url/format.hpp>
29d7f04fd9SNan Zhou #include <nlohmann/json.hpp>
30d7857201SEd Tanous #include <sdbusplus/message/native_types.hpp>
31c1343bf6SKrzysztof Grobelny #include <sdbusplus/unpack_properties.hpp>
32ac6a4445SGunnar Mills 
337a1dbc48SGeorge Liu #include <array>
34d7857201SEd Tanous #include <cstddef>
35d7857201SEd Tanous #include <cstdint>
36*6980011bSGeorge Liu #include <functional>
37d7857201SEd Tanous #include <memory>
38*6980011bSGeorge Liu #include <optional>
39d7857201SEd Tanous #include <string>
407a1dbc48SGeorge Liu #include <string_view>
41d7857201SEd Tanous #include <utility>
42d7857201SEd Tanous #include <vector>
437a1dbc48SGeorge Liu 
44ac6a4445SGunnar Mills namespace redfish
45ac6a4445SGunnar Mills {
46ac6a4445SGunnar Mills 
47313efb1cSGunnar Mills inline std::string translateMemoryTypeToRedfish(const std::string& memoryType)
48313efb1cSGunnar Mills {
49313efb1cSGunnar Mills     if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR")
50313efb1cSGunnar Mills     {
51313efb1cSGunnar Mills         return "DDR";
52313efb1cSGunnar Mills     }
53313efb1cSGunnar Mills     if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR2")
54313efb1cSGunnar Mills     {
55313efb1cSGunnar Mills         return "DDR2";
56313efb1cSGunnar Mills     }
57313efb1cSGunnar Mills     if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR3")
58313efb1cSGunnar Mills     {
59313efb1cSGunnar Mills         return "DDR3";
60313efb1cSGunnar Mills     }
61313efb1cSGunnar Mills     if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR4")
62313efb1cSGunnar Mills     {
63313efb1cSGunnar Mills         return "DDR4";
64313efb1cSGunnar Mills     }
65313efb1cSGunnar Mills     if (memoryType ==
66313efb1cSGunnar Mills         "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR4E_SDRAM")
67313efb1cSGunnar Mills     {
68313efb1cSGunnar Mills         return "DDR4E_SDRAM";
69313efb1cSGunnar Mills     }
7011a2f0f0SMansi Joshi     if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR5")
7111a2f0f0SMansi Joshi     {
7211a2f0f0SMansi Joshi         return "DDR5";
7311a2f0f0SMansi Joshi     }
74313efb1cSGunnar Mills     if (memoryType ==
75313efb1cSGunnar Mills         "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.LPDDR4_SDRAM")
76313efb1cSGunnar Mills     {
77313efb1cSGunnar Mills         return "LPDDR4_SDRAM";
78313efb1cSGunnar Mills     }
79313efb1cSGunnar Mills     if (memoryType ==
80313efb1cSGunnar Mills         "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.LPDDR3_SDRAM")
81313efb1cSGunnar Mills     {
82313efb1cSGunnar Mills         return "LPDDR3_SDRAM";
83313efb1cSGunnar Mills     }
84313efb1cSGunnar Mills     if (memoryType ==
85313efb1cSGunnar Mills         "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR2_SDRAM_FB_DIMM")
86313efb1cSGunnar Mills     {
87313efb1cSGunnar Mills         return "DDR2_SDRAM_FB_DIMM";
88313efb1cSGunnar Mills     }
890fda0f12SGeorge Liu     if (memoryType ==
900fda0f12SGeorge Liu         "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR2_SDRAM_FB_DIMM_PROB")
91313efb1cSGunnar Mills     {
92313efb1cSGunnar Mills         return "DDR2_SDRAM_FB_DIMM_PROBE";
93313efb1cSGunnar Mills     }
94313efb1cSGunnar Mills     if (memoryType ==
95313efb1cSGunnar Mills         "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR_SGRAM")
96313efb1cSGunnar Mills     {
97313efb1cSGunnar Mills         return "DDR_SGRAM";
98313efb1cSGunnar Mills     }
99313efb1cSGunnar Mills     if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.ROM")
100313efb1cSGunnar Mills     {
101313efb1cSGunnar Mills         return "ROM";
102313efb1cSGunnar Mills     }
103313efb1cSGunnar Mills     if (memoryType ==
104313efb1cSGunnar Mills         "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.SDRAM")
105313efb1cSGunnar Mills     {
106313efb1cSGunnar Mills         return "SDRAM";
107313efb1cSGunnar Mills     }
108313efb1cSGunnar Mills     if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.EDO")
109313efb1cSGunnar Mills     {
110313efb1cSGunnar Mills         return "EDO";
111313efb1cSGunnar Mills     }
112313efb1cSGunnar Mills     if (memoryType ==
113313efb1cSGunnar Mills         "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.FastPageMode")
114313efb1cSGunnar Mills     {
115313efb1cSGunnar Mills         return "FastPageMode";
116313efb1cSGunnar Mills     }
117313efb1cSGunnar Mills     if (memoryType ==
118313efb1cSGunnar Mills         "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.PipelinedNibble")
119313efb1cSGunnar Mills     {
120313efb1cSGunnar Mills         return "PipelinedNibble";
121313efb1cSGunnar Mills     }
122313efb1cSGunnar Mills     if (memoryType ==
123313efb1cSGunnar Mills         "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.Logical")
124313efb1cSGunnar Mills     {
125313efb1cSGunnar Mills         return "Logical";
126313efb1cSGunnar Mills     }
127313efb1cSGunnar Mills     if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.HBM")
128313efb1cSGunnar Mills     {
129313efb1cSGunnar Mills         return "HBM";
130313efb1cSGunnar Mills     }
131313efb1cSGunnar Mills     if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.HBM2")
132313efb1cSGunnar Mills     {
133313efb1cSGunnar Mills         return "HBM2";
134313efb1cSGunnar Mills     }
135ce34d514STyson Tuckerbear     if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.HBM3")
136ce34d514STyson Tuckerbear     {
137ce34d514STyson Tuckerbear         return "HBM3";
138ce34d514STyson Tuckerbear     }
139313efb1cSGunnar Mills     // This is values like Other or Unknown
140313efb1cSGunnar Mills     // Also D-Bus values:
141313efb1cSGunnar Mills     // DRAM
142313efb1cSGunnar Mills     // EDRAM
143313efb1cSGunnar Mills     // VRAM
144313efb1cSGunnar Mills     // SRAM
145313efb1cSGunnar Mills     // RAM
146313efb1cSGunnar Mills     // FLASH
147313efb1cSGunnar Mills     // EEPROM
148313efb1cSGunnar Mills     // FEPROM
149313efb1cSGunnar Mills     // EPROM
150313efb1cSGunnar Mills     // CDRAM
151313efb1cSGunnar Mills     // ThreeDRAM
152313efb1cSGunnar Mills     // RDRAM
153313efb1cSGunnar Mills     // FBD2
154313efb1cSGunnar Mills     // LPDDR_SDRAM
155313efb1cSGunnar Mills     // LPDDR2_SDRAM
15611a2f0f0SMansi Joshi     // LPDDR5_SDRAM
157313efb1cSGunnar Mills     return "";
158313efb1cSGunnar Mills }
159313efb1cSGunnar Mills 
160ac106bf6SEd Tanous inline void dimmPropToHex(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
161c1343bf6SKrzysztof Grobelny                           const char* key, const uint16_t* value,
162d7f04fd9SNan Zhou                           const nlohmann::json::json_pointer& jsonPtr)
163ac6a4445SGunnar Mills {
164ac6a4445SGunnar Mills     if (value == nullptr)
165ac6a4445SGunnar Mills     {
166ac6a4445SGunnar Mills         return;
167ac6a4445SGunnar Mills     }
168ac106bf6SEd Tanous     asyncResp->res.jsonValue[jsonPtr][key] = "0x" + intToHexString(*value, 4);
169ac6a4445SGunnar Mills }
170ac6a4445SGunnar Mills 
1718d1b46d7Szhanghch05 inline void getPersistentMemoryProperties(
172ac106bf6SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
173c1343bf6SKrzysztof Grobelny     const dbus::utility::DBusPropertiesMap& properties,
174d7f04fd9SNan Zhou     const nlohmann::json::json_pointer& jsonPtr)
175ac6a4445SGunnar Mills {
176c1343bf6SKrzysztof Grobelny     const uint16_t* moduleManufacturerID = nullptr;
177c1343bf6SKrzysztof Grobelny     const uint16_t* moduleProductID = nullptr;
178c1343bf6SKrzysztof Grobelny     const uint16_t* subsystemVendorID = nullptr;
179c1343bf6SKrzysztof Grobelny     const uint16_t* subsystemDeviceID = nullptr;
180c1343bf6SKrzysztof Grobelny     const uint64_t* volatileRegionSizeLimitInKiB = nullptr;
181c1343bf6SKrzysztof Grobelny     const uint64_t* pmRegionSizeLimitInKiB = nullptr;
182c1343bf6SKrzysztof Grobelny     const uint64_t* volatileSizeInKiB = nullptr;
183c1343bf6SKrzysztof Grobelny     const uint64_t* pmSizeInKiB = nullptr;
184c1343bf6SKrzysztof Grobelny     const uint64_t* cacheSizeInKB = nullptr;
185c1343bf6SKrzysztof Grobelny     const uint64_t* voltaileRegionMaxSizeInKib = nullptr;
186c1343bf6SKrzysztof Grobelny     const uint64_t* pmRegionMaxSizeInKiB = nullptr;
187c1343bf6SKrzysztof Grobelny     const uint64_t* allocationIncrementInKiB = nullptr;
188c1343bf6SKrzysztof Grobelny     const uint64_t* allocationAlignmentInKiB = nullptr;
189c1343bf6SKrzysztof Grobelny     const uint64_t* volatileRegionNumberLimit = nullptr;
190c1343bf6SKrzysztof Grobelny     const uint64_t* pmRegionNumberLimit = nullptr;
191c1343bf6SKrzysztof Grobelny     const uint64_t* spareDeviceCount = nullptr;
192c1343bf6SKrzysztof Grobelny     const bool* isSpareDeviceInUse = nullptr;
193c1343bf6SKrzysztof Grobelny     const bool* isRankSpareEnabled = nullptr;
194c1343bf6SKrzysztof Grobelny     const std::vector<uint32_t>* maxAveragePowerLimitmW = nullptr;
195c1343bf6SKrzysztof Grobelny     const bool* configurationLocked = nullptr;
196c1343bf6SKrzysztof Grobelny     const std::string* allowedMemoryModes = nullptr;
197c1343bf6SKrzysztof Grobelny     const std::string* memoryMedia = nullptr;
198c1343bf6SKrzysztof Grobelny     const bool* configurationLockCapable = nullptr;
199c1343bf6SKrzysztof Grobelny     const bool* dataLockCapable = nullptr;
200c1343bf6SKrzysztof Grobelny     const bool* passphraseCapable = nullptr;
201c1343bf6SKrzysztof Grobelny     const uint64_t* maxPassphraseCount = nullptr;
202c1343bf6SKrzysztof Grobelny     const uint64_t* passphraseLockLimit = nullptr;
203c1343bf6SKrzysztof Grobelny 
204c1343bf6SKrzysztof Grobelny     const bool success = sdbusplus::unpackPropertiesNoThrow(
205c1343bf6SKrzysztof Grobelny         dbus_utils::UnpackErrorPrinter(), properties, "ModuleManufacturerID",
206c1343bf6SKrzysztof Grobelny         moduleManufacturerID, "ModuleProductID", moduleProductID,
207c1343bf6SKrzysztof Grobelny         "SubsystemVendorID", subsystemVendorID, "SubsystemDeviceID",
208c1343bf6SKrzysztof Grobelny         subsystemDeviceID, "VolatileRegionSizeLimitInKiB",
209c1343bf6SKrzysztof Grobelny         volatileRegionSizeLimitInKiB, "PmRegionSizeLimitInKiB",
210c1343bf6SKrzysztof Grobelny         pmRegionSizeLimitInKiB, "VolatileSizeInKiB", volatileSizeInKiB,
211c1343bf6SKrzysztof Grobelny         "PmSizeInKiB", pmSizeInKiB, "CacheSizeInKB", cacheSizeInKB,
212c1343bf6SKrzysztof Grobelny         "VoltaileRegionMaxSizeInKib", voltaileRegionMaxSizeInKib,
213c1343bf6SKrzysztof Grobelny         "PmRegionMaxSizeInKiB", pmRegionMaxSizeInKiB,
214c1343bf6SKrzysztof Grobelny         "AllocationIncrementInKiB", allocationIncrementInKiB,
215c1343bf6SKrzysztof Grobelny         "AllocationAlignmentInKiB", allocationAlignmentInKiB,
216c1343bf6SKrzysztof Grobelny         "VolatileRegionNumberLimit", volatileRegionNumberLimit,
217c1343bf6SKrzysztof Grobelny         "PmRegionNumberLimit", pmRegionNumberLimit, "SpareDeviceCount",
218c1343bf6SKrzysztof Grobelny         spareDeviceCount, "IsSpareDeviceInUse", isSpareDeviceInUse,
219c1343bf6SKrzysztof Grobelny         "IsRankSpareEnabled", isRankSpareEnabled, "MaxAveragePowerLimitmW",
220c1343bf6SKrzysztof Grobelny         maxAveragePowerLimitmW, "ConfigurationLocked", configurationLocked,
221c1343bf6SKrzysztof Grobelny         "AllowedMemoryModes", allowedMemoryModes, "MemoryMedia", memoryMedia,
222c1343bf6SKrzysztof Grobelny         "ConfigurationLockCapable", configurationLockCapable, "DataLockCapable",
223c1343bf6SKrzysztof Grobelny         dataLockCapable, "PassphraseCapable", passphraseCapable,
224c1343bf6SKrzysztof Grobelny         "MaxPassphraseCount", maxPassphraseCount, "PassphraseLockLimit",
225c1343bf6SKrzysztof Grobelny         passphraseLockLimit);
226c1343bf6SKrzysztof Grobelny 
227c1343bf6SKrzysztof Grobelny     if (!success)
228ac6a4445SGunnar Mills     {
229ac106bf6SEd Tanous         messages::internalError(asyncResp->res);
230c1343bf6SKrzysztof Grobelny         return;
231ac6a4445SGunnar Mills     }
232c1343bf6SKrzysztof Grobelny 
233ac106bf6SEd Tanous     dimmPropToHex(asyncResp, "ModuleManufacturerID", moduleManufacturerID,
234ac106bf6SEd Tanous                   jsonPtr);
235ac106bf6SEd Tanous     dimmPropToHex(asyncResp, "ModuleProductID", moduleProductID, jsonPtr);
236ac106bf6SEd Tanous     dimmPropToHex(asyncResp, "MemorySubsystemControllerManufacturerID",
237c1343bf6SKrzysztof Grobelny                   subsystemVendorID, jsonPtr);
238ac106bf6SEd Tanous     dimmPropToHex(asyncResp, "MemorySubsystemControllerProductID",
239c1343bf6SKrzysztof Grobelny                   subsystemDeviceID, jsonPtr);
240ac6a4445SGunnar Mills 
241c1343bf6SKrzysztof Grobelny     if (volatileRegionSizeLimitInKiB != nullptr)
242ac6a4445SGunnar Mills     {
243ac106bf6SEd Tanous         asyncResp->res.jsonValue[jsonPtr]["VolatileRegionSizeLimitMiB"] =
244c1343bf6SKrzysztof Grobelny             (*volatileRegionSizeLimitInKiB) >> 10;
245ac6a4445SGunnar Mills     }
246ac6a4445SGunnar Mills 
247c1343bf6SKrzysztof Grobelny     if (pmRegionSizeLimitInKiB != nullptr)
248ac6a4445SGunnar Mills     {
249ac106bf6SEd Tanous         asyncResp->res.jsonValue[jsonPtr]["PersistentRegionSizeLimitMiB"] =
250c1343bf6SKrzysztof Grobelny             (*pmRegionSizeLimitInKiB) >> 10;
251ac6a4445SGunnar Mills     }
252ac6a4445SGunnar Mills 
253c1343bf6SKrzysztof Grobelny     if (volatileSizeInKiB != nullptr)
254ac6a4445SGunnar Mills     {
255ac106bf6SEd Tanous         asyncResp->res.jsonValue[jsonPtr]["VolatileSizeMiB"] =
256c1343bf6SKrzysztof Grobelny             (*volatileSizeInKiB) >> 10;
257ac6a4445SGunnar Mills     }
258c1343bf6SKrzysztof Grobelny 
259c1343bf6SKrzysztof Grobelny     if (pmSizeInKiB != nullptr)
260c1343bf6SKrzysztof Grobelny     {
261ac106bf6SEd Tanous         asyncResp->res.jsonValue[jsonPtr]["NonVolatileSizeMiB"] =
262ac106bf6SEd Tanous             (*pmSizeInKiB) >> 10;
263c1343bf6SKrzysztof Grobelny     }
264c1343bf6SKrzysztof Grobelny 
265c1343bf6SKrzysztof Grobelny     if (cacheSizeInKB != nullptr)
266c1343bf6SKrzysztof Grobelny     {
267ac106bf6SEd Tanous         asyncResp->res.jsonValue[jsonPtr]["CacheSizeMiB"] =
268ac106bf6SEd Tanous             (*cacheSizeInKB >> 10);
269c1343bf6SKrzysztof Grobelny     }
270c1343bf6SKrzysztof Grobelny 
271c1343bf6SKrzysztof Grobelny     if (voltaileRegionMaxSizeInKib != nullptr)
272c1343bf6SKrzysztof Grobelny     {
273ac106bf6SEd Tanous         asyncResp->res.jsonValue[jsonPtr]["VolatileRegionSizeMaxMiB"] =
274c1343bf6SKrzysztof Grobelny             (*voltaileRegionMaxSizeInKib) >> 10;
275ac6a4445SGunnar Mills     }
276ac6a4445SGunnar Mills 
277c1343bf6SKrzysztof Grobelny     if (pmRegionMaxSizeInKiB != nullptr)
278ac6a4445SGunnar Mills     {
279ac106bf6SEd Tanous         asyncResp->res.jsonValue[jsonPtr]["PersistentRegionSizeMaxMiB"] =
280c1343bf6SKrzysztof Grobelny             (*pmRegionMaxSizeInKiB) >> 10;
281ac6a4445SGunnar Mills     }
282ac6a4445SGunnar Mills 
283c1343bf6SKrzysztof Grobelny     if (allocationIncrementInKiB != nullptr)
284ac6a4445SGunnar Mills     {
285ac106bf6SEd Tanous         asyncResp->res.jsonValue[jsonPtr]["AllocationIncrementMiB"] =
286c1343bf6SKrzysztof Grobelny             (*allocationIncrementInKiB) >> 10;
287ac6a4445SGunnar Mills     }
288ac6a4445SGunnar Mills 
289c1343bf6SKrzysztof Grobelny     if (allocationAlignmentInKiB != nullptr)
290ac6a4445SGunnar Mills     {
291ac106bf6SEd Tanous         asyncResp->res.jsonValue[jsonPtr]["AllocationAlignmentMiB"] =
292c1343bf6SKrzysztof Grobelny             (*allocationAlignmentInKiB) >> 10;
293ac6a4445SGunnar Mills     }
294c1343bf6SKrzysztof Grobelny 
295c1343bf6SKrzysztof Grobelny     if (volatileRegionNumberLimit != nullptr)
296ac6a4445SGunnar Mills     {
297ac106bf6SEd Tanous         asyncResp->res.jsonValue[jsonPtr]["VolatileRegionNumberLimit"] =
298c1343bf6SKrzysztof Grobelny             *volatileRegionNumberLimit;
299ac6a4445SGunnar Mills     }
300c1343bf6SKrzysztof Grobelny 
301c1343bf6SKrzysztof Grobelny     if (pmRegionNumberLimit != nullptr)
302ac6a4445SGunnar Mills     {
303ac106bf6SEd Tanous         asyncResp->res.jsonValue[jsonPtr]["PersistentRegionNumberLimit"] =
304c1343bf6SKrzysztof Grobelny             *pmRegionNumberLimit;
305ac6a4445SGunnar Mills     }
306c1343bf6SKrzysztof Grobelny 
307c1343bf6SKrzysztof Grobelny     if (spareDeviceCount != nullptr)
308ac6a4445SGunnar Mills     {
309ac106bf6SEd Tanous         asyncResp->res.jsonValue[jsonPtr]["SpareDeviceCount"] =
310ac106bf6SEd Tanous             *spareDeviceCount;
311ac6a4445SGunnar Mills     }
312c1343bf6SKrzysztof Grobelny 
313c1343bf6SKrzysztof Grobelny     if (isSpareDeviceInUse != nullptr)
314ac6a4445SGunnar Mills     {
315ac106bf6SEd Tanous         asyncResp->res.jsonValue[jsonPtr]["IsSpareDeviceEnabled"] =
316c1343bf6SKrzysztof Grobelny             *isSpareDeviceInUse;
317ac6a4445SGunnar Mills     }
318c1343bf6SKrzysztof Grobelny 
319c1343bf6SKrzysztof Grobelny     if (isRankSpareEnabled != nullptr)
320ac6a4445SGunnar Mills     {
321ac106bf6SEd Tanous         asyncResp->res.jsonValue[jsonPtr]["IsRankSpareEnabled"] =
322c1343bf6SKrzysztof Grobelny             *isRankSpareEnabled;
323ac6a4445SGunnar Mills     }
324c1343bf6SKrzysztof Grobelny 
325c1343bf6SKrzysztof Grobelny     if (maxAveragePowerLimitmW != nullptr)
326ac6a4445SGunnar Mills     {
327ac106bf6SEd Tanous         asyncResp->res.jsonValue[jsonPtr]["MaxTDPMilliWatts"] =
328c1343bf6SKrzysztof Grobelny             *maxAveragePowerLimitmW;
329ac6a4445SGunnar Mills     }
330c1343bf6SKrzysztof Grobelny 
331c1343bf6SKrzysztof Grobelny     if (configurationLocked != nullptr)
332ac6a4445SGunnar Mills     {
333ac106bf6SEd Tanous         asyncResp->res.jsonValue[jsonPtr]["ConfigurationLocked"] =
334c1343bf6SKrzysztof Grobelny             *configurationLocked;
335ac6a4445SGunnar Mills     }
336c1343bf6SKrzysztof Grobelny 
337c1343bf6SKrzysztof Grobelny     if (allowedMemoryModes != nullptr)
338ac6a4445SGunnar Mills     {
33980badf7cSJiaqing Zhao         constexpr const std::array<const char*, 3> values{"Volatile", "PMEM",
34080badf7cSJiaqing Zhao                                                           "Block"};
341ac6a4445SGunnar Mills 
342ac6a4445SGunnar Mills         for (const char* v : values)
343ac6a4445SGunnar Mills         {
344c1343bf6SKrzysztof Grobelny             if (allowedMemoryModes->ends_with(v))
345ac6a4445SGunnar Mills             {
346ac106bf6SEd Tanous                 asyncResp->res.jsonValue[jsonPtr]["OperatingMemoryModes"]
347ac106bf6SEd Tanous                     .push_back(v);
348ac6a4445SGunnar Mills                 break;
349ac6a4445SGunnar Mills             }
350ac6a4445SGunnar Mills         }
351ac6a4445SGunnar Mills     }
352c1343bf6SKrzysztof Grobelny 
353c1343bf6SKrzysztof Grobelny     if (memoryMedia != nullptr)
354ac6a4445SGunnar Mills     {
355ac6a4445SGunnar Mills         constexpr const std::array<const char*, 3> values{"DRAM", "NAND",
356ac6a4445SGunnar Mills                                                           "Intel3DXPoint"};
357ac6a4445SGunnar Mills 
358ac6a4445SGunnar Mills         for (const char* v : values)
359ac6a4445SGunnar Mills         {
360c1343bf6SKrzysztof Grobelny             if (memoryMedia->ends_with(v))
361ac6a4445SGunnar Mills             {
362ac106bf6SEd Tanous                 asyncResp->res.jsonValue[jsonPtr]["MemoryMedia"].push_back(v);
363ac6a4445SGunnar Mills                 break;
364ac6a4445SGunnar Mills             }
365ac6a4445SGunnar Mills         }
366ac6a4445SGunnar Mills     }
367c1343bf6SKrzysztof Grobelny 
368c1343bf6SKrzysztof Grobelny     if (configurationLockCapable != nullptr)
369ac6a4445SGunnar Mills     {
370ac106bf6SEd Tanous         asyncResp->res.jsonValue[jsonPtr]["SecurityCapabilities"]
371c1343bf6SKrzysztof Grobelny                                 ["ConfigurationLockCapable"] =
372c1343bf6SKrzysztof Grobelny             *configurationLockCapable;
373ac6a4445SGunnar Mills     }
374c1343bf6SKrzysztof Grobelny 
375c1343bf6SKrzysztof Grobelny     if (dataLockCapable != nullptr)
376ac6a4445SGunnar Mills     {
377bd79bce8SPatrick Williams         asyncResp->res
378bd79bce8SPatrick Williams             .jsonValue[jsonPtr]["SecurityCapabilities"]["DataLockCapable"] =
379bd79bce8SPatrick Williams             *dataLockCapable;
380ac6a4445SGunnar Mills     }
381c1343bf6SKrzysztof Grobelny 
382c1343bf6SKrzysztof Grobelny     if (passphraseCapable != nullptr)
383c1343bf6SKrzysztof Grobelny     {
384bd79bce8SPatrick Williams         asyncResp->res
385bd79bce8SPatrick Williams             .jsonValue[jsonPtr]["SecurityCapabilities"]["PassphraseCapable"] =
386bd79bce8SPatrick Williams             *passphraseCapable;
387c1343bf6SKrzysztof Grobelny     }
388c1343bf6SKrzysztof Grobelny 
389c1343bf6SKrzysztof Grobelny     if (maxPassphraseCount != nullptr)
390c1343bf6SKrzysztof Grobelny     {
391bd79bce8SPatrick Williams         asyncResp->res
392bd79bce8SPatrick Williams             .jsonValue[jsonPtr]["SecurityCapabilities"]["MaxPassphraseCount"] =
393bd79bce8SPatrick Williams             *maxPassphraseCount;
394c1343bf6SKrzysztof Grobelny     }
395c1343bf6SKrzysztof Grobelny 
396c1343bf6SKrzysztof Grobelny     if (passphraseLockLimit != nullptr)
397c1343bf6SKrzysztof Grobelny     {
398bd79bce8SPatrick Williams         asyncResp->res
399bd79bce8SPatrick Williams             .jsonValue[jsonPtr]["SecurityCapabilities"]["PassphraseLockLimit"] =
400bd79bce8SPatrick Williams             *passphraseLockLimit;
401ac6a4445SGunnar Mills     }
402ac6a4445SGunnar Mills }
403ac6a4445SGunnar Mills 
404bd79bce8SPatrick Williams inline void assembleDimmProperties(
405bd79bce8SPatrick Williams     std::string_view dimmId,
406ac106bf6SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
407d7f04fd9SNan Zhou     const dbus::utility::DBusPropertiesMap& properties,
408d7f04fd9SNan Zhou     const nlohmann::json::json_pointer& jsonPtr)
409ac6a4445SGunnar Mills {
410ac106bf6SEd Tanous     asyncResp->res.jsonValue[jsonPtr]["Id"] = dimmId;
411ac106bf6SEd Tanous     asyncResp->res.jsonValue[jsonPtr]["Name"] = "DIMM Slot";
412539d8c6bSEd Tanous     asyncResp->res.jsonValue[jsonPtr]["Status"]["State"] =
413539d8c6bSEd Tanous         resource::State::Enabled;
414539d8c6bSEd Tanous     asyncResp->res.jsonValue[jsonPtr]["Status"]["Health"] =
415539d8c6bSEd Tanous         resource::Health::OK;
416ac6a4445SGunnar Mills 
417c1343bf6SKrzysztof Grobelny     const uint16_t* memoryDataWidth = nullptr;
418c1343bf6SKrzysztof Grobelny     const size_t* memorySizeInKB = nullptr;
419c1343bf6SKrzysztof Grobelny     const std::string* partNumber = nullptr;
420c1343bf6SKrzysztof Grobelny     const std::string* serialNumber = nullptr;
421c1343bf6SKrzysztof Grobelny     const std::string* manufacturer = nullptr;
422c1343bf6SKrzysztof Grobelny     const uint16_t* revisionCode = nullptr;
423c1343bf6SKrzysztof Grobelny     const bool* present = nullptr;
424c1343bf6SKrzysztof Grobelny     const uint16_t* memoryTotalWidth = nullptr;
425c1343bf6SKrzysztof Grobelny     const std::string* ecc = nullptr;
426c1343bf6SKrzysztof Grobelny     const std::string* formFactor = nullptr;
427c1343bf6SKrzysztof Grobelny     const std::vector<uint16_t>* allowedSpeedsMT = nullptr;
4286995c1ceSGeorge Liu     const size_t* memoryAttributes = nullptr;
429c1343bf6SKrzysztof Grobelny     const uint16_t* memoryConfiguredSpeedInMhz = nullptr;
430c1343bf6SKrzysztof Grobelny     const std::string* memoryType = nullptr;
4316fde5971SJayaprakash Mutyala     const std::uint8_t* channel = nullptr;
4326fde5971SJayaprakash Mutyala     const std::uint8_t* memoryController = nullptr;
4336fde5971SJayaprakash Mutyala     const std::uint8_t* slot = nullptr;
4346fde5971SJayaprakash Mutyala     const std::uint8_t* socket = nullptr;
435c1343bf6SKrzysztof Grobelny     const std::string* sparePartNumber = nullptr;
436c1343bf6SKrzysztof Grobelny     const std::string* model = nullptr;
437c1343bf6SKrzysztof Grobelny     const std::string* locationCode = nullptr;
4387fe6d534SGeorge Liu     const bool* functional = nullptr;
439ac6a4445SGunnar Mills 
440c1343bf6SKrzysztof Grobelny     const bool success = sdbusplus::unpackPropertiesNoThrow(
441c1343bf6SKrzysztof Grobelny         dbus_utils::UnpackErrorPrinter(), properties, "MemoryDataWidth",
442c1343bf6SKrzysztof Grobelny         memoryDataWidth, "MemorySizeInKB", memorySizeInKB, "PartNumber",
443656472d9SNikhil Namjoshi         partNumber, "SerialNumber", serialNumber, "Manufacturer", manufacturer,
444656472d9SNikhil Namjoshi         "RevisionCode", revisionCode, "Present", present, "MemoryTotalWidth",
445656472d9SNikhil Namjoshi         memoryTotalWidth, "ECC", ecc, "FormFactor", formFactor,
446656472d9SNikhil Namjoshi         "AllowedSpeedsMT", allowedSpeedsMT, "MemoryAttributes",
447c1343bf6SKrzysztof Grobelny         memoryAttributes, "MemoryConfiguredSpeedInMhz",
448c1343bf6SKrzysztof Grobelny         memoryConfiguredSpeedInMhz, "MemoryType", memoryType, "Channel",
449c1343bf6SKrzysztof Grobelny         channel, "MemoryController", memoryController, "Slot", slot, "Socket",
450c1343bf6SKrzysztof Grobelny         socket, "SparePartNumber", sparePartNumber, "Model", model,
4517fe6d534SGeorge Liu         "LocationCode", locationCode, "Functional", functional);
452c1343bf6SKrzysztof Grobelny 
453c1343bf6SKrzysztof Grobelny     if (!success)
454ac6a4445SGunnar Mills     {
455ac106bf6SEd Tanous         messages::internalError(asyncResp->res);
456601af5edSChicago Duan         return;
457ac6a4445SGunnar Mills     }
458c1343bf6SKrzysztof Grobelny 
459c1343bf6SKrzysztof Grobelny     if (memoryDataWidth != nullptr)
460c1343bf6SKrzysztof Grobelny     {
461ac106bf6SEd Tanous         asyncResp->res.jsonValue[jsonPtr]["DataWidthBits"] = *memoryDataWidth;
462c1343bf6SKrzysztof Grobelny     }
463c1343bf6SKrzysztof Grobelny 
464c1343bf6SKrzysztof Grobelny     if (memorySizeInKB != nullptr)
465c1343bf6SKrzysztof Grobelny     {
466ac106bf6SEd Tanous         asyncResp->res.jsonValue[jsonPtr]["CapacityMiB"] =
467ac106bf6SEd Tanous             (*memorySizeInKB >> 10);
468c1343bf6SKrzysztof Grobelny     }
469c1343bf6SKrzysztof Grobelny 
470c1343bf6SKrzysztof Grobelny     if (partNumber != nullptr)
471c1343bf6SKrzysztof Grobelny     {
472ac106bf6SEd Tanous         asyncResp->res.jsonValue[jsonPtr]["PartNumber"] = *partNumber;
473c1343bf6SKrzysztof Grobelny     }
474c1343bf6SKrzysztof Grobelny 
475c1343bf6SKrzysztof Grobelny     if (serialNumber != nullptr)
476c1343bf6SKrzysztof Grobelny     {
477ac106bf6SEd Tanous         asyncResp->res.jsonValue[jsonPtr]["SerialNumber"] = *serialNumber;
478c1343bf6SKrzysztof Grobelny     }
479c1343bf6SKrzysztof Grobelny 
480c1343bf6SKrzysztof Grobelny     if (manufacturer != nullptr)
481c1343bf6SKrzysztof Grobelny     {
482ac106bf6SEd Tanous         asyncResp->res.jsonValue[jsonPtr]["Manufacturer"] = *manufacturer;
483c1343bf6SKrzysztof Grobelny     }
484c1343bf6SKrzysztof Grobelny 
485c1343bf6SKrzysztof Grobelny     if (revisionCode != nullptr)
486c1343bf6SKrzysztof Grobelny     {
487ac106bf6SEd Tanous         asyncResp->res.jsonValue[jsonPtr]["FirmwareRevision"] =
488c1343bf6SKrzysztof Grobelny             std::to_string(*revisionCode);
489ac6a4445SGunnar Mills     }
490c1343bf6SKrzysztof Grobelny 
491c1343bf6SKrzysztof Grobelny     if (present != nullptr && !*present)
4929a128eb3SJoshi-Mansi     {
493539d8c6bSEd Tanous         asyncResp->res.jsonValue[jsonPtr]["Status"]["State"] =
494539d8c6bSEd Tanous             resource::State::Absent;
4959a128eb3SJoshi-Mansi     }
496c1343bf6SKrzysztof Grobelny 
4977fe6d534SGeorge Liu     if (functional != nullptr)
4987fe6d534SGeorge Liu     {
4997fe6d534SGeorge Liu         if (!*functional)
5007fe6d534SGeorge Liu         {
5017fe6d534SGeorge Liu             asyncResp->res.jsonValue[jsonPtr]["Status"]["Health"] =
5027fe6d534SGeorge Liu                 resource::Health::Critical;
5037fe6d534SGeorge Liu         }
5047fe6d534SGeorge Liu     }
5057fe6d534SGeorge Liu 
506c1343bf6SKrzysztof Grobelny     if (memoryTotalWidth != nullptr)
507ac6a4445SGunnar Mills     {
508ac106bf6SEd Tanous         asyncResp->res.jsonValue[jsonPtr]["BusWidthBits"] = *memoryTotalWidth;
509ac6a4445SGunnar Mills     }
510c1343bf6SKrzysztof Grobelny 
511c1343bf6SKrzysztof Grobelny     if (ecc != nullptr)
512ac6a4445SGunnar Mills     {
513ac6a4445SGunnar Mills         constexpr const std::array<const char*, 4> values{
5149a5aceacSNan Zhou             "NoECC", "SingleBitECC", "MultiBitECC", "AddressParity"};
515ac6a4445SGunnar Mills 
516ac6a4445SGunnar Mills         for (const char* v : values)
517ac6a4445SGunnar Mills         {
518c1343bf6SKrzysztof Grobelny             if (ecc->ends_with(v))
519ac6a4445SGunnar Mills             {
520ac106bf6SEd Tanous                 asyncResp->res.jsonValue[jsonPtr]["ErrorCorrection"] = v;
521ac6a4445SGunnar Mills                 break;
522ac6a4445SGunnar Mills             }
523ac6a4445SGunnar Mills         }
524ac6a4445SGunnar Mills     }
525c1343bf6SKrzysztof Grobelny 
526c1343bf6SKrzysztof Grobelny     if (formFactor != nullptr)
527ac6a4445SGunnar Mills     {
528ac6a4445SGunnar Mills         constexpr const std::array<const char*, 11> values{
5299a5aceacSNan Zhou             "RDIMM",       "UDIMM",       "SO_DIMM",      "LRDIMM",
5309a5aceacSNan Zhou             "Mini_RDIMM",  "Mini_UDIMM",  "SO_RDIMM_72b", "SO_UDIMM_72b",
5319a5aceacSNan Zhou             "SO_DIMM_16b", "SO_DIMM_32b", "Die"};
532ac6a4445SGunnar Mills 
533ac6a4445SGunnar Mills         for (const char* v : values)
534ac6a4445SGunnar Mills         {
535c1343bf6SKrzysztof Grobelny             if (formFactor->ends_with(v))
536ac6a4445SGunnar Mills             {
537ac106bf6SEd Tanous                 asyncResp->res.jsonValue[jsonPtr]["BaseModuleType"] = v;
538ac6a4445SGunnar Mills                 break;
539ac6a4445SGunnar Mills             }
540ac6a4445SGunnar Mills         }
541ac6a4445SGunnar Mills     }
542c1343bf6SKrzysztof Grobelny 
543c1343bf6SKrzysztof Grobelny     if (allowedSpeedsMT != nullptr)
544ac6a4445SGunnar Mills     {
545d7f04fd9SNan Zhou         nlohmann::json& jValue =
546ac106bf6SEd Tanous             asyncResp->res.jsonValue[jsonPtr]["AllowedSpeedsMHz"];
547ac6a4445SGunnar Mills         jValue = nlohmann::json::array();
548c1343bf6SKrzysztof Grobelny         for (uint16_t subVal : *allowedSpeedsMT)
549ac6a4445SGunnar Mills         {
550ac6a4445SGunnar Mills             jValue.push_back(subVal);
551ac6a4445SGunnar Mills         }
552ac6a4445SGunnar Mills     }
553ac6a4445SGunnar Mills 
554c1343bf6SKrzysztof Grobelny     if (memoryAttributes != nullptr)
555ac6a4445SGunnar Mills     {
5566995c1ceSGeorge Liu         asyncResp->res.jsonValue[jsonPtr]["RankCount"] = *memoryAttributes;
557ac6a4445SGunnar Mills     }
558c1343bf6SKrzysztof Grobelny 
559c1343bf6SKrzysztof Grobelny     if (memoryConfiguredSpeedInMhz != nullptr)
560ac6a4445SGunnar Mills     {
561ac106bf6SEd Tanous         asyncResp->res.jsonValue[jsonPtr]["OperatingSpeedMhz"] =
562c1343bf6SKrzysztof Grobelny             *memoryConfiguredSpeedInMhz;
563ac6a4445SGunnar Mills     }
564c1343bf6SKrzysztof Grobelny 
565c1343bf6SKrzysztof Grobelny     if (memoryType != nullptr)
566ac6a4445SGunnar Mills     {
567313efb1cSGunnar Mills         std::string memoryDeviceType =
568c1343bf6SKrzysztof Grobelny             translateMemoryTypeToRedfish(*memoryType);
569313efb1cSGunnar Mills         // Values like "Unknown" or "Other" will return empty
570313efb1cSGunnar Mills         // so just leave off
571313efb1cSGunnar Mills         if (!memoryDeviceType.empty())
572ac6a4445SGunnar Mills         {
573ac106bf6SEd Tanous             asyncResp->res.jsonValue[jsonPtr]["MemoryDeviceType"] =
574d7f04fd9SNan Zhou                 memoryDeviceType;
575ac6a4445SGunnar Mills         }
576c1343bf6SKrzysztof Grobelny         if (memoryType->find("DDR") != std::string::npos)
577ac6a4445SGunnar Mills         {
578539d8c6bSEd Tanous             asyncResp->res.jsonValue[jsonPtr]["MemoryType"] =
579539d8c6bSEd Tanous                 memory::MemoryType::DRAM;
580ac6a4445SGunnar Mills         }
581c1343bf6SKrzysztof Grobelny         else if (memoryType->ends_with("Logical"))
582ac6a4445SGunnar Mills         {
583539d8c6bSEd Tanous             asyncResp->res.jsonValue[jsonPtr]["MemoryType"] =
584539d8c6bSEd Tanous                 memory::MemoryType::IntelOptane;
585ac6a4445SGunnar Mills         }
586ac6a4445SGunnar Mills     }
587c1343bf6SKrzysztof Grobelny 
588c1343bf6SKrzysztof Grobelny     if (channel != nullptr)
589ac6a4445SGunnar Mills     {
590ac106bf6SEd Tanous         asyncResp->res.jsonValue[jsonPtr]["MemoryLocation"]["Channel"] =
591ac106bf6SEd Tanous             *channel;
592c1343bf6SKrzysztof Grobelny     }
593c1343bf6SKrzysztof Grobelny 
594c1343bf6SKrzysztof Grobelny     if (memoryController != nullptr)
595ac6a4445SGunnar Mills     {
596bd79bce8SPatrick Williams         asyncResp->res
597bd79bce8SPatrick Williams             .jsonValue[jsonPtr]["MemoryLocation"]["MemoryController"] =
598bd79bce8SPatrick Williams             *memoryController;
599ac6a4445SGunnar Mills     }
600c1343bf6SKrzysztof Grobelny 
601c1343bf6SKrzysztof Grobelny     if (slot != nullptr)
602ee135e24SSunnySrivastava1984     {
603ac106bf6SEd Tanous         asyncResp->res.jsonValue[jsonPtr]["MemoryLocation"]["Slot"] = *slot;
604c1343bf6SKrzysztof Grobelny     }
605c1343bf6SKrzysztof Grobelny 
606c1343bf6SKrzysztof Grobelny     if (socket != nullptr)
607ee135e24SSunnySrivastava1984     {
608ac106bf6SEd Tanous         asyncResp->res.jsonValue[jsonPtr]["MemoryLocation"]["Socket"] = *socket;
609ee135e24SSunnySrivastava1984     }
610c1343bf6SKrzysztof Grobelny 
611c1343bf6SKrzysztof Grobelny     if (sparePartNumber != nullptr)
612ee135e24SSunnySrivastava1984     {
613ac106bf6SEd Tanous         asyncResp->res.jsonValue[jsonPtr]["SparePartNumber"] = *sparePartNumber;
614c1343bf6SKrzysztof Grobelny     }
615c1343bf6SKrzysztof Grobelny 
616c1343bf6SKrzysztof Grobelny     if (model != nullptr)
617ee135e24SSunnySrivastava1984     {
618ac106bf6SEd Tanous         asyncResp->res.jsonValue[jsonPtr]["Model"] = *model;
619ee135e24SSunnySrivastava1984     }
620c1343bf6SKrzysztof Grobelny 
621c1343bf6SKrzysztof Grobelny     if (locationCode != nullptr)
622ee135e24SSunnySrivastava1984     {
623bd79bce8SPatrick Williams         asyncResp->res
624bd79bce8SPatrick Williams             .jsonValue[jsonPtr]["Location"]["PartLocation"]["ServiceLabel"] =
625bd79bce8SPatrick Williams             *locationCode;
626ee135e24SSunnySrivastava1984     }
627c1343bf6SKrzysztof Grobelny 
628ac106bf6SEd Tanous     getPersistentMemoryProperties(asyncResp, properties, jsonPtr);
6299a5aceacSNan Zhou }
6309a5aceacSNan Zhou 
631bd79bce8SPatrick Williams inline void getDimmDataByService(
632bd79bce8SPatrick Williams     std::shared_ptr<bmcweb::AsyncResp> asyncResp, const std::string& dimmId,
633bd79bce8SPatrick Williams     const std::string& service, const std::string& objPath)
6349a5aceacSNan Zhou {
63562598e31SEd Tanous     BMCWEB_LOG_DEBUG("Get available system components.");
636deae6a78SEd Tanous     dbus::utility::getAllProperties(
637deae6a78SEd Tanous         service, objPath, "",
638ac106bf6SEd Tanous         [dimmId, asyncResp{std::move(asyncResp)}](
6395e7e2dc5SEd Tanous             const boost::system::error_code& ec,
6409a5aceacSNan Zhou             const dbus::utility::DBusPropertiesMap& properties) {
6419a5aceacSNan Zhou             if (ec)
6429a5aceacSNan Zhou             {
64362598e31SEd Tanous                 BMCWEB_LOG_DEBUG("DBUS response error");
644ac106bf6SEd Tanous                 messages::internalError(asyncResp->res);
6459a5aceacSNan Zhou                 return;
6469a5aceacSNan Zhou             }
647bd79bce8SPatrick Williams             assembleDimmProperties(dimmId, asyncResp, properties,
648bd79bce8SPatrick Williams                                    ""_json_pointer);
649c1343bf6SKrzysztof Grobelny         });
650ac6a4445SGunnar Mills }
651ac6a4445SGunnar Mills 
652ef00d7d4SNan Zhou inline void assembleDimmPartitionData(
653ac106bf6SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
654d7f04fd9SNan Zhou     const dbus::utility::DBusPropertiesMap& properties,
655d7f04fd9SNan Zhou     const nlohmann::json::json_pointer& regionPtr)
656ac6a4445SGunnar Mills {
657c1343bf6SKrzysztof Grobelny     const std::string* memoryClassification = nullptr;
658c1343bf6SKrzysztof Grobelny     const uint64_t* offsetInKiB = nullptr;
659c1343bf6SKrzysztof Grobelny     const std::string* partitionId = nullptr;
660c1343bf6SKrzysztof Grobelny     const bool* passphraseState = nullptr;
661c1343bf6SKrzysztof Grobelny     const uint64_t* sizeInKiB = nullptr;
662c1343bf6SKrzysztof Grobelny 
663c1343bf6SKrzysztof Grobelny     const bool success = sdbusplus::unpackPropertiesNoThrow(
664c1343bf6SKrzysztof Grobelny         dbus_utils::UnpackErrorPrinter(), properties, "MemoryClassification",
665c1343bf6SKrzysztof Grobelny         memoryClassification, "OffsetInKiB", offsetInKiB, "PartitionId",
666c1343bf6SKrzysztof Grobelny         partitionId, "PassphraseState", passphraseState, "SizeInKiB",
667c1343bf6SKrzysztof Grobelny         sizeInKiB);
668c1343bf6SKrzysztof Grobelny 
669c1343bf6SKrzysztof Grobelny     if (!success)
670c1343bf6SKrzysztof Grobelny     {
671ac106bf6SEd Tanous         messages::internalError(asyncResp->res);
672c1343bf6SKrzysztof Grobelny         return;
673c1343bf6SKrzysztof Grobelny     }
674c1343bf6SKrzysztof Grobelny 
675d7f04fd9SNan Zhou     nlohmann::json::object_t partition;
676c1343bf6SKrzysztof Grobelny 
677c1343bf6SKrzysztof Grobelny     if (memoryClassification != nullptr)
678ac6a4445SGunnar Mills     {
679c1343bf6SKrzysztof Grobelny         partition["MemoryClassification"] = *memoryClassification;
680ac6a4445SGunnar Mills     }
681ac6a4445SGunnar Mills 
682c1343bf6SKrzysztof Grobelny     if (offsetInKiB != nullptr)
683ac6a4445SGunnar Mills     {
684c1343bf6SKrzysztof Grobelny         partition["OffsetMiB"] = (*offsetInKiB >> 10);
685ac6a4445SGunnar Mills     }
686ac6a4445SGunnar Mills 
687c1343bf6SKrzysztof Grobelny     if (partitionId != nullptr)
688ac6a4445SGunnar Mills     {
689c1343bf6SKrzysztof Grobelny         partition["RegionId"] = *partitionId;
690c1343bf6SKrzysztof Grobelny     }
691c1343bf6SKrzysztof Grobelny 
692c1343bf6SKrzysztof Grobelny     if (passphraseState != nullptr)
693ac6a4445SGunnar Mills     {
694c1343bf6SKrzysztof Grobelny         partition["PassphraseEnabled"] = *passphraseState;
695ac6a4445SGunnar Mills     }
696c1343bf6SKrzysztof Grobelny 
697c1343bf6SKrzysztof Grobelny     if (sizeInKiB != nullptr)
698ac6a4445SGunnar Mills     {
699c1343bf6SKrzysztof Grobelny         partition["SizeMiB"] = (*sizeInKiB >> 10);
700ac6a4445SGunnar Mills     }
701c1343bf6SKrzysztof Grobelny 
702ac106bf6SEd Tanous     asyncResp->res.jsonValue[regionPtr].emplace_back(std::move(partition));
703ef00d7d4SNan Zhou }
704ef00d7d4SNan Zhou 
705ac106bf6SEd Tanous inline void getDimmPartitionData(std::shared_ptr<bmcweb::AsyncResp> asyncResp,
706ef00d7d4SNan Zhou                                  const std::string& service,
707ef00d7d4SNan Zhou                                  const std::string& path)
708ef00d7d4SNan Zhou {
709deae6a78SEd Tanous     dbus::utility::getAllProperties(
710deae6a78SEd Tanous         service, path,
711c1343bf6SKrzysztof Grobelny         "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition",
712ac106bf6SEd Tanous         [asyncResp{std::move(asyncResp)}](
7135e7e2dc5SEd Tanous             const boost::system::error_code& ec,
714ef00d7d4SNan Zhou             const dbus::utility::DBusPropertiesMap& properties) {
715ef00d7d4SNan Zhou             if (ec)
716ef00d7d4SNan Zhou             {
71762598e31SEd Tanous                 BMCWEB_LOG_DEBUG("DBUS response error");
718ac106bf6SEd Tanous                 messages::internalError(asyncResp->res);
719ef00d7d4SNan Zhou 
720ef00d7d4SNan Zhou                 return;
721ef00d7d4SNan Zhou             }
722d7f04fd9SNan Zhou             nlohmann::json::json_pointer regionPtr = "/Regions"_json_pointer;
723ac106bf6SEd Tanous             assembleDimmPartitionData(asyncResp, properties, regionPtr);
724c1343bf6SKrzysztof Grobelny         }
725ac6a4445SGunnar Mills 
726c1343bf6SKrzysztof Grobelny     );
727ac6a4445SGunnar Mills }
728ac6a4445SGunnar Mills 
729*6980011bSGeorge Liu inline void afterGetDimmData(
730*6980011bSGeorge Liu     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
731*6980011bSGeorge Liu     const std::string& dimmId, const boost::system::error_code& ec,
732*6980011bSGeorge Liu     const dbus::utility::MapperGetSubTreeResponse& subtree)
733ac6a4445SGunnar Mills {
734ac6a4445SGunnar Mills     if (ec)
735ac6a4445SGunnar Mills     {
736*6980011bSGeorge Liu         if (ec.value() != EBADR)
737*6980011bSGeorge Liu         {
738*6980011bSGeorge Liu             BMCWEB_LOG_ERROR("DBUS response error: {}", ec.value());
739ac106bf6SEd Tanous             messages::internalError(asyncResp->res);
740*6980011bSGeorge Liu         }
741ac6a4445SGunnar Mills         return;
742ac6a4445SGunnar Mills     }
743*6980011bSGeorge Liu 
744ac6a4445SGunnar Mills     bool found = false;
745*6980011bSGeorge Liu     for (const auto& [objectPath, serviceMap] : subtree)
746ac6a4445SGunnar Mills     {
747*6980011bSGeorge Liu         sdbusplus::message::object_path path(objectPath);
748*6980011bSGeorge Liu 
749*6980011bSGeorge Liu         bool dimmInterface = false;
750*6980011bSGeorge Liu         bool associationInterface = false;
751*6980011bSGeorge Liu         /* Note: Multiple D-Bus objects can provide details for the Memory
752*6980011bSGeorge Liu          * object: 1) Dimm is the primary object 2) Additional partitions could
753*6980011bSGeorge Liu          * exist per Dimm. Only consider the object found if the Dimm is found.
754*6980011bSGeorge Liu          */
755*6980011bSGeorge Liu         for (const auto& [serviceName, interfaceList] : serviceMap)
756ac6a4445SGunnar Mills         {
757*6980011bSGeorge Liu             for (const auto& interface : interfaceList)
758ac6a4445SGunnar Mills             {
759*6980011bSGeorge Liu                 if (interface == "xyz.openbmc_project.Inventory.Item.Dimm" &&
76076686dccSNan Zhou                     path.filename() == dimmId)
761b9d36b47SEd Tanous                 {
762*6980011bSGeorge Liu                     // Found the single Dimm
763*6980011bSGeorge Liu                     getDimmDataByService(asyncResp, dimmId, serviceName,
764*6980011bSGeorge Liu                                          objectPath);
765*6980011bSGeorge Liu                     dimmInterface = true;
766ac6a4445SGunnar Mills                     found = true;
767ac6a4445SGunnar Mills                 }
768*6980011bSGeorge Liu                 else if (interface ==
769*6980011bSGeorge Liu                          "xyz.openbmc_project.Association.Definitions")
770*6980011bSGeorge Liu                 {
771*6980011bSGeorge Liu                     /* Object has associations. If this object is also a Dimm
772*6980011bSGeorge Liu                      * then the association might provide the LED state
773*6980011bSGeorge Liu                      * information. After all interfaces for this object have
774*6980011bSGeorge Liu                      * been checked the LED information will be gathered if the
775*6980011bSGeorge Liu                      * object was a Dimm
776*6980011bSGeorge Liu                      */
777*6980011bSGeorge Liu                     associationInterface = true;
778*6980011bSGeorge Liu                 }
779*6980011bSGeorge Liu                 else if (
780*6980011bSGeorge Liu                     interface ==
78176686dccSNan Zhou                         "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition" &&
78276686dccSNan Zhou                     path.parent_path().filename() == dimmId)
783ac6a4445SGunnar Mills                 {
784*6980011bSGeorge Liu                     // partitions are separate as there can be multiple per
785*6980011bSGeorge Liu                     // device, i.e.
786*6980011bSGeorge Liu                     // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition1
787*6980011bSGeorge Liu                     // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition2
788*6980011bSGeorge Liu                     getDimmPartitionData(asyncResp, serviceName, objectPath);
789ac6a4445SGunnar Mills                 }
790ac6a4445SGunnar Mills             }
791ac6a4445SGunnar Mills         }
792*6980011bSGeorge Liu 
793*6980011bSGeorge Liu         /* If a Dimm has an Association check if it has a LED */
794*6980011bSGeorge Liu         if (associationInterface && dimmInterface)
795*6980011bSGeorge Liu         {
796*6980011bSGeorge Liu             getLocationIndicatorActive(asyncResp, objectPath);
797b9d36b47SEd Tanous         }
798*6980011bSGeorge Liu     }
799*6980011bSGeorge Liu 
800ac6a4445SGunnar Mills     if (!found)
801ac6a4445SGunnar Mills     {
802*6980011bSGeorge Liu         // Dimm object not found
803ac106bf6SEd Tanous         messages::resourceNotFound(asyncResp->res, "Memory", dimmId);
8041a1d5d6dSNan Zhou         return;
805ac6a4445SGunnar Mills     }
8061a1d5d6dSNan Zhou     // Set @odata only if object is found
807ac106bf6SEd Tanous     asyncResp->res.jsonValue["@odata.type"] = "#Memory.v1_11_0.Memory";
808ac106bf6SEd Tanous     asyncResp->res.jsonValue["@odata.id"] =
809253f11b8SEd Tanous         boost::urls::format("/redfish/v1/Systems/{}/Memory/{}",
810253f11b8SEd Tanous                             BMCWEB_REDFISH_SYSTEM_URI_NAME, dimmId);
811*6980011bSGeorge Liu }
812*6980011bSGeorge Liu 
813*6980011bSGeorge Liu inline void getDimmData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
814*6980011bSGeorge Liu                         const std::string& dimmId)
815*6980011bSGeorge Liu {
816*6980011bSGeorge Liu     BMCWEB_LOG_DEBUG("Get dimm path for {}", dimmId);
817*6980011bSGeorge Liu     constexpr std::array<std::string_view, 2> interfaces = {
818*6980011bSGeorge Liu         "xyz.openbmc_project.Inventory.Item.Dimm",
819*6980011bSGeorge Liu         "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition"};
820*6980011bSGeorge Liu 
821*6980011bSGeorge Liu     dbus::utility::getSubTree(
822*6980011bSGeorge Liu         "/xyz/openbmc_project/inventory", 0, interfaces,
823*6980011bSGeorge Liu         [asyncResp,
824*6980011bSGeorge Liu          dimmId](const boost::system::error_code& ec,
825*6980011bSGeorge Liu                  const dbus::utility::MapperGetSubTreeResponse& subtree) {
826*6980011bSGeorge Liu             afterGetDimmData(asyncResp, dimmId, ec, subtree);
827e99073f5SGeorge Liu         });
828ac6a4445SGunnar Mills }
829ac6a4445SGunnar Mills 
830*6980011bSGeorge Liu inline void handleSetDimmData(
831*6980011bSGeorge Liu     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
832*6980011bSGeorge Liu     bool locationIndicatorActive, const std::string& dimmPath)
833*6980011bSGeorge Liu {
834*6980011bSGeorge Liu     setLocationIndicatorActive(asyncResp, dimmPath, locationIndicatorActive);
835*6980011bSGeorge Liu }
836*6980011bSGeorge Liu 
837*6980011bSGeorge Liu inline void afterGetValidDimmPath(
838*6980011bSGeorge Liu     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
839*6980011bSGeorge Liu     const std::string& dimmId, const boost::system::error_code& ec,
840*6980011bSGeorge Liu     const dbus::utility::MapperGetSubTreePathsResponse& subtree,
841*6980011bSGeorge Liu     const std::function<void(const std::string& dimmPath)>& callback)
842*6980011bSGeorge Liu {
843*6980011bSGeorge Liu     if (ec)
844*6980011bSGeorge Liu     {
845*6980011bSGeorge Liu         if (ec.value() == EBADR)
846*6980011bSGeorge Liu         {
847*6980011bSGeorge Liu             /* Need to report error for PATCH */
848*6980011bSGeorge Liu             BMCWEB_LOG_WARNING("Dimm not found in inventory");
849*6980011bSGeorge Liu             messages::resourceNotFound(asyncResp->res, "Memory", dimmId);
850*6980011bSGeorge Liu         }
851*6980011bSGeorge Liu         else
852*6980011bSGeorge Liu         {
853*6980011bSGeorge Liu             BMCWEB_LOG_ERROR("DBUS response error: {}", ec.value());
854*6980011bSGeorge Liu             messages::internalError(asyncResp->res);
855*6980011bSGeorge Liu         }
856*6980011bSGeorge Liu         return;
857*6980011bSGeorge Liu     }
858*6980011bSGeorge Liu 
859*6980011bSGeorge Liu     for (const auto& objectPath : subtree)
860*6980011bSGeorge Liu     {
861*6980011bSGeorge Liu         // Ignore any objects which don't end with our desired dimm name
862*6980011bSGeorge Liu         sdbusplus::message::object_path path(objectPath);
863*6980011bSGeorge Liu         if (path.filename() == dimmId)
864*6980011bSGeorge Liu         {
865*6980011bSGeorge Liu             callback(path);
866*6980011bSGeorge Liu             return;
867*6980011bSGeorge Liu         }
868*6980011bSGeorge Liu     }
869*6980011bSGeorge Liu 
870*6980011bSGeorge Liu     // Object not found
871*6980011bSGeorge Liu     messages::resourceNotFound(asyncResp->res, "Memory", dimmId);
872*6980011bSGeorge Liu }
873*6980011bSGeorge Liu 
874*6980011bSGeorge Liu inline void getValidDimmPath(
875*6980011bSGeorge Liu     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
876*6980011bSGeorge Liu     const std::string& dimmId,
877*6980011bSGeorge Liu     std::function<void(const std::string& dimmPath)>&& callback)
878*6980011bSGeorge Liu {
879*6980011bSGeorge Liu     BMCWEB_LOG_DEBUG("Get dimm path for {}", dimmId);
880*6980011bSGeorge Liu     constexpr std::array<std::string_view, 1> interfaces = {
881*6980011bSGeorge Liu         "xyz.openbmc_project.Inventory.Item.Dimm"};
882*6980011bSGeorge Liu 
883*6980011bSGeorge Liu     dbus::utility::getSubTreePaths(
884*6980011bSGeorge Liu         "/xyz/openbmc_project/inventory", 0, interfaces,
885*6980011bSGeorge Liu         [asyncResp, dimmId, callback{std::move(callback)}](
886*6980011bSGeorge Liu             const boost::system::error_code& ec,
887*6980011bSGeorge Liu             const dbus::utility::MapperGetSubTreePathsResponse& subtree) {
888*6980011bSGeorge Liu             afterGetValidDimmPath(asyncResp, dimmId, ec, subtree, callback);
889*6980011bSGeorge Liu         });
890*6980011bSGeorge Liu }
891*6980011bSGeorge Liu 
892*6980011bSGeorge Liu inline void handleMemoryPatch(
893*6980011bSGeorge Liu     App& app, const crow::Request& req,
894*6980011bSGeorge Liu     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
895*6980011bSGeorge Liu     const std::string& systemName, const std::string& dimmId)
896*6980011bSGeorge Liu {
897*6980011bSGeorge Liu     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
898*6980011bSGeorge Liu     {
899*6980011bSGeorge Liu         return;
900*6980011bSGeorge Liu     }
901*6980011bSGeorge Liu 
902*6980011bSGeorge Liu     if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
903*6980011bSGeorge Liu     {
904*6980011bSGeorge Liu         // Option currently returns no systems.  TBD
905*6980011bSGeorge Liu         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
906*6980011bSGeorge Liu                                    systemName);
907*6980011bSGeorge Liu         return;
908*6980011bSGeorge Liu     }
909*6980011bSGeorge Liu 
910*6980011bSGeorge Liu     if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
911*6980011bSGeorge Liu     {
912*6980011bSGeorge Liu         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
913*6980011bSGeorge Liu                                    systemName);
914*6980011bSGeorge Liu         return;
915*6980011bSGeorge Liu     }
916*6980011bSGeorge Liu 
917*6980011bSGeorge Liu     std::optional<bool> locationIndicatorActive;
918*6980011bSGeorge Liu     if (!json_util::readJsonPatch(                             //
919*6980011bSGeorge Liu             req, asyncResp->res,                               //
920*6980011bSGeorge Liu             "LocationIndicatorActive", locationIndicatorActive //
921*6980011bSGeorge Liu             ))
922*6980011bSGeorge Liu     {
923*6980011bSGeorge Liu         return;
924*6980011bSGeorge Liu     }
925*6980011bSGeorge Liu 
926*6980011bSGeorge Liu     if (locationIndicatorActive)
927*6980011bSGeorge Liu     {
928*6980011bSGeorge Liu         getValidDimmPath(asyncResp, dimmId,
929*6980011bSGeorge Liu                          std::bind_front(handleSetDimmData, asyncResp,
930*6980011bSGeorge Liu                                          *locationIndicatorActive));
931*6980011bSGeorge Liu     }
932*6980011bSGeorge Liu }
933*6980011bSGeorge Liu 
934*6980011bSGeorge Liu inline void handleMemoryGet(App& app, const crow::Request& req,
935*6980011bSGeorge Liu                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
936*6980011bSGeorge Liu                             const std::string& systemName,
937*6980011bSGeorge Liu                             const std::string& dimmId)
938*6980011bSGeorge Liu {
939*6980011bSGeorge Liu     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
940*6980011bSGeorge Liu     {
941*6980011bSGeorge Liu         return;
942*6980011bSGeorge Liu     }
943*6980011bSGeorge Liu 
944*6980011bSGeorge Liu     if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
945*6980011bSGeorge Liu     {
946*6980011bSGeorge Liu         // Option currently returns no systems.  TBD
947*6980011bSGeorge Liu         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
948*6980011bSGeorge Liu                                    systemName);
949*6980011bSGeorge Liu         return;
950*6980011bSGeorge Liu     }
951*6980011bSGeorge Liu 
952*6980011bSGeorge Liu     if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
953*6980011bSGeorge Liu     {
954*6980011bSGeorge Liu         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
955*6980011bSGeorge Liu                                    systemName);
956*6980011bSGeorge Liu         return;
957*6980011bSGeorge Liu     }
958*6980011bSGeorge Liu 
959*6980011bSGeorge Liu     getDimmData(asyncResp, dimmId);
960*6980011bSGeorge Liu }
961*6980011bSGeorge Liu 
9627e860f15SJohn Edward Broadbent inline void requestRoutesMemoryCollection(App& app)
963ac6a4445SGunnar Mills {
964ac6a4445SGunnar Mills     /**
965ac6a4445SGunnar Mills      * Functions triggers appropriate requests on DBus
966ac6a4445SGunnar Mills      */
96722d268cbSEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Memory/")
968ed398213SEd Tanous         .privileges(redfish::privileges::getMemoryCollection)
9697e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
97045ca1b86SEd Tanous             [&app](const crow::Request& req,
97122d268cbSEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
97222d268cbSEd Tanous                    const std::string& systemName) {
9733ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
97445ca1b86SEd Tanous                 {
97545ca1b86SEd Tanous                     return;
97645ca1b86SEd Tanous                 }
97725b54dbaSEd Tanous                 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
9787f3e84a1SEd Tanous                 {
9797f3e84a1SEd Tanous                     // Option currently returns no systems.  TBD
9807f3e84a1SEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
9817f3e84a1SEd Tanous                                                systemName);
9827f3e84a1SEd Tanous                     return;
9837f3e84a1SEd Tanous                 }
984253f11b8SEd Tanous                 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
98522d268cbSEd Tanous                 {
98622d268cbSEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
98722d268cbSEd Tanous                                                systemName);
98822d268cbSEd Tanous                     return;
98922d268cbSEd Tanous                 }
99022d268cbSEd Tanous 
9918d1b46d7Szhanghch05                 asyncResp->res.jsonValue["@odata.type"] =
9928d1b46d7Szhanghch05                     "#MemoryCollection.MemoryCollection";
9938d1b46d7Szhanghch05                 asyncResp->res.jsonValue["Name"] = "Memory Module Collection";
994bd79bce8SPatrick Williams                 asyncResp->res.jsonValue["@odata.id"] =
995bd79bce8SPatrick Williams                     boost::urls::format("/redfish/v1/Systems/{}/Memory",
996bd79bce8SPatrick Williams                                         BMCWEB_REDFISH_SYSTEM_URI_NAME);
997ac6a4445SGunnar Mills 
9987a1dbc48SGeorge Liu                 constexpr std::array<std::string_view, 1> interfaces{
9997a1dbc48SGeorge Liu                     "xyz.openbmc_project.Inventory.Item.Dimm"};
100005030b8eSGunnar Mills                 collection_util::getCollectionMembers(
1001253f11b8SEd Tanous                     asyncResp,
1002253f11b8SEd Tanous                     boost::urls::format("/redfish/v1/Systems/{}/Memory",
1003253f11b8SEd Tanous                                         BMCWEB_REDFISH_SYSTEM_URI_NAME),
100436b5f1edSLakshmi Yadlapati                     interfaces, "/xyz/openbmc_project/inventory");
10057e860f15SJohn Edward Broadbent             });
1006ac6a4445SGunnar Mills }
1007ac6a4445SGunnar Mills 
10087e860f15SJohn Edward Broadbent inline void requestRoutesMemory(App& app)
10097e860f15SJohn Edward Broadbent {
1010ac6a4445SGunnar Mills     /**
1011ac6a4445SGunnar Mills      * Functions triggers appropriate requests on DBus
1012ac6a4445SGunnar Mills      */
101322d268cbSEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Memory/<str>/")
1014ed398213SEd Tanous         .privileges(redfish::privileges::getMemory)
10157e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
1016*6980011bSGeorge Liu             std::bind_front(handleMemoryGet, std::ref(app)));
10177f3e84a1SEd Tanous 
1018*6980011bSGeorge Liu     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Memory/<str>/")
1019*6980011bSGeorge Liu         .privileges(redfish::privileges::patchMemory)
1020*6980011bSGeorge Liu         .methods(boost::beast::http::verb::patch)(
1021*6980011bSGeorge Liu             std::bind_front(handleMemoryPatch, std::ref(app)));
1022ac6a4445SGunnar Mills }
1023ac6a4445SGunnar Mills 
1024ac6a4445SGunnar Mills } // namespace redfish
1025