xref: /openbmc/bmcweb/features/redfish/lib/memory.hpp (revision ed3982131dcef2b499da36e674d2d21b2289ef29)
1ac6a4445SGunnar Mills /*
2ac6a4445SGunnar Mills // Copyright (c) 2018 Intel Corporation
3ac6a4445SGunnar Mills //
4ac6a4445SGunnar Mills // Licensed under the Apache License, Version 2.0 (the "License");
5ac6a4445SGunnar Mills // you may not use this file except in compliance with the License.
6ac6a4445SGunnar Mills // You may obtain a copy of the License at
7ac6a4445SGunnar Mills //
8ac6a4445SGunnar Mills //      http://www.apache.org/licenses/LICENSE-2.0
9ac6a4445SGunnar Mills //
10ac6a4445SGunnar Mills // Unless required by applicable law or agreed to in writing, software
11ac6a4445SGunnar Mills // distributed under the License is distributed on an "AS IS" BASIS,
12ac6a4445SGunnar Mills // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ac6a4445SGunnar Mills // See the License for the specific language governing permissions and
14ac6a4445SGunnar Mills // limitations under the License.
15ac6a4445SGunnar Mills */
16ac6a4445SGunnar Mills #pragma once
17ac6a4445SGunnar Mills 
18ac6a4445SGunnar Mills #include "health.hpp"
19ac6a4445SGunnar Mills 
207e860f15SJohn Edward Broadbent #include <app.hpp>
21ac6a4445SGunnar Mills #include <boost/container/flat_map.hpp>
22ac6a4445SGunnar Mills #include <boost/format.hpp>
23*ed398213SEd Tanous #include <registries/privilege_registry.hpp>
24ac6a4445SGunnar Mills #include <utils/collection.hpp>
25ac6a4445SGunnar Mills #include <utils/json_utils.hpp>
26ac6a4445SGunnar Mills 
27ac6a4445SGunnar Mills namespace redfish
28ac6a4445SGunnar Mills {
29ac6a4445SGunnar Mills 
30ac6a4445SGunnar Mills using DimmProperty =
31ac6a4445SGunnar Mills     std::variant<std::string, std::vector<uint32_t>, std::vector<uint16_t>,
32ac6a4445SGunnar Mills                  uint64_t, uint32_t, uint16_t, uint8_t, bool>;
33ac6a4445SGunnar Mills 
34ac6a4445SGunnar Mills using DimmProperties = boost::container::flat_map<std::string, DimmProperty>;
35ac6a4445SGunnar Mills 
36313efb1cSGunnar Mills inline std::string translateMemoryTypeToRedfish(const std::string& memoryType)
37313efb1cSGunnar Mills {
38313efb1cSGunnar Mills     if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR")
39313efb1cSGunnar Mills     {
40313efb1cSGunnar Mills         return "DDR";
41313efb1cSGunnar Mills     }
42313efb1cSGunnar Mills     if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR2")
43313efb1cSGunnar Mills     {
44313efb1cSGunnar Mills         return "DDR2";
45313efb1cSGunnar Mills     }
46313efb1cSGunnar Mills     if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR3")
47313efb1cSGunnar Mills     {
48313efb1cSGunnar Mills         return "DDR3";
49313efb1cSGunnar Mills     }
50313efb1cSGunnar Mills     if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR4")
51313efb1cSGunnar Mills     {
52313efb1cSGunnar Mills         return "DDR4";
53313efb1cSGunnar Mills     }
54313efb1cSGunnar Mills     if (memoryType ==
55313efb1cSGunnar Mills         "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR4E_SDRAM")
56313efb1cSGunnar Mills     {
57313efb1cSGunnar Mills         return "DDR4E_SDRAM";
58313efb1cSGunnar Mills     }
59313efb1cSGunnar Mills     if (memoryType ==
60313efb1cSGunnar Mills         "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.LPDDR4_SDRAM")
61313efb1cSGunnar Mills     {
62313efb1cSGunnar Mills         return "LPDDR4_SDRAM";
63313efb1cSGunnar Mills     }
64313efb1cSGunnar Mills     if (memoryType ==
65313efb1cSGunnar Mills         "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.LPDDR3_SDRAM")
66313efb1cSGunnar Mills     {
67313efb1cSGunnar Mills         return "LPDDR3_SDRAM";
68313efb1cSGunnar Mills     }
69313efb1cSGunnar Mills     if (memoryType ==
70313efb1cSGunnar Mills         "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR2_SDRAM_FB_DIMM")
71313efb1cSGunnar Mills     {
72313efb1cSGunnar Mills         return "DDR2_SDRAM_FB_DIMM";
73313efb1cSGunnar Mills     }
74313efb1cSGunnar Mills     if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR2_"
75313efb1cSGunnar Mills                       "SDRAM_FB_DIMM_PROB")
76313efb1cSGunnar Mills     {
77313efb1cSGunnar Mills         return "DDR2_SDRAM_FB_DIMM_PROBE";
78313efb1cSGunnar Mills     }
79313efb1cSGunnar Mills     if (memoryType ==
80313efb1cSGunnar Mills         "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR_SGRAM")
81313efb1cSGunnar Mills     {
82313efb1cSGunnar Mills         return "DDR_SGRAM";
83313efb1cSGunnar Mills     }
84313efb1cSGunnar Mills     if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.ROM")
85313efb1cSGunnar Mills     {
86313efb1cSGunnar Mills         return "ROM";
87313efb1cSGunnar Mills     }
88313efb1cSGunnar Mills     if (memoryType ==
89313efb1cSGunnar Mills         "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.SDRAM")
90313efb1cSGunnar Mills     {
91313efb1cSGunnar Mills         return "SDRAM";
92313efb1cSGunnar Mills     }
93313efb1cSGunnar Mills     if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.EDO")
94313efb1cSGunnar Mills     {
95313efb1cSGunnar Mills         return "EDO";
96313efb1cSGunnar Mills     }
97313efb1cSGunnar Mills     if (memoryType ==
98313efb1cSGunnar Mills         "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.FastPageMode")
99313efb1cSGunnar Mills     {
100313efb1cSGunnar Mills         return "FastPageMode";
101313efb1cSGunnar Mills     }
102313efb1cSGunnar Mills     if (memoryType ==
103313efb1cSGunnar Mills         "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.PipelinedNibble")
104313efb1cSGunnar Mills     {
105313efb1cSGunnar Mills         return "PipelinedNibble";
106313efb1cSGunnar Mills     }
107313efb1cSGunnar Mills     if (memoryType ==
108313efb1cSGunnar Mills         "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.Logical")
109313efb1cSGunnar Mills     {
110313efb1cSGunnar Mills         return "Logical";
111313efb1cSGunnar Mills     }
112313efb1cSGunnar Mills     if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.HBM")
113313efb1cSGunnar Mills     {
114313efb1cSGunnar Mills         return "HBM";
115313efb1cSGunnar Mills     }
116313efb1cSGunnar Mills     if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.HBM2")
117313efb1cSGunnar Mills     {
118313efb1cSGunnar Mills         return "HBM2";
119313efb1cSGunnar Mills     }
120313efb1cSGunnar Mills     // This is values like Other or Unknown
121313efb1cSGunnar Mills     // Also D-Bus values:
122313efb1cSGunnar Mills     // DRAM
123313efb1cSGunnar Mills     // EDRAM
124313efb1cSGunnar Mills     // VRAM
125313efb1cSGunnar Mills     // SRAM
126313efb1cSGunnar Mills     // RAM
127313efb1cSGunnar Mills     // FLASH
128313efb1cSGunnar Mills     // EEPROM
129313efb1cSGunnar Mills     // FEPROM
130313efb1cSGunnar Mills     // EPROM
131313efb1cSGunnar Mills     // CDRAM
132313efb1cSGunnar Mills     // ThreeDRAM
133313efb1cSGunnar Mills     // RDRAM
134313efb1cSGunnar Mills     // FBD2
135313efb1cSGunnar Mills     // LPDDR_SDRAM
136313efb1cSGunnar Mills     // LPDDR2_SDRAM
137313efb1cSGunnar Mills     return "";
138313efb1cSGunnar Mills }
139313efb1cSGunnar Mills 
1408d1b46d7Szhanghch05 inline void dimmPropToHex(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
141ac6a4445SGunnar Mills                           const char* key,
142ac6a4445SGunnar Mills                           const std::pair<std::string, DimmProperty>& property)
143ac6a4445SGunnar Mills {
144ac6a4445SGunnar Mills     const uint16_t* value = std::get_if<uint16_t>(&property.second);
145ac6a4445SGunnar Mills     if (value == nullptr)
146ac6a4445SGunnar Mills     {
147ac6a4445SGunnar Mills         messages::internalError(aResp->res);
148ac6a4445SGunnar Mills         BMCWEB_LOG_DEBUG << "Invalid property type for " << property.first;
149ac6a4445SGunnar Mills         return;
150ac6a4445SGunnar Mills     }
151ac6a4445SGunnar Mills 
152ac6a4445SGunnar Mills     aResp->res.jsonValue[key] = (boost::format("0x%04x") % *value).str();
153ac6a4445SGunnar Mills }
154ac6a4445SGunnar Mills 
1558d1b46d7Szhanghch05 inline void getPersistentMemoryProperties(
1568d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& aResp,
157ac6a4445SGunnar Mills     const DimmProperties& properties)
158ac6a4445SGunnar Mills {
159ac6a4445SGunnar Mills     for (const auto& property : properties)
160ac6a4445SGunnar Mills     {
161ac6a4445SGunnar Mills         if (property.first == "ModuleManufacturerID")
162ac6a4445SGunnar Mills         {
163ac6a4445SGunnar Mills             dimmPropToHex(aResp, "ModuleManufacturerID", property);
164ac6a4445SGunnar Mills         }
165ac6a4445SGunnar Mills         else if (property.first == "ModuleProductID")
166ac6a4445SGunnar Mills         {
167ac6a4445SGunnar Mills             dimmPropToHex(aResp, "ModuleProductID", property);
168ac6a4445SGunnar Mills         }
169ac6a4445SGunnar Mills         else if (property.first == "SubsystemVendorID")
170ac6a4445SGunnar Mills         {
171ac6a4445SGunnar Mills             dimmPropToHex(aResp, "MemorySubsystemControllerManufacturerID",
172ac6a4445SGunnar Mills                           property);
173ac6a4445SGunnar Mills         }
174ac6a4445SGunnar Mills         else if (property.first == "SubsystemDeviceID")
175ac6a4445SGunnar Mills         {
176ac6a4445SGunnar Mills             dimmPropToHex(aResp, "MemorySubsystemControllerProductID",
177ac6a4445SGunnar Mills                           property);
178ac6a4445SGunnar Mills         }
179ac6a4445SGunnar Mills         else if (property.first == "VolatileRegionSizeLimitInKiB")
180ac6a4445SGunnar Mills         {
181ac6a4445SGunnar Mills             const uint64_t* value = std::get_if<uint64_t>(&property.second);
182ac6a4445SGunnar Mills 
183ac6a4445SGunnar Mills             if (value == nullptr)
184ac6a4445SGunnar Mills             {
185ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
186ac6a4445SGunnar Mills                 BMCWEB_LOG_DEBUG << "Invalid property type for "
187ac6a4445SGunnar Mills                                     "VolatileRegionSizeLimitKiB";
188601af5edSChicago Duan                 return;
189ac6a4445SGunnar Mills             }
190ac6a4445SGunnar Mills             aResp->res.jsonValue["VolatileRegionSizeLimitMiB"] = (*value) >> 10;
191ac6a4445SGunnar Mills         }
192ac6a4445SGunnar Mills         else if (property.first == "PmRegionSizeLimitInKiB")
193ac6a4445SGunnar Mills         {
194ac6a4445SGunnar Mills             const uint64_t* value = std::get_if<uint64_t>(&property.second);
195ac6a4445SGunnar Mills 
196ac6a4445SGunnar Mills             if (value == nullptr)
197ac6a4445SGunnar Mills             {
198ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
199ac6a4445SGunnar Mills                 BMCWEB_LOG_DEBUG
200ac6a4445SGunnar Mills                     << "Invalid property type for PmRegioSizeLimitKiB";
201601af5edSChicago Duan                 return;
202ac6a4445SGunnar Mills             }
203ac6a4445SGunnar Mills             aResp->res.jsonValue["PersistentRegionSizeLimitMiB"] =
204ac6a4445SGunnar Mills                 (*value) >> 10;
205ac6a4445SGunnar Mills         }
206ac6a4445SGunnar Mills         else if (property.first == "VolatileSizeInKiB")
207ac6a4445SGunnar Mills         {
208ac6a4445SGunnar Mills             const uint64_t* value = std::get_if<uint64_t>(&property.second);
209ac6a4445SGunnar Mills 
210ac6a4445SGunnar Mills             if (value == nullptr)
211ac6a4445SGunnar Mills             {
212ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
213ac6a4445SGunnar Mills                 BMCWEB_LOG_DEBUG
214ac6a4445SGunnar Mills                     << "Invalid property type for VolatileSizeInKiB";
215601af5edSChicago Duan                 return;
216ac6a4445SGunnar Mills             }
217ac6a4445SGunnar Mills             aResp->res.jsonValue["VolatileSizeMiB"] = (*value) >> 10;
218ac6a4445SGunnar Mills         }
219ac6a4445SGunnar Mills         else if (property.first == "PmSizeInKiB")
220ac6a4445SGunnar Mills         {
221ac6a4445SGunnar Mills             const uint64_t* value = std::get_if<uint64_t>(&property.second);
222ac6a4445SGunnar Mills             if (value == nullptr)
223ac6a4445SGunnar Mills             {
224ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
225ac6a4445SGunnar Mills                 BMCWEB_LOG_DEBUG << "Invalid property type for PmSizeInKiB";
226601af5edSChicago Duan                 return;
227ac6a4445SGunnar Mills             }
228ac6a4445SGunnar Mills             aResp->res.jsonValue["NonVolatileSizeMiB"] = (*value) >> 10;
229ac6a4445SGunnar Mills         }
230ac6a4445SGunnar Mills         else if (property.first == "CacheSizeInKB")
231ac6a4445SGunnar Mills         {
232ac6a4445SGunnar Mills             const uint64_t* value = std::get_if<uint64_t>(&property.second);
233ac6a4445SGunnar Mills             if (value == nullptr)
234ac6a4445SGunnar Mills             {
235ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
236ac6a4445SGunnar Mills                 BMCWEB_LOG_DEBUG << "Invalid property type for CacheSizeInKB";
237601af5edSChicago Duan                 return;
238ac6a4445SGunnar Mills             }
239ac6a4445SGunnar Mills             aResp->res.jsonValue["CacheSizeMiB"] = (*value >> 10);
240ac6a4445SGunnar Mills         }
241ac6a4445SGunnar Mills 
242ac6a4445SGunnar Mills         else if (property.first == "VoltaileRegionMaxSizeInKib")
243ac6a4445SGunnar Mills         {
244ac6a4445SGunnar Mills             const uint64_t* value = std::get_if<uint64_t>(&property.second);
245ac6a4445SGunnar Mills 
246ac6a4445SGunnar Mills             if (value == nullptr)
247ac6a4445SGunnar Mills             {
248ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
249ac6a4445SGunnar Mills                 BMCWEB_LOG_DEBUG << "Invalid property type for "
250ac6a4445SGunnar Mills                                     "VolatileRegionMaxSizeInKib";
251601af5edSChicago Duan                 return;
252ac6a4445SGunnar Mills             }
253ac6a4445SGunnar Mills             aResp->res.jsonValue["VolatileRegionSizeMaxMiB"] = (*value) >> 10;
254ac6a4445SGunnar Mills         }
255ac6a4445SGunnar Mills         else if (property.first == "PmRegionMaxSizeInKiB")
256ac6a4445SGunnar Mills         {
257ac6a4445SGunnar Mills             const uint64_t* value = std::get_if<uint64_t>(&property.second);
258ac6a4445SGunnar Mills 
259ac6a4445SGunnar Mills             if (value == nullptr)
260ac6a4445SGunnar Mills             {
261ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
262ac6a4445SGunnar Mills                 BMCWEB_LOG_DEBUG
263ac6a4445SGunnar Mills                     << "Invalid property type for PmRegionMaxSizeInKiB";
264601af5edSChicago Duan                 return;
265ac6a4445SGunnar Mills             }
266ac6a4445SGunnar Mills             aResp->res.jsonValue["PersistentRegionSizeMaxMiB"] = (*value) >> 10;
267ac6a4445SGunnar Mills         }
268ac6a4445SGunnar Mills         else if (property.first == "AllocationIncrementInKiB")
269ac6a4445SGunnar Mills         {
270ac6a4445SGunnar Mills             const uint64_t* value = std::get_if<uint64_t>(&property.second);
271ac6a4445SGunnar Mills 
272ac6a4445SGunnar Mills             if (value == nullptr)
273ac6a4445SGunnar Mills             {
274ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
275ac6a4445SGunnar Mills                 BMCWEB_LOG_DEBUG << "Invalid property type for "
276ac6a4445SGunnar Mills                                     "AllocationIncrementInKiB";
277601af5edSChicago Duan                 return;
278ac6a4445SGunnar Mills             }
279ac6a4445SGunnar Mills             aResp->res.jsonValue["AllocationIncrementMiB"] = (*value) >> 10;
280ac6a4445SGunnar Mills         }
281ac6a4445SGunnar Mills         else if (property.first == "AllocationAlignmentInKiB")
282ac6a4445SGunnar Mills         {
283ac6a4445SGunnar Mills             const uint64_t* value = std::get_if<uint64_t>(&property.second);
284ac6a4445SGunnar Mills 
285ac6a4445SGunnar Mills             if (value == nullptr)
286ac6a4445SGunnar Mills             {
287ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
288ac6a4445SGunnar Mills                 BMCWEB_LOG_DEBUG << "Invalid property type for "
289ac6a4445SGunnar Mills                                     "AllocationAlignmentInKiB";
290601af5edSChicago Duan                 return;
291ac6a4445SGunnar Mills             }
292ac6a4445SGunnar Mills             aResp->res.jsonValue["AllocationAlignmentMiB"] = (*value) >> 10;
293ac6a4445SGunnar Mills         }
294ac6a4445SGunnar Mills         else if (property.first == "VolatileRegionNumberLimit")
295ac6a4445SGunnar Mills         {
296ac6a4445SGunnar Mills             const uint64_t* value = std::get_if<uint64_t>(&property.second);
297ac6a4445SGunnar Mills             if (value == nullptr)
298ac6a4445SGunnar Mills             {
299ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
300601af5edSChicago Duan                 return;
301ac6a4445SGunnar Mills             }
302ac6a4445SGunnar Mills             aResp->res.jsonValue["VolatileRegionNumberLimit"] = *value;
303ac6a4445SGunnar Mills         }
304ac6a4445SGunnar Mills         else if (property.first == "PmRegionNumberLimit")
305ac6a4445SGunnar Mills         {
306ac6a4445SGunnar Mills             const uint64_t* value = std::get_if<uint64_t>(&property.second);
307ac6a4445SGunnar Mills             if (value == nullptr)
308ac6a4445SGunnar Mills             {
309ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
310601af5edSChicago Duan                 return;
311ac6a4445SGunnar Mills             }
312ac6a4445SGunnar Mills             aResp->res.jsonValue["PersistentRegionNumberLimit"] = *value;
313ac6a4445SGunnar Mills         }
314ac6a4445SGunnar Mills         else if (property.first == "SpareDeviceCount")
315ac6a4445SGunnar Mills         {
316ac6a4445SGunnar Mills             const uint64_t* value = std::get_if<uint64_t>(&property.second);
317ac6a4445SGunnar Mills             if (value == nullptr)
318ac6a4445SGunnar Mills             {
319ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
320601af5edSChicago Duan                 return;
321ac6a4445SGunnar Mills             }
322ac6a4445SGunnar Mills             aResp->res.jsonValue["SpareDeviceCount"] = *value;
323ac6a4445SGunnar Mills         }
324ac6a4445SGunnar Mills         else if (property.first == "IsSpareDeviceInUse")
325ac6a4445SGunnar Mills         {
326ac6a4445SGunnar Mills             const bool* value = std::get_if<bool>(&property.second);
327ac6a4445SGunnar Mills             if (value == nullptr)
328ac6a4445SGunnar Mills             {
329ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
330601af5edSChicago Duan                 return;
331ac6a4445SGunnar Mills             }
332ac6a4445SGunnar Mills             aResp->res.jsonValue["IsSpareDeviceEnabled"] = *value;
333ac6a4445SGunnar Mills         }
334ac6a4445SGunnar Mills         else if (property.first == "IsRankSpareEnabled")
335ac6a4445SGunnar Mills         {
336ac6a4445SGunnar Mills             const bool* value = std::get_if<bool>(&property.second);
337ac6a4445SGunnar Mills             if (value == nullptr)
338ac6a4445SGunnar Mills             {
339ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
340601af5edSChicago Duan                 return;
341ac6a4445SGunnar Mills             }
342ac6a4445SGunnar Mills             aResp->res.jsonValue["IsRankSpareEnabled"] = *value;
343ac6a4445SGunnar Mills         }
344ac6a4445SGunnar Mills         else if (property.first == "MaxAveragePowerLimitmW")
345ac6a4445SGunnar Mills         {
346ac6a4445SGunnar Mills             const auto* value =
347ac6a4445SGunnar Mills                 std::get_if<std::vector<uint32_t>>(&property.second);
348ac6a4445SGunnar Mills             if (value == nullptr)
349ac6a4445SGunnar Mills             {
350ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
351ac6a4445SGunnar Mills                 BMCWEB_LOG_DEBUG << "Invalid property type for "
352ac6a4445SGunnar Mills                                     "MaxAveragePowerLimitmW";
353601af5edSChicago Duan                 return;
354ac6a4445SGunnar Mills             }
355ac6a4445SGunnar Mills             aResp->res.jsonValue["MaxTDPMilliWatts"] = *value;
356ac6a4445SGunnar Mills         }
357ac6a4445SGunnar Mills         else if (property.first == "ConfigurationLocked")
358ac6a4445SGunnar Mills         {
359ac6a4445SGunnar Mills             const bool* value = std::get_if<bool>(&property.second);
360ac6a4445SGunnar Mills             if (value == nullptr)
361ac6a4445SGunnar Mills             {
362ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
363601af5edSChicago Duan                 return;
364ac6a4445SGunnar Mills             }
365ac6a4445SGunnar Mills             aResp->res.jsonValue["ConfigurationLocked"] = *value;
366ac6a4445SGunnar Mills         }
367ac6a4445SGunnar Mills         else if (property.first == "AllowedMemoryModes")
368ac6a4445SGunnar Mills         {
369ac6a4445SGunnar Mills             const std::string* value =
370ac6a4445SGunnar Mills                 std::get_if<std::string>(&property.second);
371ac6a4445SGunnar Mills             if (value == nullptr)
372ac6a4445SGunnar Mills             {
373ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
374ac6a4445SGunnar Mills                 BMCWEB_LOG_DEBUG << "Invalid property type for FormFactor";
375601af5edSChicago Duan                 return;
376ac6a4445SGunnar Mills             }
377ac6a4445SGunnar Mills             constexpr const std::array<const char*, 3> values{"Volatile",
378ac6a4445SGunnar Mills                                                               "PMEM", "Block"};
379ac6a4445SGunnar Mills 
380ac6a4445SGunnar Mills             for (const char* v : values)
381ac6a4445SGunnar Mills             {
382ac6a4445SGunnar Mills                 if (boost::ends_with(*value, v))
383ac6a4445SGunnar Mills                 {
384ac6a4445SGunnar Mills                     aResp->res.jsonValue["OperatingMemoryModes "] = v;
385ac6a4445SGunnar Mills                     break;
386ac6a4445SGunnar Mills                 }
387ac6a4445SGunnar Mills             }
388ac6a4445SGunnar Mills         }
389ac6a4445SGunnar Mills         else if (property.first == "MemoryMedia")
390ac6a4445SGunnar Mills         {
391ac6a4445SGunnar Mills             const std::string* value =
392ac6a4445SGunnar Mills                 std::get_if<std::string>(&property.second);
393ac6a4445SGunnar Mills             if (value == nullptr)
394ac6a4445SGunnar Mills             {
395ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
396ac6a4445SGunnar Mills                 BMCWEB_LOG_DEBUG << "Invalid property type for MemoryMedia";
397601af5edSChicago Duan                 return;
398ac6a4445SGunnar Mills             }
399ac6a4445SGunnar Mills             constexpr const std::array<const char*, 3> values{"DRAM", "NAND",
400ac6a4445SGunnar Mills                                                               "Intel3DXPoint"};
401ac6a4445SGunnar Mills 
402ac6a4445SGunnar Mills             for (const char* v : values)
403ac6a4445SGunnar Mills             {
404ac6a4445SGunnar Mills                 if (boost::ends_with(*value, v))
405ac6a4445SGunnar Mills                 {
406ac6a4445SGunnar Mills                     aResp->res.jsonValue["MemoryMedia"] = v;
407ac6a4445SGunnar Mills                     break;
408ac6a4445SGunnar Mills                 }
409ac6a4445SGunnar Mills             }
410ac6a4445SGunnar Mills         }
411ac6a4445SGunnar Mills         // PersistantMemory.SecurityCapabilites interface
412ac6a4445SGunnar Mills         else if (property.first == "ConfigurationLockCapable" ||
413ac6a4445SGunnar Mills                  property.first == "DataLockCapable" ||
414ac6a4445SGunnar Mills                  property.first == "PassphraseCapable")
415ac6a4445SGunnar Mills         {
416ac6a4445SGunnar Mills             const bool* value = std::get_if<bool>(&property.second);
417ac6a4445SGunnar Mills             if (value == nullptr)
418ac6a4445SGunnar Mills             {
419ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
420601af5edSChicago Duan                 return;
421ac6a4445SGunnar Mills             }
422ac6a4445SGunnar Mills             aResp->res.jsonValue["SecurityCapabilities"][property.first] =
423ac6a4445SGunnar Mills                 *value;
424ac6a4445SGunnar Mills         }
425ac6a4445SGunnar Mills         else if (property.first == "MaxPassphraseCount" ||
426ac6a4445SGunnar Mills                  property.first == "PassphraseLockLimit")
427ac6a4445SGunnar Mills         {
428ac6a4445SGunnar Mills             const uint64_t* value = std::get_if<uint64_t>(&property.second);
429ac6a4445SGunnar Mills             if (value == nullptr)
430ac6a4445SGunnar Mills             {
431ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
432601af5edSChicago Duan                 return;
433ac6a4445SGunnar Mills             }
434ac6a4445SGunnar Mills             aResp->res.jsonValue["SecurityCapabilities"][property.first] =
435ac6a4445SGunnar Mills                 *value;
436ac6a4445SGunnar Mills         }
437ac6a4445SGunnar Mills     }
438ac6a4445SGunnar Mills }
439ac6a4445SGunnar Mills 
4408d1b46d7Szhanghch05 inline void getDimmDataByService(std::shared_ptr<bmcweb::AsyncResp> aResp,
441ac6a4445SGunnar Mills                                  const std::string& dimmId,
442ac6a4445SGunnar Mills                                  const std::string& service,
443ac6a4445SGunnar Mills                                  const std::string& objPath)
444ac6a4445SGunnar Mills {
445ac6a4445SGunnar Mills     auto health = std::make_shared<HealthPopulate>(aResp);
446ac6a4445SGunnar Mills     health->selfPath = objPath;
447ac6a4445SGunnar Mills     health->populate();
448ac6a4445SGunnar Mills 
449ac6a4445SGunnar Mills     BMCWEB_LOG_DEBUG << "Get available system components.";
450ac6a4445SGunnar Mills     crow::connections::systemBus->async_method_call(
451ac6a4445SGunnar Mills         [dimmId, aResp{std::move(aResp)}](const boost::system::error_code ec,
452ac6a4445SGunnar Mills                                           const DimmProperties& properties) {
453ac6a4445SGunnar Mills             if (ec)
454ac6a4445SGunnar Mills             {
455ac6a4445SGunnar Mills                 BMCWEB_LOG_DEBUG << "DBUS response error";
456ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
457ac6a4445SGunnar Mills 
458ac6a4445SGunnar Mills                 return;
459ac6a4445SGunnar Mills             }
460ac6a4445SGunnar Mills             aResp->res.jsonValue["Id"] = dimmId;
461ac6a4445SGunnar Mills             aResp->res.jsonValue["Name"] = "DIMM Slot";
462ac6a4445SGunnar Mills 
463ac6a4445SGunnar Mills             const auto memorySizeProperty = properties.find("MemorySizeInKB");
464ac6a4445SGunnar Mills             if (memorySizeProperty != properties.end())
465ac6a4445SGunnar Mills             {
466ac6a4445SGunnar Mills                 const uint32_t* memorySize =
467ac6a4445SGunnar Mills                     std::get_if<uint32_t>(&memorySizeProperty->second);
468ac6a4445SGunnar Mills                 if (memorySize == nullptr)
469ac6a4445SGunnar Mills                 {
470ac6a4445SGunnar Mills                     // Important property not in desired type
471ac6a4445SGunnar Mills                     messages::internalError(aResp->res);
472ac6a4445SGunnar Mills                     return;
473ac6a4445SGunnar Mills                 }
474ac6a4445SGunnar Mills                 aResp->res.jsonValue["CapacityMiB"] = (*memorySize >> 10);
475ac6a4445SGunnar Mills             }
476ac6a4445SGunnar Mills             aResp->res.jsonValue["Status"]["State"] = "Enabled";
477ac6a4445SGunnar Mills             aResp->res.jsonValue["Status"]["Health"] = "OK";
478ac6a4445SGunnar Mills 
479ac6a4445SGunnar Mills             for (const auto& property : properties)
480ac6a4445SGunnar Mills             {
481ac6a4445SGunnar Mills                 if (property.first == "MemoryDataWidth")
482ac6a4445SGunnar Mills                 {
483ac6a4445SGunnar Mills                     const uint16_t* value =
484ac6a4445SGunnar Mills                         std::get_if<uint16_t>(&property.second);
485ac6a4445SGunnar Mills                     if (value == nullptr)
486ac6a4445SGunnar Mills                     {
487ac6a4445SGunnar Mills                         continue;
488ac6a4445SGunnar Mills                     }
489ac6a4445SGunnar Mills                     aResp->res.jsonValue["DataWidthBits"] = *value;
490ac6a4445SGunnar Mills                 }
491ac6a4445SGunnar Mills                 else if (property.first == "PartNumber")
492ac6a4445SGunnar Mills                 {
493ac6a4445SGunnar Mills                     const std::string* value =
494ac6a4445SGunnar Mills                         std::get_if<std::string>(&property.second);
495ac6a4445SGunnar Mills                     if (value == nullptr)
496ac6a4445SGunnar Mills                     {
497ac6a4445SGunnar Mills                         continue;
498ac6a4445SGunnar Mills                     }
499ac6a4445SGunnar Mills                     aResp->res.jsonValue["PartNumber"] = *value;
500ac6a4445SGunnar Mills                 }
501ac6a4445SGunnar Mills                 else if (property.first == "SerialNumber")
502ac6a4445SGunnar Mills                 {
503ac6a4445SGunnar Mills                     const std::string* value =
504ac6a4445SGunnar Mills                         std::get_if<std::string>(&property.second);
505ac6a4445SGunnar Mills                     if (value == nullptr)
506ac6a4445SGunnar Mills                     {
507ac6a4445SGunnar Mills                         continue;
508ac6a4445SGunnar Mills                     }
509ac6a4445SGunnar Mills                     aResp->res.jsonValue["SerialNumber"] = *value;
510ac6a4445SGunnar Mills                 }
511ac6a4445SGunnar Mills                 else if (property.first == "Manufacturer")
512ac6a4445SGunnar Mills                 {
513ac6a4445SGunnar Mills                     const std::string* value =
514ac6a4445SGunnar Mills                         std::get_if<std::string>(&property.second);
515ac6a4445SGunnar Mills                     if (value == nullptr)
516ac6a4445SGunnar Mills                     {
517ac6a4445SGunnar Mills                         continue;
518ac6a4445SGunnar Mills                     }
519ac6a4445SGunnar Mills                     aResp->res.jsonValue["Manufacturer"] = *value;
520ac6a4445SGunnar Mills                 }
521ac6a4445SGunnar Mills                 else if (property.first == "RevisionCode")
522ac6a4445SGunnar Mills                 {
523ac6a4445SGunnar Mills                     const uint16_t* value =
524ac6a4445SGunnar Mills                         std::get_if<uint16_t>(&property.second);
525ac6a4445SGunnar Mills 
526ac6a4445SGunnar Mills                     if (value == nullptr)
527ac6a4445SGunnar Mills                     {
528ac6a4445SGunnar Mills                         messages::internalError(aResp->res);
529ac6a4445SGunnar Mills                         BMCWEB_LOG_DEBUG
530ac6a4445SGunnar Mills                             << "Invalid property type for RevisionCode";
531601af5edSChicago Duan                         return;
532ac6a4445SGunnar Mills                     }
533ac6a4445SGunnar Mills                     aResp->res.jsonValue["FirmwareRevision"] =
534ac6a4445SGunnar Mills                         std::to_string(*value);
535ac6a4445SGunnar Mills                 }
5369a128eb3SJoshi-Mansi                 else if (property.first == "Present")
5379a128eb3SJoshi-Mansi                 {
5389a128eb3SJoshi-Mansi                     const bool* value = std::get_if<bool>(&property.second);
5399a128eb3SJoshi-Mansi                     if (value == nullptr)
5409a128eb3SJoshi-Mansi                     {
5419a128eb3SJoshi-Mansi                         messages::internalError(aResp->res);
5429a128eb3SJoshi-Mansi                         BMCWEB_LOG_DEBUG
5439a128eb3SJoshi-Mansi                             << "Invalid property type for Dimm Presence";
5449a128eb3SJoshi-Mansi                         return;
5459a128eb3SJoshi-Mansi                     }
5469a128eb3SJoshi-Mansi                     if (*value == false)
5479a128eb3SJoshi-Mansi                     {
5489a128eb3SJoshi-Mansi                         aResp->res.jsonValue["Status"]["State"] = "Absent";
5499a128eb3SJoshi-Mansi                     }
5509a128eb3SJoshi-Mansi                 }
551ac6a4445SGunnar Mills                 else if (property.first == "MemoryTotalWidth")
552ac6a4445SGunnar Mills                 {
553ac6a4445SGunnar Mills                     const uint16_t* value =
554ac6a4445SGunnar Mills                         std::get_if<uint16_t>(&property.second);
555ac6a4445SGunnar Mills                     if (value == nullptr)
556ac6a4445SGunnar Mills                     {
557ac6a4445SGunnar Mills                         continue;
558ac6a4445SGunnar Mills                     }
559ac6a4445SGunnar Mills                     aResp->res.jsonValue["BusWidthBits"] = *value;
560ac6a4445SGunnar Mills                 }
561ac6a4445SGunnar Mills                 else if (property.first == "ECC")
562ac6a4445SGunnar Mills                 {
563ac6a4445SGunnar Mills                     const std::string* value =
564ac6a4445SGunnar Mills                         std::get_if<std::string>(&property.second);
565ac6a4445SGunnar Mills                     if (value == nullptr)
566ac6a4445SGunnar Mills                     {
567ac6a4445SGunnar Mills                         messages::internalError(aResp->res);
568ac6a4445SGunnar Mills                         BMCWEB_LOG_DEBUG << "Invalid property type for ECC";
569601af5edSChicago Duan                         return;
570ac6a4445SGunnar Mills                     }
571ac6a4445SGunnar Mills                     constexpr const std::array<const char*, 4> values{
572ac6a4445SGunnar Mills                         "NoECC", "SingleBitECC", "MultiBitECC",
573ac6a4445SGunnar Mills                         "AddressParity"};
574ac6a4445SGunnar Mills 
575ac6a4445SGunnar Mills                     for (const char* v : values)
576ac6a4445SGunnar Mills                     {
577ac6a4445SGunnar Mills                         if (boost::ends_with(*value, v))
578ac6a4445SGunnar Mills                         {
579ac6a4445SGunnar Mills                             aResp->res.jsonValue["ErrorCorrection"] = v;
580ac6a4445SGunnar Mills                             break;
581ac6a4445SGunnar Mills                         }
582ac6a4445SGunnar Mills                     }
583ac6a4445SGunnar Mills                 }
584ac6a4445SGunnar Mills                 else if (property.first == "FormFactor")
585ac6a4445SGunnar Mills                 {
586ac6a4445SGunnar Mills                     const std::string* value =
587ac6a4445SGunnar Mills                         std::get_if<std::string>(&property.second);
588ac6a4445SGunnar Mills                     if (value == nullptr)
589ac6a4445SGunnar Mills                     {
590ac6a4445SGunnar Mills                         messages::internalError(aResp->res);
591ac6a4445SGunnar Mills                         BMCWEB_LOG_DEBUG
592ac6a4445SGunnar Mills                             << "Invalid property type for FormFactor";
593601af5edSChicago Duan                         return;
594ac6a4445SGunnar Mills                     }
595ac6a4445SGunnar Mills                     constexpr const std::array<const char*, 11> values{
596ac6a4445SGunnar Mills                         "RDIMM",        "UDIMM",        "SO_DIMM",
597ac6a4445SGunnar Mills                         "LRDIMM",       "Mini_RDIMM",   "Mini_UDIMM",
598ac6a4445SGunnar Mills                         "SO_RDIMM_72b", "SO_UDIMM_72b", "SO_DIMM_16b",
599ac6a4445SGunnar Mills                         "SO_DIMM_32b",  "Die"};
600ac6a4445SGunnar Mills 
601ac6a4445SGunnar Mills                     for (const char* v : values)
602ac6a4445SGunnar Mills                     {
603ac6a4445SGunnar Mills                         if (boost::ends_with(*value, v))
604ac6a4445SGunnar Mills                         {
605ac6a4445SGunnar Mills                             aResp->res.jsonValue["BaseModuleType"] = v;
606ac6a4445SGunnar Mills                             break;
607ac6a4445SGunnar Mills                         }
608ac6a4445SGunnar Mills                     }
609ac6a4445SGunnar Mills                 }
610ac6a4445SGunnar Mills                 else if (property.first == "AllowedSpeedsMT")
611ac6a4445SGunnar Mills                 {
612ac6a4445SGunnar Mills                     const std::vector<uint16_t>* value =
613ac6a4445SGunnar Mills                         std::get_if<std::vector<uint16_t>>(&property.second);
614ac6a4445SGunnar Mills                     if (value == nullptr)
615ac6a4445SGunnar Mills                     {
616ac6a4445SGunnar Mills                         continue;
617ac6a4445SGunnar Mills                     }
618ac6a4445SGunnar Mills                     nlohmann::json& jValue =
619ac6a4445SGunnar Mills                         aResp->res.jsonValue["AllowedSpeedsMHz"];
620ac6a4445SGunnar Mills                     jValue = nlohmann::json::array();
621ac6a4445SGunnar Mills                     for (uint16_t subVal : *value)
622ac6a4445SGunnar Mills                     {
623ac6a4445SGunnar Mills                         jValue.push_back(subVal);
624ac6a4445SGunnar Mills                     }
625ac6a4445SGunnar Mills                 }
626ac6a4445SGunnar Mills                 else if (property.first == "MemoryAttributes")
627ac6a4445SGunnar Mills                 {
628ac6a4445SGunnar Mills                     const uint8_t* value =
629ac6a4445SGunnar Mills                         std::get_if<uint8_t>(&property.second);
630ac6a4445SGunnar Mills 
631ac6a4445SGunnar Mills                     if (value == nullptr)
632ac6a4445SGunnar Mills                     {
633ac6a4445SGunnar Mills                         messages::internalError(aResp->res);
634ac6a4445SGunnar Mills                         BMCWEB_LOG_DEBUG
635ac6a4445SGunnar Mills                             << "Invalid property type for MemoryAttributes";
636601af5edSChicago Duan                         return;
637ac6a4445SGunnar Mills                     }
638ac6a4445SGunnar Mills                     aResp->res.jsonValue["RankCount"] =
639ac6a4445SGunnar Mills                         static_cast<uint64_t>(*value);
640ac6a4445SGunnar Mills                 }
641ac6a4445SGunnar Mills                 else if (property.first == "MemoryConfiguredSpeedInMhz")
642ac6a4445SGunnar Mills                 {
643ac6a4445SGunnar Mills                     const uint16_t* value =
644ac6a4445SGunnar Mills                         std::get_if<uint16_t>(&property.second);
645ac6a4445SGunnar Mills                     if (value == nullptr)
646ac6a4445SGunnar Mills                     {
647ac6a4445SGunnar Mills                         continue;
648ac6a4445SGunnar Mills                     }
649ac6a4445SGunnar Mills                     aResp->res.jsonValue["OperatingSpeedMhz"] = *value;
650ac6a4445SGunnar Mills                 }
651ac6a4445SGunnar Mills                 else if (property.first == "MemoryType")
652ac6a4445SGunnar Mills                 {
653ac6a4445SGunnar Mills                     const auto* value =
654ac6a4445SGunnar Mills                         std::get_if<std::string>(&property.second);
655ac6a4445SGunnar Mills                     if (value != nullptr)
656ac6a4445SGunnar Mills                     {
657313efb1cSGunnar Mills                         std::string memoryDeviceType =
658313efb1cSGunnar Mills                             translateMemoryTypeToRedfish(*value);
659313efb1cSGunnar Mills                         // Values like "Unknown" or "Other" will return empty
660313efb1cSGunnar Mills                         // so just leave off
661313efb1cSGunnar Mills                         if (!memoryDeviceType.empty())
662ac6a4445SGunnar Mills                         {
663313efb1cSGunnar Mills                             aResp->res.jsonValue["MemoryDeviceType"] =
664313efb1cSGunnar Mills                                 memoryDeviceType;
665ac6a4445SGunnar Mills                         }
666ac6a4445SGunnar Mills                         if (value->find("DDR") != std::string::npos)
667ac6a4445SGunnar Mills                         {
668ac6a4445SGunnar Mills                             aResp->res.jsonValue["MemoryType"] = "DRAM";
669ac6a4445SGunnar Mills                         }
670ac6a4445SGunnar Mills                         else if (boost::ends_with(*value, "Logical"))
671ac6a4445SGunnar Mills                         {
672ac6a4445SGunnar Mills                             aResp->res.jsonValue["MemoryType"] = "IntelOptane";
673ac6a4445SGunnar Mills                         }
674ac6a4445SGunnar Mills                     }
675ac6a4445SGunnar Mills                 }
676ac6a4445SGunnar Mills                 // memory location interface
677ac6a4445SGunnar Mills                 else if (property.first == "Channel" ||
678ac6a4445SGunnar Mills                          property.first == "MemoryController" ||
679ac6a4445SGunnar Mills                          property.first == "Slot" || property.first == "Socket")
680ac6a4445SGunnar Mills                 {
681ac6a4445SGunnar Mills                     const std::string* value =
682ac6a4445SGunnar Mills                         std::get_if<std::string>(&property.second);
683ac6a4445SGunnar Mills                     if (value == nullptr)
684ac6a4445SGunnar Mills                     {
685ac6a4445SGunnar Mills                         messages::internalError(aResp->res);
686601af5edSChicago Duan                         return;
687ac6a4445SGunnar Mills                     }
688ac6a4445SGunnar Mills                     aResp->res.jsonValue["MemoryLocation"][property.first] =
689ac6a4445SGunnar Mills                         *value;
690ac6a4445SGunnar Mills                 }
691ee135e24SSunnySrivastava1984                 else if (property.first == "SparePartNumber")
692ee135e24SSunnySrivastava1984                 {
693ee135e24SSunnySrivastava1984                     const std::string* value =
694ee135e24SSunnySrivastava1984                         std::get_if<std::string>(&property.second);
695ee135e24SSunnySrivastava1984                     if (value == nullptr)
696ee135e24SSunnySrivastava1984                     {
697ee135e24SSunnySrivastava1984                         messages::internalError(aResp->res);
698601af5edSChicago Duan                         return;
699ee135e24SSunnySrivastava1984                     }
700ee135e24SSunnySrivastava1984                     aResp->res.jsonValue["SparePartNumber"] = *value;
701ee135e24SSunnySrivastava1984                 }
702ee135e24SSunnySrivastava1984                 else if (property.first == "Model")
703ee135e24SSunnySrivastava1984                 {
704ee135e24SSunnySrivastava1984                     const std::string* value =
705ee135e24SSunnySrivastava1984                         std::get_if<std::string>(&property.second);
706ee135e24SSunnySrivastava1984                     if (value == nullptr)
707ee135e24SSunnySrivastava1984                     {
708ee135e24SSunnySrivastava1984                         messages::internalError(aResp->res);
709601af5edSChicago Duan                         return;
710ee135e24SSunnySrivastava1984                     }
711ee135e24SSunnySrivastava1984                     aResp->res.jsonValue["Model"] = *value;
712ee135e24SSunnySrivastava1984                 }
713ee135e24SSunnySrivastava1984                 else if (property.first == "LocationCode")
714ee135e24SSunnySrivastava1984                 {
715ee135e24SSunnySrivastava1984                     const std::string* value =
716ee135e24SSunnySrivastava1984                         std::get_if<std::string>(&property.second);
717ee135e24SSunnySrivastava1984                     if (value == nullptr)
718ee135e24SSunnySrivastava1984                     {
719ee135e24SSunnySrivastava1984                         messages::internalError(aResp->res);
720601af5edSChicago Duan                         return;
721ee135e24SSunnySrivastava1984                     }
722ee135e24SSunnySrivastava1984                     aResp->res
723ee135e24SSunnySrivastava1984                         .jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
724ee135e24SSunnySrivastava1984                         *value;
725ee135e24SSunnySrivastava1984                 }
726ac6a4445SGunnar Mills                 else
727ac6a4445SGunnar Mills                 {
728ac6a4445SGunnar Mills                     getPersistentMemoryProperties(aResp, properties);
729ac6a4445SGunnar Mills                 }
730ac6a4445SGunnar Mills             }
731ac6a4445SGunnar Mills         },
732ac6a4445SGunnar Mills         service, objPath, "org.freedesktop.DBus.Properties", "GetAll", "");
733ac6a4445SGunnar Mills }
734ac6a4445SGunnar Mills 
7358d1b46d7Szhanghch05 inline void getDimmPartitionData(std::shared_ptr<bmcweb::AsyncResp> aResp,
736ac6a4445SGunnar Mills                                  const std::string& service,
737ac6a4445SGunnar Mills                                  const std::string& path)
738ac6a4445SGunnar Mills {
739ac6a4445SGunnar Mills     crow::connections::systemBus->async_method_call(
740ac6a4445SGunnar Mills         [aResp{std::move(aResp)}](
741ac6a4445SGunnar Mills             const boost::system::error_code ec,
742ac6a4445SGunnar Mills             const boost::container::flat_map<
743ac6a4445SGunnar Mills                 std::string, std::variant<std::string, uint64_t, uint32_t,
744ac6a4445SGunnar Mills                                           bool>>& properties) {
745ac6a4445SGunnar Mills             if (ec)
746ac6a4445SGunnar Mills             {
747ac6a4445SGunnar Mills                 BMCWEB_LOG_DEBUG << "DBUS response error";
748ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
749ac6a4445SGunnar Mills 
750ac6a4445SGunnar Mills                 return;
751ac6a4445SGunnar Mills             }
752ac6a4445SGunnar Mills 
753ac6a4445SGunnar Mills             nlohmann::json& partition =
754ac6a4445SGunnar Mills                 aResp->res.jsonValue["Regions"].emplace_back(
755ac6a4445SGunnar Mills                     nlohmann::json::object());
756ac6a4445SGunnar Mills             for (const auto& [key, val] : properties)
757ac6a4445SGunnar Mills             {
758ac6a4445SGunnar Mills                 if (key == "MemoryClassification")
759ac6a4445SGunnar Mills                 {
760ac6a4445SGunnar Mills                     const std::string* value = std::get_if<std::string>(&val);
761ac6a4445SGunnar Mills                     if (value == nullptr)
762ac6a4445SGunnar Mills                     {
763ac6a4445SGunnar Mills                         messages::internalError(aResp->res);
764601af5edSChicago Duan                         return;
765ac6a4445SGunnar Mills                     }
766ac6a4445SGunnar Mills                     partition[key] = *value;
767ac6a4445SGunnar Mills                 }
768ac6a4445SGunnar Mills                 else if (key == "OffsetInKiB")
769ac6a4445SGunnar Mills                 {
770ac6a4445SGunnar Mills                     const uint64_t* value = std::get_if<uint64_t>(&val);
771ac6a4445SGunnar Mills                     if (value == nullptr)
772ac6a4445SGunnar Mills                     {
773ac6a4445SGunnar Mills                         messages::internalError(aResp->res);
774601af5edSChicago Duan                         return;
775ac6a4445SGunnar Mills                     }
776ac6a4445SGunnar Mills 
777ac6a4445SGunnar Mills                     partition["OffsetMiB"] = (*value >> 10);
778ac6a4445SGunnar Mills                 }
779ac6a4445SGunnar Mills                 else if (key == "PartitionId")
780ac6a4445SGunnar Mills                 {
781ac6a4445SGunnar Mills                     const std::string* value = std::get_if<std::string>(&val);
782ac6a4445SGunnar Mills                     if (value == nullptr)
783ac6a4445SGunnar Mills                     {
784ac6a4445SGunnar Mills                         messages::internalError(aResp->res);
785601af5edSChicago Duan                         return;
786ac6a4445SGunnar Mills                     }
787ac6a4445SGunnar Mills                     partition["RegionId"] = *value;
788ac6a4445SGunnar Mills                 }
789ac6a4445SGunnar Mills 
790ac6a4445SGunnar Mills                 else if (key == "PassphraseState")
791ac6a4445SGunnar Mills                 {
792ac6a4445SGunnar Mills                     const bool* value = std::get_if<bool>(&val);
793ac6a4445SGunnar Mills                     if (value == nullptr)
794ac6a4445SGunnar Mills                     {
795ac6a4445SGunnar Mills                         messages::internalError(aResp->res);
796601af5edSChicago Duan                         return;
797ac6a4445SGunnar Mills                     }
798ac6a4445SGunnar Mills                     partition["PassphraseEnabled"] = *value;
799ac6a4445SGunnar Mills                 }
800ac6a4445SGunnar Mills                 else if (key == "SizeInKiB")
801ac6a4445SGunnar Mills                 {
802ac6a4445SGunnar Mills                     const uint64_t* value = std::get_if<uint64_t>(&val);
803ac6a4445SGunnar Mills                     if (value == nullptr)
804ac6a4445SGunnar Mills                     {
805ac6a4445SGunnar Mills                         messages::internalError(aResp->res);
806ac6a4445SGunnar Mills                         BMCWEB_LOG_DEBUG
807ac6a4445SGunnar Mills                             << "Invalid property type for SizeInKiB";
808601af5edSChicago Duan                         return;
809ac6a4445SGunnar Mills                     }
810ac6a4445SGunnar Mills                     partition["SizeMiB"] = (*value >> 10);
811ac6a4445SGunnar Mills                 }
812ac6a4445SGunnar Mills             }
813ac6a4445SGunnar Mills         },
814ac6a4445SGunnar Mills 
815ac6a4445SGunnar Mills         service, path, "org.freedesktop.DBus.Properties", "GetAll",
816ac6a4445SGunnar Mills         "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition");
817ac6a4445SGunnar Mills }
818ac6a4445SGunnar Mills 
8198d1b46d7Szhanghch05 inline void getDimmData(std::shared_ptr<bmcweb::AsyncResp> aResp,
820ac6a4445SGunnar Mills                         const std::string& dimmId)
821ac6a4445SGunnar Mills {
822ac6a4445SGunnar Mills     BMCWEB_LOG_DEBUG << "Get available system dimm resources.";
823ac6a4445SGunnar Mills     crow::connections::systemBus->async_method_call(
824ac6a4445SGunnar Mills         [dimmId, aResp{std::move(aResp)}](
825ac6a4445SGunnar Mills             const boost::system::error_code ec,
826ac6a4445SGunnar Mills             const boost::container::flat_map<
827ac6a4445SGunnar Mills                 std::string, boost::container::flat_map<
828ac6a4445SGunnar Mills                                  std::string, std::vector<std::string>>>&
829ac6a4445SGunnar Mills                 subtree) {
830ac6a4445SGunnar Mills             if (ec)
831ac6a4445SGunnar Mills             {
832ac6a4445SGunnar Mills                 BMCWEB_LOG_DEBUG << "DBUS response error";
833ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
834ac6a4445SGunnar Mills 
835ac6a4445SGunnar Mills                 return;
836ac6a4445SGunnar Mills             }
837ac6a4445SGunnar Mills             bool found = false;
838ac6a4445SGunnar Mills             for (const auto& [path, object] : subtree)
839ac6a4445SGunnar Mills             {
840ac6a4445SGunnar Mills                 if (path.find(dimmId) != std::string::npos)
841ac6a4445SGunnar Mills                 {
842ac6a4445SGunnar Mills                     for (const auto& [service, interfaces] : object)
843ac6a4445SGunnar Mills                     {
844ac6a4445SGunnar Mills                         if (!found &&
845ac6a4445SGunnar Mills                             (std::find(
846ac6a4445SGunnar Mills                                  interfaces.begin(), interfaces.end(),
847ac6a4445SGunnar Mills                                  "xyz.openbmc_project.Inventory.Item.Dimm") !=
848ac6a4445SGunnar Mills                              interfaces.end()))
849ac6a4445SGunnar Mills                         {
850ac6a4445SGunnar Mills                             getDimmDataByService(aResp, dimmId, service, path);
851ac6a4445SGunnar Mills                             found = true;
852ac6a4445SGunnar Mills                         }
853ac6a4445SGunnar Mills 
854ac6a4445SGunnar Mills                         // partitions are separate as there can be multiple per
855ac6a4445SGunnar Mills                         // device, i.e.
856ac6a4445SGunnar Mills                         // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition1
857ac6a4445SGunnar Mills                         // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition2
858ac6a4445SGunnar Mills                         if (std::find(interfaces.begin(), interfaces.end(),
859ac6a4445SGunnar Mills                                       "xyz.openbmc_project.Inventory.Item."
860ac6a4445SGunnar Mills                                       "PersistentMemory.Partition") !=
861ac6a4445SGunnar Mills                             interfaces.end())
862ac6a4445SGunnar Mills                         {
863ac6a4445SGunnar Mills                             getDimmPartitionData(aResp, service, path);
864ac6a4445SGunnar Mills                         }
865ac6a4445SGunnar Mills                     }
866ac6a4445SGunnar Mills                 }
867ac6a4445SGunnar Mills             }
868ac6a4445SGunnar Mills             // Object not found
869ac6a4445SGunnar Mills             if (!found)
870ac6a4445SGunnar Mills             {
871ac6a4445SGunnar Mills                 messages::resourceNotFound(aResp->res, "Memory", dimmId);
872ac6a4445SGunnar Mills             }
873ac6a4445SGunnar Mills             return;
874ac6a4445SGunnar Mills         },
875ac6a4445SGunnar Mills         "xyz.openbmc_project.ObjectMapper",
876ac6a4445SGunnar Mills         "/xyz/openbmc_project/object_mapper",
877ac6a4445SGunnar Mills         "xyz.openbmc_project.ObjectMapper", "GetSubTree",
878ac6a4445SGunnar Mills         "/xyz/openbmc_project/inventory", 0,
879ac6a4445SGunnar Mills         std::array<const char*, 2>{
880ac6a4445SGunnar Mills             "xyz.openbmc_project.Inventory.Item.Dimm",
881ac6a4445SGunnar Mills             "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition"});
882ac6a4445SGunnar Mills }
883ac6a4445SGunnar Mills 
8847e860f15SJohn Edward Broadbent inline void requestRoutesMemoryCollection(App& app)
885ac6a4445SGunnar Mills {
886ac6a4445SGunnar Mills     /**
887ac6a4445SGunnar Mills      * Functions triggers appropriate requests on DBus
888ac6a4445SGunnar Mills      */
8897e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Memory/")
890*ed398213SEd Tanous         .privileges(redfish::privileges::getMemoryCollection)
8917e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
8927e860f15SJohn Edward Broadbent             [](const crow::Request&,
8937e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
8948d1b46d7Szhanghch05                 asyncResp->res.jsonValue["@odata.type"] =
8958d1b46d7Szhanghch05                     "#MemoryCollection.MemoryCollection";
8968d1b46d7Szhanghch05                 asyncResp->res.jsonValue["Name"] = "Memory Module Collection";
8978d1b46d7Szhanghch05                 asyncResp->res.jsonValue["@odata.id"] =
8988d1b46d7Szhanghch05                     "/redfish/v1/Systems/system/Memory";
899ac6a4445SGunnar Mills 
90005030b8eSGunnar Mills                 collection_util::getCollectionMembers(
90105030b8eSGunnar Mills                     asyncResp, "/redfish/v1/Systems/system/Memory",
90205030b8eSGunnar Mills                     {"xyz.openbmc_project.Inventory.Item.Dimm"});
9037e860f15SJohn Edward Broadbent             });
904ac6a4445SGunnar Mills }
905ac6a4445SGunnar Mills 
9067e860f15SJohn Edward Broadbent inline void requestRoutesMemory(App& app)
9077e860f15SJohn Edward Broadbent {
908ac6a4445SGunnar Mills     /**
909ac6a4445SGunnar Mills      * Functions triggers appropriate requests on DBus
910ac6a4445SGunnar Mills      */
9117e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Memory/<str>/")
912*ed398213SEd Tanous         .privileges(redfish::privileges::getMemory)
9137e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
9147e860f15SJohn Edward Broadbent             [](const crow::Request&,
9157e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
9167e860f15SJohn Edward Broadbent                const std::string& dimmId) {
9177e860f15SJohn Edward Broadbent                 asyncResp->res.jsonValue["@odata.type"] =
9187e860f15SJohn Edward Broadbent                     "#Memory.v1_11_0.Memory";
9198d1b46d7Szhanghch05                 asyncResp->res.jsonValue["@odata.id"] =
920ac6a4445SGunnar Mills                     "/redfish/v1/Systems/system/Memory/" + dimmId;
921ac6a4445SGunnar Mills 
922ac6a4445SGunnar Mills                 getDimmData(asyncResp, dimmId);
9237e860f15SJohn Edward Broadbent             });
924ac6a4445SGunnar Mills }
925ac6a4445SGunnar Mills 
926ac6a4445SGunnar Mills } // namespace redfish
927