xref: /openbmc/bmcweb/features/redfish/lib/memory.hpp (revision 0fda0f12bb9ae0604a083dfae419be38a1418913)
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>
22ed398213SEd Tanous #include <registries/privilege_registry.hpp>
23ac6a4445SGunnar Mills #include <utils/collection.hpp>
24f201ffb4SEd Tanous #include <utils/hex_utils.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     }
5911a2f0f0SMansi Joshi     if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR5")
6011a2f0f0SMansi Joshi     {
6111a2f0f0SMansi Joshi         return "DDR5";
6211a2f0f0SMansi Joshi     }
63313efb1cSGunnar Mills     if (memoryType ==
64313efb1cSGunnar Mills         "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.LPDDR4_SDRAM")
65313efb1cSGunnar Mills     {
66313efb1cSGunnar Mills         return "LPDDR4_SDRAM";
67313efb1cSGunnar Mills     }
68313efb1cSGunnar Mills     if (memoryType ==
69313efb1cSGunnar Mills         "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.LPDDR3_SDRAM")
70313efb1cSGunnar Mills     {
71313efb1cSGunnar Mills         return "LPDDR3_SDRAM";
72313efb1cSGunnar Mills     }
73313efb1cSGunnar Mills     if (memoryType ==
74313efb1cSGunnar Mills         "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR2_SDRAM_FB_DIMM")
75313efb1cSGunnar Mills     {
76313efb1cSGunnar Mills         return "DDR2_SDRAM_FB_DIMM";
77313efb1cSGunnar Mills     }
78*0fda0f12SGeorge Liu     if (memoryType ==
79*0fda0f12SGeorge Liu         "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR2_SDRAM_FB_DIMM_PROB")
80313efb1cSGunnar Mills     {
81313efb1cSGunnar Mills         return "DDR2_SDRAM_FB_DIMM_PROBE";
82313efb1cSGunnar Mills     }
83313efb1cSGunnar Mills     if (memoryType ==
84313efb1cSGunnar Mills         "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR_SGRAM")
85313efb1cSGunnar Mills     {
86313efb1cSGunnar Mills         return "DDR_SGRAM";
87313efb1cSGunnar Mills     }
88313efb1cSGunnar Mills     if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.ROM")
89313efb1cSGunnar Mills     {
90313efb1cSGunnar Mills         return "ROM";
91313efb1cSGunnar Mills     }
92313efb1cSGunnar Mills     if (memoryType ==
93313efb1cSGunnar Mills         "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.SDRAM")
94313efb1cSGunnar Mills     {
95313efb1cSGunnar Mills         return "SDRAM";
96313efb1cSGunnar Mills     }
97313efb1cSGunnar Mills     if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.EDO")
98313efb1cSGunnar Mills     {
99313efb1cSGunnar Mills         return "EDO";
100313efb1cSGunnar Mills     }
101313efb1cSGunnar Mills     if (memoryType ==
102313efb1cSGunnar Mills         "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.FastPageMode")
103313efb1cSGunnar Mills     {
104313efb1cSGunnar Mills         return "FastPageMode";
105313efb1cSGunnar Mills     }
106313efb1cSGunnar Mills     if (memoryType ==
107313efb1cSGunnar Mills         "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.PipelinedNibble")
108313efb1cSGunnar Mills     {
109313efb1cSGunnar Mills         return "PipelinedNibble";
110313efb1cSGunnar Mills     }
111313efb1cSGunnar Mills     if (memoryType ==
112313efb1cSGunnar Mills         "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.Logical")
113313efb1cSGunnar Mills     {
114313efb1cSGunnar Mills         return "Logical";
115313efb1cSGunnar Mills     }
116313efb1cSGunnar Mills     if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.HBM")
117313efb1cSGunnar Mills     {
118313efb1cSGunnar Mills         return "HBM";
119313efb1cSGunnar Mills     }
120313efb1cSGunnar Mills     if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.HBM2")
121313efb1cSGunnar Mills     {
122313efb1cSGunnar Mills         return "HBM2";
123313efb1cSGunnar Mills     }
124313efb1cSGunnar Mills     // This is values like Other or Unknown
125313efb1cSGunnar Mills     // Also D-Bus values:
126313efb1cSGunnar Mills     // DRAM
127313efb1cSGunnar Mills     // EDRAM
128313efb1cSGunnar Mills     // VRAM
129313efb1cSGunnar Mills     // SRAM
130313efb1cSGunnar Mills     // RAM
131313efb1cSGunnar Mills     // FLASH
132313efb1cSGunnar Mills     // EEPROM
133313efb1cSGunnar Mills     // FEPROM
134313efb1cSGunnar Mills     // EPROM
135313efb1cSGunnar Mills     // CDRAM
136313efb1cSGunnar Mills     // ThreeDRAM
137313efb1cSGunnar Mills     // RDRAM
138313efb1cSGunnar Mills     // FBD2
139313efb1cSGunnar Mills     // LPDDR_SDRAM
140313efb1cSGunnar Mills     // LPDDR2_SDRAM
14111a2f0f0SMansi Joshi     // LPDDR5_SDRAM
142313efb1cSGunnar Mills     return "";
143313efb1cSGunnar Mills }
144313efb1cSGunnar Mills 
1458d1b46d7Szhanghch05 inline void dimmPropToHex(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
146ac6a4445SGunnar Mills                           const char* key,
147ac6a4445SGunnar Mills                           const std::pair<std::string, DimmProperty>& property)
148ac6a4445SGunnar Mills {
149ac6a4445SGunnar Mills     const uint16_t* value = std::get_if<uint16_t>(&property.second);
150ac6a4445SGunnar Mills     if (value == nullptr)
151ac6a4445SGunnar Mills     {
152ac6a4445SGunnar Mills         messages::internalError(aResp->res);
153ac6a4445SGunnar Mills         BMCWEB_LOG_DEBUG << "Invalid property type for " << property.first;
154ac6a4445SGunnar Mills         return;
155ac6a4445SGunnar Mills     }
156ac6a4445SGunnar Mills 
157f201ffb4SEd Tanous     aResp->res.jsonValue[key] = "0x" + intToHexString(*value);
158ac6a4445SGunnar Mills }
159ac6a4445SGunnar Mills 
1608d1b46d7Szhanghch05 inline void getPersistentMemoryProperties(
1618d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& aResp,
162ac6a4445SGunnar Mills     const DimmProperties& properties)
163ac6a4445SGunnar Mills {
164ac6a4445SGunnar Mills     for (const auto& property : properties)
165ac6a4445SGunnar Mills     {
166ac6a4445SGunnar Mills         if (property.first == "ModuleManufacturerID")
167ac6a4445SGunnar Mills         {
168ac6a4445SGunnar Mills             dimmPropToHex(aResp, "ModuleManufacturerID", property);
169ac6a4445SGunnar Mills         }
170ac6a4445SGunnar Mills         else if (property.first == "ModuleProductID")
171ac6a4445SGunnar Mills         {
172ac6a4445SGunnar Mills             dimmPropToHex(aResp, "ModuleProductID", property);
173ac6a4445SGunnar Mills         }
174ac6a4445SGunnar Mills         else if (property.first == "SubsystemVendorID")
175ac6a4445SGunnar Mills         {
176ac6a4445SGunnar Mills             dimmPropToHex(aResp, "MemorySubsystemControllerManufacturerID",
177ac6a4445SGunnar Mills                           property);
178ac6a4445SGunnar Mills         }
179ac6a4445SGunnar Mills         else if (property.first == "SubsystemDeviceID")
180ac6a4445SGunnar Mills         {
181ac6a4445SGunnar Mills             dimmPropToHex(aResp, "MemorySubsystemControllerProductID",
182ac6a4445SGunnar Mills                           property);
183ac6a4445SGunnar Mills         }
184ac6a4445SGunnar Mills         else if (property.first == "VolatileRegionSizeLimitInKiB")
185ac6a4445SGunnar Mills         {
186ac6a4445SGunnar Mills             const uint64_t* value = std::get_if<uint64_t>(&property.second);
187ac6a4445SGunnar Mills 
188ac6a4445SGunnar Mills             if (value == nullptr)
189ac6a4445SGunnar Mills             {
190ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
191*0fda0f12SGeorge Liu                 BMCWEB_LOG_DEBUG
192*0fda0f12SGeorge Liu                     << "Invalid property type for VolatileRegionSizeLimitKiB";
193601af5edSChicago Duan                 return;
194ac6a4445SGunnar Mills             }
195ac6a4445SGunnar Mills             aResp->res.jsonValue["VolatileRegionSizeLimitMiB"] = (*value) >> 10;
196ac6a4445SGunnar Mills         }
197ac6a4445SGunnar Mills         else if (property.first == "PmRegionSizeLimitInKiB")
198ac6a4445SGunnar Mills         {
199ac6a4445SGunnar Mills             const uint64_t* value = std::get_if<uint64_t>(&property.second);
200ac6a4445SGunnar Mills 
201ac6a4445SGunnar Mills             if (value == nullptr)
202ac6a4445SGunnar Mills             {
203ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
204ac6a4445SGunnar Mills                 BMCWEB_LOG_DEBUG
205ac6a4445SGunnar Mills                     << "Invalid property type for PmRegioSizeLimitKiB";
206601af5edSChicago Duan                 return;
207ac6a4445SGunnar Mills             }
208ac6a4445SGunnar Mills             aResp->res.jsonValue["PersistentRegionSizeLimitMiB"] =
209ac6a4445SGunnar Mills                 (*value) >> 10;
210ac6a4445SGunnar Mills         }
211ac6a4445SGunnar Mills         else if (property.first == "VolatileSizeInKiB")
212ac6a4445SGunnar Mills         {
213ac6a4445SGunnar Mills             const uint64_t* value = std::get_if<uint64_t>(&property.second);
214ac6a4445SGunnar Mills 
215ac6a4445SGunnar Mills             if (value == nullptr)
216ac6a4445SGunnar Mills             {
217ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
218ac6a4445SGunnar Mills                 BMCWEB_LOG_DEBUG
219ac6a4445SGunnar Mills                     << "Invalid property type for VolatileSizeInKiB";
220601af5edSChicago Duan                 return;
221ac6a4445SGunnar Mills             }
222ac6a4445SGunnar Mills             aResp->res.jsonValue["VolatileSizeMiB"] = (*value) >> 10;
223ac6a4445SGunnar Mills         }
224ac6a4445SGunnar Mills         else if (property.first == "PmSizeInKiB")
225ac6a4445SGunnar Mills         {
226ac6a4445SGunnar Mills             const uint64_t* value = std::get_if<uint64_t>(&property.second);
227ac6a4445SGunnar Mills             if (value == nullptr)
228ac6a4445SGunnar Mills             {
229ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
230ac6a4445SGunnar Mills                 BMCWEB_LOG_DEBUG << "Invalid property type for PmSizeInKiB";
231601af5edSChicago Duan                 return;
232ac6a4445SGunnar Mills             }
233ac6a4445SGunnar Mills             aResp->res.jsonValue["NonVolatileSizeMiB"] = (*value) >> 10;
234ac6a4445SGunnar Mills         }
235ac6a4445SGunnar Mills         else if (property.first == "CacheSizeInKB")
236ac6a4445SGunnar Mills         {
237ac6a4445SGunnar Mills             const uint64_t* value = std::get_if<uint64_t>(&property.second);
238ac6a4445SGunnar Mills             if (value == nullptr)
239ac6a4445SGunnar Mills             {
240ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
241ac6a4445SGunnar Mills                 BMCWEB_LOG_DEBUG << "Invalid property type for CacheSizeInKB";
242601af5edSChicago Duan                 return;
243ac6a4445SGunnar Mills             }
244ac6a4445SGunnar Mills             aResp->res.jsonValue["CacheSizeMiB"] = (*value >> 10);
245ac6a4445SGunnar Mills         }
246ac6a4445SGunnar Mills 
247ac6a4445SGunnar Mills         else if (property.first == "VoltaileRegionMaxSizeInKib")
248ac6a4445SGunnar Mills         {
249ac6a4445SGunnar Mills             const uint64_t* value = std::get_if<uint64_t>(&property.second);
250ac6a4445SGunnar Mills 
251ac6a4445SGunnar Mills             if (value == nullptr)
252ac6a4445SGunnar Mills             {
253ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
254*0fda0f12SGeorge Liu                 BMCWEB_LOG_DEBUG
255*0fda0f12SGeorge Liu                     << "Invalid property type for VolatileRegionMaxSizeInKib";
256601af5edSChicago Duan                 return;
257ac6a4445SGunnar Mills             }
258ac6a4445SGunnar Mills             aResp->res.jsonValue["VolatileRegionSizeMaxMiB"] = (*value) >> 10;
259ac6a4445SGunnar Mills         }
260ac6a4445SGunnar Mills         else if (property.first == "PmRegionMaxSizeInKiB")
261ac6a4445SGunnar Mills         {
262ac6a4445SGunnar Mills             const uint64_t* value = std::get_if<uint64_t>(&property.second);
263ac6a4445SGunnar Mills 
264ac6a4445SGunnar Mills             if (value == nullptr)
265ac6a4445SGunnar Mills             {
266ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
267ac6a4445SGunnar Mills                 BMCWEB_LOG_DEBUG
268ac6a4445SGunnar Mills                     << "Invalid property type for PmRegionMaxSizeInKiB";
269601af5edSChicago Duan                 return;
270ac6a4445SGunnar Mills             }
271ac6a4445SGunnar Mills             aResp->res.jsonValue["PersistentRegionSizeMaxMiB"] = (*value) >> 10;
272ac6a4445SGunnar Mills         }
273ac6a4445SGunnar Mills         else if (property.first == "AllocationIncrementInKiB")
274ac6a4445SGunnar Mills         {
275ac6a4445SGunnar Mills             const uint64_t* value = std::get_if<uint64_t>(&property.second);
276ac6a4445SGunnar Mills 
277ac6a4445SGunnar Mills             if (value == nullptr)
278ac6a4445SGunnar Mills             {
279ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
280*0fda0f12SGeorge Liu                 BMCWEB_LOG_DEBUG
281*0fda0f12SGeorge Liu                     << "Invalid property type for AllocationIncrementInKiB";
282601af5edSChicago Duan                 return;
283ac6a4445SGunnar Mills             }
284ac6a4445SGunnar Mills             aResp->res.jsonValue["AllocationIncrementMiB"] = (*value) >> 10;
285ac6a4445SGunnar Mills         }
286ac6a4445SGunnar Mills         else if (property.first == "AllocationAlignmentInKiB")
287ac6a4445SGunnar Mills         {
288ac6a4445SGunnar Mills             const uint64_t* value = std::get_if<uint64_t>(&property.second);
289ac6a4445SGunnar Mills 
290ac6a4445SGunnar Mills             if (value == nullptr)
291ac6a4445SGunnar Mills             {
292ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
293*0fda0f12SGeorge Liu                 BMCWEB_LOG_DEBUG
294*0fda0f12SGeorge Liu                     << "Invalid property type for AllocationAlignmentInKiB";
295601af5edSChicago Duan                 return;
296ac6a4445SGunnar Mills             }
297ac6a4445SGunnar Mills             aResp->res.jsonValue["AllocationAlignmentMiB"] = (*value) >> 10;
298ac6a4445SGunnar Mills         }
299ac6a4445SGunnar Mills         else if (property.first == "VolatileRegionNumberLimit")
300ac6a4445SGunnar Mills         {
301ac6a4445SGunnar Mills             const uint64_t* value = std::get_if<uint64_t>(&property.second);
302ac6a4445SGunnar Mills             if (value == nullptr)
303ac6a4445SGunnar Mills             {
304ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
305601af5edSChicago Duan                 return;
306ac6a4445SGunnar Mills             }
307ac6a4445SGunnar Mills             aResp->res.jsonValue["VolatileRegionNumberLimit"] = *value;
308ac6a4445SGunnar Mills         }
309ac6a4445SGunnar Mills         else if (property.first == "PmRegionNumberLimit")
310ac6a4445SGunnar Mills         {
311ac6a4445SGunnar Mills             const uint64_t* value = std::get_if<uint64_t>(&property.second);
312ac6a4445SGunnar Mills             if (value == nullptr)
313ac6a4445SGunnar Mills             {
314ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
315601af5edSChicago Duan                 return;
316ac6a4445SGunnar Mills             }
317ac6a4445SGunnar Mills             aResp->res.jsonValue["PersistentRegionNumberLimit"] = *value;
318ac6a4445SGunnar Mills         }
319ac6a4445SGunnar Mills         else if (property.first == "SpareDeviceCount")
320ac6a4445SGunnar Mills         {
321ac6a4445SGunnar Mills             const uint64_t* value = std::get_if<uint64_t>(&property.second);
322ac6a4445SGunnar Mills             if (value == nullptr)
323ac6a4445SGunnar Mills             {
324ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
325601af5edSChicago Duan                 return;
326ac6a4445SGunnar Mills             }
327ac6a4445SGunnar Mills             aResp->res.jsonValue["SpareDeviceCount"] = *value;
328ac6a4445SGunnar Mills         }
329ac6a4445SGunnar Mills         else if (property.first == "IsSpareDeviceInUse")
330ac6a4445SGunnar Mills         {
331ac6a4445SGunnar Mills             const bool* value = std::get_if<bool>(&property.second);
332ac6a4445SGunnar Mills             if (value == nullptr)
333ac6a4445SGunnar Mills             {
334ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
335601af5edSChicago Duan                 return;
336ac6a4445SGunnar Mills             }
337ac6a4445SGunnar Mills             aResp->res.jsonValue["IsSpareDeviceEnabled"] = *value;
338ac6a4445SGunnar Mills         }
339ac6a4445SGunnar Mills         else if (property.first == "IsRankSpareEnabled")
340ac6a4445SGunnar Mills         {
341ac6a4445SGunnar Mills             const bool* value = std::get_if<bool>(&property.second);
342ac6a4445SGunnar Mills             if (value == nullptr)
343ac6a4445SGunnar Mills             {
344ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
345601af5edSChicago Duan                 return;
346ac6a4445SGunnar Mills             }
347ac6a4445SGunnar Mills             aResp->res.jsonValue["IsRankSpareEnabled"] = *value;
348ac6a4445SGunnar Mills         }
349ac6a4445SGunnar Mills         else if (property.first == "MaxAveragePowerLimitmW")
350ac6a4445SGunnar Mills         {
351ac6a4445SGunnar Mills             const auto* value =
352ac6a4445SGunnar Mills                 std::get_if<std::vector<uint32_t>>(&property.second);
353ac6a4445SGunnar Mills             if (value == nullptr)
354ac6a4445SGunnar Mills             {
355ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
356*0fda0f12SGeorge Liu                 BMCWEB_LOG_DEBUG
357*0fda0f12SGeorge Liu                     << "Invalid property type for MaxAveragePowerLimitmW";
358601af5edSChicago Duan                 return;
359ac6a4445SGunnar Mills             }
360ac6a4445SGunnar Mills             aResp->res.jsonValue["MaxTDPMilliWatts"] = *value;
361ac6a4445SGunnar Mills         }
362ac6a4445SGunnar Mills         else if (property.first == "ConfigurationLocked")
363ac6a4445SGunnar Mills         {
364ac6a4445SGunnar Mills             const bool* value = std::get_if<bool>(&property.second);
365ac6a4445SGunnar Mills             if (value == nullptr)
366ac6a4445SGunnar Mills             {
367ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
368601af5edSChicago Duan                 return;
369ac6a4445SGunnar Mills             }
370ac6a4445SGunnar Mills             aResp->res.jsonValue["ConfigurationLocked"] = *value;
371ac6a4445SGunnar Mills         }
372ac6a4445SGunnar Mills         else if (property.first == "AllowedMemoryModes")
373ac6a4445SGunnar Mills         {
374ac6a4445SGunnar Mills             const std::string* value =
375ac6a4445SGunnar Mills                 std::get_if<std::string>(&property.second);
376ac6a4445SGunnar Mills             if (value == nullptr)
377ac6a4445SGunnar Mills             {
378ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
379ac6a4445SGunnar Mills                 BMCWEB_LOG_DEBUG << "Invalid property type for FormFactor";
380601af5edSChicago Duan                 return;
381ac6a4445SGunnar Mills             }
382ac6a4445SGunnar Mills             constexpr const std::array<const char*, 3> values{"Volatile",
383ac6a4445SGunnar Mills                                                               "PMEM", "Block"};
384ac6a4445SGunnar Mills 
385ac6a4445SGunnar Mills             for (const char* v : values)
386ac6a4445SGunnar Mills             {
387ac6a4445SGunnar Mills                 if (boost::ends_with(*value, v))
388ac6a4445SGunnar Mills                 {
389ac6a4445SGunnar Mills                     aResp->res.jsonValue["OperatingMemoryModes "] = v;
390ac6a4445SGunnar Mills                     break;
391ac6a4445SGunnar Mills                 }
392ac6a4445SGunnar Mills             }
393ac6a4445SGunnar Mills         }
394ac6a4445SGunnar Mills         else if (property.first == "MemoryMedia")
395ac6a4445SGunnar Mills         {
396ac6a4445SGunnar Mills             const std::string* value =
397ac6a4445SGunnar Mills                 std::get_if<std::string>(&property.second);
398ac6a4445SGunnar Mills             if (value == nullptr)
399ac6a4445SGunnar Mills             {
400ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
401ac6a4445SGunnar Mills                 BMCWEB_LOG_DEBUG << "Invalid property type for MemoryMedia";
402601af5edSChicago Duan                 return;
403ac6a4445SGunnar Mills             }
404ac6a4445SGunnar Mills             constexpr const std::array<const char*, 3> values{"DRAM", "NAND",
405ac6a4445SGunnar Mills                                                               "Intel3DXPoint"};
406ac6a4445SGunnar Mills 
407ac6a4445SGunnar Mills             for (const char* v : values)
408ac6a4445SGunnar Mills             {
409ac6a4445SGunnar Mills                 if (boost::ends_with(*value, v))
410ac6a4445SGunnar Mills                 {
411ac6a4445SGunnar Mills                     aResp->res.jsonValue["MemoryMedia"] = v;
412ac6a4445SGunnar Mills                     break;
413ac6a4445SGunnar Mills                 }
414ac6a4445SGunnar Mills             }
415ac6a4445SGunnar Mills         }
416ac6a4445SGunnar Mills         // PersistantMemory.SecurityCapabilites interface
417ac6a4445SGunnar Mills         else if (property.first == "ConfigurationLockCapable" ||
418ac6a4445SGunnar Mills                  property.first == "DataLockCapable" ||
419ac6a4445SGunnar Mills                  property.first == "PassphraseCapable")
420ac6a4445SGunnar Mills         {
421ac6a4445SGunnar Mills             const bool* value = std::get_if<bool>(&property.second);
422ac6a4445SGunnar Mills             if (value == nullptr)
423ac6a4445SGunnar Mills             {
424ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
425601af5edSChicago Duan                 return;
426ac6a4445SGunnar Mills             }
427ac6a4445SGunnar Mills             aResp->res.jsonValue["SecurityCapabilities"][property.first] =
428ac6a4445SGunnar Mills                 *value;
429ac6a4445SGunnar Mills         }
430ac6a4445SGunnar Mills         else if (property.first == "MaxPassphraseCount" ||
431ac6a4445SGunnar Mills                  property.first == "PassphraseLockLimit")
432ac6a4445SGunnar Mills         {
433ac6a4445SGunnar Mills             const uint64_t* value = std::get_if<uint64_t>(&property.second);
434ac6a4445SGunnar Mills             if (value == nullptr)
435ac6a4445SGunnar Mills             {
436ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
437601af5edSChicago Duan                 return;
438ac6a4445SGunnar Mills             }
439ac6a4445SGunnar Mills             aResp->res.jsonValue["SecurityCapabilities"][property.first] =
440ac6a4445SGunnar Mills                 *value;
441ac6a4445SGunnar Mills         }
442ac6a4445SGunnar Mills     }
443ac6a4445SGunnar Mills }
444ac6a4445SGunnar Mills 
4458d1b46d7Szhanghch05 inline void getDimmDataByService(std::shared_ptr<bmcweb::AsyncResp> aResp,
446ac6a4445SGunnar Mills                                  const std::string& dimmId,
447ac6a4445SGunnar Mills                                  const std::string& service,
448ac6a4445SGunnar Mills                                  const std::string& objPath)
449ac6a4445SGunnar Mills {
450ac6a4445SGunnar Mills     auto health = std::make_shared<HealthPopulate>(aResp);
451ac6a4445SGunnar Mills     health->selfPath = objPath;
452ac6a4445SGunnar Mills     health->populate();
453ac6a4445SGunnar Mills 
454ac6a4445SGunnar Mills     BMCWEB_LOG_DEBUG << "Get available system components.";
455ac6a4445SGunnar Mills     crow::connections::systemBus->async_method_call(
456ac6a4445SGunnar Mills         [dimmId, aResp{std::move(aResp)}](const boost::system::error_code ec,
457ac6a4445SGunnar Mills                                           const DimmProperties& properties) {
458ac6a4445SGunnar Mills             if (ec)
459ac6a4445SGunnar Mills             {
460ac6a4445SGunnar Mills                 BMCWEB_LOG_DEBUG << "DBUS response error";
461ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
462ac6a4445SGunnar Mills 
463ac6a4445SGunnar Mills                 return;
464ac6a4445SGunnar Mills             }
465ac6a4445SGunnar Mills             aResp->res.jsonValue["Id"] = dimmId;
466ac6a4445SGunnar Mills             aResp->res.jsonValue["Name"] = "DIMM Slot";
467ac6a4445SGunnar Mills 
468ac6a4445SGunnar Mills             const auto memorySizeProperty = properties.find("MemorySizeInKB");
469ac6a4445SGunnar Mills             if (memorySizeProperty != properties.end())
470ac6a4445SGunnar Mills             {
471ac6a4445SGunnar Mills                 const uint32_t* memorySize =
472ac6a4445SGunnar Mills                     std::get_if<uint32_t>(&memorySizeProperty->second);
473ac6a4445SGunnar Mills                 if (memorySize == nullptr)
474ac6a4445SGunnar Mills                 {
475ac6a4445SGunnar Mills                     // Important property not in desired type
476ac6a4445SGunnar Mills                     messages::internalError(aResp->res);
477ac6a4445SGunnar Mills                     return;
478ac6a4445SGunnar Mills                 }
479ac6a4445SGunnar Mills                 aResp->res.jsonValue["CapacityMiB"] = (*memorySize >> 10);
480ac6a4445SGunnar Mills             }
481ac6a4445SGunnar Mills             aResp->res.jsonValue["Status"]["State"] = "Enabled";
482ac6a4445SGunnar Mills             aResp->res.jsonValue["Status"]["Health"] = "OK";
483ac6a4445SGunnar Mills 
484ac6a4445SGunnar Mills             for (const auto& property : properties)
485ac6a4445SGunnar Mills             {
486ac6a4445SGunnar Mills                 if (property.first == "MemoryDataWidth")
487ac6a4445SGunnar Mills                 {
488ac6a4445SGunnar Mills                     const uint16_t* value =
489ac6a4445SGunnar Mills                         std::get_if<uint16_t>(&property.second);
490ac6a4445SGunnar Mills                     if (value == nullptr)
491ac6a4445SGunnar Mills                     {
492ac6a4445SGunnar Mills                         continue;
493ac6a4445SGunnar Mills                     }
494ac6a4445SGunnar Mills                     aResp->res.jsonValue["DataWidthBits"] = *value;
495ac6a4445SGunnar Mills                 }
496ac6a4445SGunnar Mills                 else if (property.first == "PartNumber")
497ac6a4445SGunnar Mills                 {
498ac6a4445SGunnar Mills                     const std::string* value =
499ac6a4445SGunnar Mills                         std::get_if<std::string>(&property.second);
500ac6a4445SGunnar Mills                     if (value == nullptr)
501ac6a4445SGunnar Mills                     {
502ac6a4445SGunnar Mills                         continue;
503ac6a4445SGunnar Mills                     }
504ac6a4445SGunnar Mills                     aResp->res.jsonValue["PartNumber"] = *value;
505ac6a4445SGunnar Mills                 }
506ac6a4445SGunnar Mills                 else if (property.first == "SerialNumber")
507ac6a4445SGunnar Mills                 {
508ac6a4445SGunnar Mills                     const std::string* value =
509ac6a4445SGunnar Mills                         std::get_if<std::string>(&property.second);
510ac6a4445SGunnar Mills                     if (value == nullptr)
511ac6a4445SGunnar Mills                     {
512ac6a4445SGunnar Mills                         continue;
513ac6a4445SGunnar Mills                     }
514ac6a4445SGunnar Mills                     aResp->res.jsonValue["SerialNumber"] = *value;
515ac6a4445SGunnar Mills                 }
516ac6a4445SGunnar Mills                 else if (property.first == "Manufacturer")
517ac6a4445SGunnar Mills                 {
518ac6a4445SGunnar Mills                     const std::string* value =
519ac6a4445SGunnar Mills                         std::get_if<std::string>(&property.second);
520ac6a4445SGunnar Mills                     if (value == nullptr)
521ac6a4445SGunnar Mills                     {
522ac6a4445SGunnar Mills                         continue;
523ac6a4445SGunnar Mills                     }
524ac6a4445SGunnar Mills                     aResp->res.jsonValue["Manufacturer"] = *value;
525ac6a4445SGunnar Mills                 }
526ac6a4445SGunnar Mills                 else if (property.first == "RevisionCode")
527ac6a4445SGunnar Mills                 {
528ac6a4445SGunnar Mills                     const uint16_t* value =
529ac6a4445SGunnar Mills                         std::get_if<uint16_t>(&property.second);
530ac6a4445SGunnar Mills 
531ac6a4445SGunnar Mills                     if (value == nullptr)
532ac6a4445SGunnar Mills                     {
533ac6a4445SGunnar Mills                         messages::internalError(aResp->res);
534ac6a4445SGunnar Mills                         BMCWEB_LOG_DEBUG
535ac6a4445SGunnar Mills                             << "Invalid property type for RevisionCode";
536601af5edSChicago Duan                         return;
537ac6a4445SGunnar Mills                     }
538ac6a4445SGunnar Mills                     aResp->res.jsonValue["FirmwareRevision"] =
539ac6a4445SGunnar Mills                         std::to_string(*value);
540ac6a4445SGunnar Mills                 }
5419a128eb3SJoshi-Mansi                 else if (property.first == "Present")
5429a128eb3SJoshi-Mansi                 {
5439a128eb3SJoshi-Mansi                     const bool* value = std::get_if<bool>(&property.second);
5449a128eb3SJoshi-Mansi                     if (value == nullptr)
5459a128eb3SJoshi-Mansi                     {
5469a128eb3SJoshi-Mansi                         messages::internalError(aResp->res);
5479a128eb3SJoshi-Mansi                         BMCWEB_LOG_DEBUG
5489a128eb3SJoshi-Mansi                             << "Invalid property type for Dimm Presence";
5499a128eb3SJoshi-Mansi                         return;
5509a128eb3SJoshi-Mansi                     }
5519a128eb3SJoshi-Mansi                     if (*value == false)
5529a128eb3SJoshi-Mansi                     {
5539a128eb3SJoshi-Mansi                         aResp->res.jsonValue["Status"]["State"] = "Absent";
5549a128eb3SJoshi-Mansi                     }
5559a128eb3SJoshi-Mansi                 }
556ac6a4445SGunnar Mills                 else if (property.first == "MemoryTotalWidth")
557ac6a4445SGunnar Mills                 {
558ac6a4445SGunnar Mills                     const uint16_t* value =
559ac6a4445SGunnar Mills                         std::get_if<uint16_t>(&property.second);
560ac6a4445SGunnar Mills                     if (value == nullptr)
561ac6a4445SGunnar Mills                     {
562ac6a4445SGunnar Mills                         continue;
563ac6a4445SGunnar Mills                     }
564ac6a4445SGunnar Mills                     aResp->res.jsonValue["BusWidthBits"] = *value;
565ac6a4445SGunnar Mills                 }
566ac6a4445SGunnar Mills                 else if (property.first == "ECC")
567ac6a4445SGunnar Mills                 {
568ac6a4445SGunnar Mills                     const std::string* value =
569ac6a4445SGunnar Mills                         std::get_if<std::string>(&property.second);
570ac6a4445SGunnar Mills                     if (value == nullptr)
571ac6a4445SGunnar Mills                     {
572ac6a4445SGunnar Mills                         messages::internalError(aResp->res);
573ac6a4445SGunnar Mills                         BMCWEB_LOG_DEBUG << "Invalid property type for ECC";
574601af5edSChicago Duan                         return;
575ac6a4445SGunnar Mills                     }
576ac6a4445SGunnar Mills                     constexpr const std::array<const char*, 4> values{
577ac6a4445SGunnar Mills                         "NoECC", "SingleBitECC", "MultiBitECC",
578ac6a4445SGunnar Mills                         "AddressParity"};
579ac6a4445SGunnar Mills 
580ac6a4445SGunnar Mills                     for (const char* v : values)
581ac6a4445SGunnar Mills                     {
582ac6a4445SGunnar Mills                         if (boost::ends_with(*value, v))
583ac6a4445SGunnar Mills                         {
584ac6a4445SGunnar Mills                             aResp->res.jsonValue["ErrorCorrection"] = v;
585ac6a4445SGunnar Mills                             break;
586ac6a4445SGunnar Mills                         }
587ac6a4445SGunnar Mills                     }
588ac6a4445SGunnar Mills                 }
589ac6a4445SGunnar Mills                 else if (property.first == "FormFactor")
590ac6a4445SGunnar Mills                 {
591ac6a4445SGunnar Mills                     const std::string* value =
592ac6a4445SGunnar Mills                         std::get_if<std::string>(&property.second);
593ac6a4445SGunnar Mills                     if (value == nullptr)
594ac6a4445SGunnar Mills                     {
595ac6a4445SGunnar Mills                         messages::internalError(aResp->res);
596ac6a4445SGunnar Mills                         BMCWEB_LOG_DEBUG
597ac6a4445SGunnar Mills                             << "Invalid property type for FormFactor";
598601af5edSChicago Duan                         return;
599ac6a4445SGunnar Mills                     }
600ac6a4445SGunnar Mills                     constexpr const std::array<const char*, 11> values{
601ac6a4445SGunnar Mills                         "RDIMM",        "UDIMM",        "SO_DIMM",
602ac6a4445SGunnar Mills                         "LRDIMM",       "Mini_RDIMM",   "Mini_UDIMM",
603ac6a4445SGunnar Mills                         "SO_RDIMM_72b", "SO_UDIMM_72b", "SO_DIMM_16b",
604ac6a4445SGunnar Mills                         "SO_DIMM_32b",  "Die"};
605ac6a4445SGunnar Mills 
606ac6a4445SGunnar Mills                     for (const char* v : values)
607ac6a4445SGunnar Mills                     {
608ac6a4445SGunnar Mills                         if (boost::ends_with(*value, v))
609ac6a4445SGunnar Mills                         {
610ac6a4445SGunnar Mills                             aResp->res.jsonValue["BaseModuleType"] = v;
611ac6a4445SGunnar Mills                             break;
612ac6a4445SGunnar Mills                         }
613ac6a4445SGunnar Mills                     }
614ac6a4445SGunnar Mills                 }
615ac6a4445SGunnar Mills                 else if (property.first == "AllowedSpeedsMT")
616ac6a4445SGunnar Mills                 {
617ac6a4445SGunnar Mills                     const std::vector<uint16_t>* value =
618ac6a4445SGunnar Mills                         std::get_if<std::vector<uint16_t>>(&property.second);
619ac6a4445SGunnar Mills                     if (value == nullptr)
620ac6a4445SGunnar Mills                     {
621ac6a4445SGunnar Mills                         continue;
622ac6a4445SGunnar Mills                     }
623ac6a4445SGunnar Mills                     nlohmann::json& jValue =
624ac6a4445SGunnar Mills                         aResp->res.jsonValue["AllowedSpeedsMHz"];
625ac6a4445SGunnar Mills                     jValue = nlohmann::json::array();
626ac6a4445SGunnar Mills                     for (uint16_t subVal : *value)
627ac6a4445SGunnar Mills                     {
628ac6a4445SGunnar Mills                         jValue.push_back(subVal);
629ac6a4445SGunnar Mills                     }
630ac6a4445SGunnar Mills                 }
631ac6a4445SGunnar Mills                 else if (property.first == "MemoryAttributes")
632ac6a4445SGunnar Mills                 {
633ac6a4445SGunnar Mills                     const uint8_t* value =
634ac6a4445SGunnar Mills                         std::get_if<uint8_t>(&property.second);
635ac6a4445SGunnar Mills 
636ac6a4445SGunnar Mills                     if (value == nullptr)
637ac6a4445SGunnar Mills                     {
638ac6a4445SGunnar Mills                         messages::internalError(aResp->res);
639ac6a4445SGunnar Mills                         BMCWEB_LOG_DEBUG
640ac6a4445SGunnar Mills                             << "Invalid property type for MemoryAttributes";
641601af5edSChicago Duan                         return;
642ac6a4445SGunnar Mills                     }
643ac6a4445SGunnar Mills                     aResp->res.jsonValue["RankCount"] =
644ac6a4445SGunnar Mills                         static_cast<uint64_t>(*value);
645ac6a4445SGunnar Mills                 }
646ac6a4445SGunnar Mills                 else if (property.first == "MemoryConfiguredSpeedInMhz")
647ac6a4445SGunnar Mills                 {
648ac6a4445SGunnar Mills                     const uint16_t* value =
649ac6a4445SGunnar Mills                         std::get_if<uint16_t>(&property.second);
650ac6a4445SGunnar Mills                     if (value == nullptr)
651ac6a4445SGunnar Mills                     {
652ac6a4445SGunnar Mills                         continue;
653ac6a4445SGunnar Mills                     }
654ac6a4445SGunnar Mills                     aResp->res.jsonValue["OperatingSpeedMhz"] = *value;
655ac6a4445SGunnar Mills                 }
656ac6a4445SGunnar Mills                 else if (property.first == "MemoryType")
657ac6a4445SGunnar Mills                 {
658ac6a4445SGunnar Mills                     const auto* value =
659ac6a4445SGunnar Mills                         std::get_if<std::string>(&property.second);
660ac6a4445SGunnar Mills                     if (value != nullptr)
661ac6a4445SGunnar Mills                     {
662313efb1cSGunnar Mills                         std::string memoryDeviceType =
663313efb1cSGunnar Mills                             translateMemoryTypeToRedfish(*value);
664313efb1cSGunnar Mills                         // Values like "Unknown" or "Other" will return empty
665313efb1cSGunnar Mills                         // so just leave off
666313efb1cSGunnar Mills                         if (!memoryDeviceType.empty())
667ac6a4445SGunnar Mills                         {
668313efb1cSGunnar Mills                             aResp->res.jsonValue["MemoryDeviceType"] =
669313efb1cSGunnar Mills                                 memoryDeviceType;
670ac6a4445SGunnar Mills                         }
671ac6a4445SGunnar Mills                         if (value->find("DDR") != std::string::npos)
672ac6a4445SGunnar Mills                         {
673ac6a4445SGunnar Mills                             aResp->res.jsonValue["MemoryType"] = "DRAM";
674ac6a4445SGunnar Mills                         }
675ac6a4445SGunnar Mills                         else if (boost::ends_with(*value, "Logical"))
676ac6a4445SGunnar Mills                         {
677ac6a4445SGunnar Mills                             aResp->res.jsonValue["MemoryType"] = "IntelOptane";
678ac6a4445SGunnar Mills                         }
679ac6a4445SGunnar Mills                     }
680ac6a4445SGunnar Mills                 }
681ac6a4445SGunnar Mills                 // memory location interface
682ac6a4445SGunnar Mills                 else if (property.first == "Channel" ||
683ac6a4445SGunnar Mills                          property.first == "MemoryController" ||
684ac6a4445SGunnar Mills                          property.first == "Slot" || property.first == "Socket")
685ac6a4445SGunnar Mills                 {
686ac6a4445SGunnar Mills                     const std::string* value =
687ac6a4445SGunnar Mills                         std::get_if<std::string>(&property.second);
688ac6a4445SGunnar Mills                     if (value == nullptr)
689ac6a4445SGunnar Mills                     {
690ac6a4445SGunnar Mills                         messages::internalError(aResp->res);
691601af5edSChicago Duan                         return;
692ac6a4445SGunnar Mills                     }
693ac6a4445SGunnar Mills                     aResp->res.jsonValue["MemoryLocation"][property.first] =
694ac6a4445SGunnar Mills                         *value;
695ac6a4445SGunnar Mills                 }
696ee135e24SSunnySrivastava1984                 else if (property.first == "SparePartNumber")
697ee135e24SSunnySrivastava1984                 {
698ee135e24SSunnySrivastava1984                     const std::string* value =
699ee135e24SSunnySrivastava1984                         std::get_if<std::string>(&property.second);
700ee135e24SSunnySrivastava1984                     if (value == nullptr)
701ee135e24SSunnySrivastava1984                     {
702ee135e24SSunnySrivastava1984                         messages::internalError(aResp->res);
703601af5edSChicago Duan                         return;
704ee135e24SSunnySrivastava1984                     }
705ee135e24SSunnySrivastava1984                     aResp->res.jsonValue["SparePartNumber"] = *value;
706ee135e24SSunnySrivastava1984                 }
707ee135e24SSunnySrivastava1984                 else if (property.first == "Model")
708ee135e24SSunnySrivastava1984                 {
709ee135e24SSunnySrivastava1984                     const std::string* value =
710ee135e24SSunnySrivastava1984                         std::get_if<std::string>(&property.second);
711ee135e24SSunnySrivastava1984                     if (value == nullptr)
712ee135e24SSunnySrivastava1984                     {
713ee135e24SSunnySrivastava1984                         messages::internalError(aResp->res);
714601af5edSChicago Duan                         return;
715ee135e24SSunnySrivastava1984                     }
716ee135e24SSunnySrivastava1984                     aResp->res.jsonValue["Model"] = *value;
717ee135e24SSunnySrivastava1984                 }
718ee135e24SSunnySrivastava1984                 else if (property.first == "LocationCode")
719ee135e24SSunnySrivastava1984                 {
720ee135e24SSunnySrivastava1984                     const std::string* value =
721ee135e24SSunnySrivastava1984                         std::get_if<std::string>(&property.second);
722ee135e24SSunnySrivastava1984                     if (value == nullptr)
723ee135e24SSunnySrivastava1984                     {
724ee135e24SSunnySrivastava1984                         messages::internalError(aResp->res);
725601af5edSChicago Duan                         return;
726ee135e24SSunnySrivastava1984                     }
727ee135e24SSunnySrivastava1984                     aResp->res
728ee135e24SSunnySrivastava1984                         .jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
729ee135e24SSunnySrivastava1984                         *value;
730ee135e24SSunnySrivastava1984                 }
731ac6a4445SGunnar Mills                 else
732ac6a4445SGunnar Mills                 {
733ac6a4445SGunnar Mills                     getPersistentMemoryProperties(aResp, properties);
734ac6a4445SGunnar Mills                 }
735ac6a4445SGunnar Mills             }
736ac6a4445SGunnar Mills         },
737ac6a4445SGunnar Mills         service, objPath, "org.freedesktop.DBus.Properties", "GetAll", "");
738ac6a4445SGunnar Mills }
739ac6a4445SGunnar Mills 
7408d1b46d7Szhanghch05 inline void getDimmPartitionData(std::shared_ptr<bmcweb::AsyncResp> aResp,
741ac6a4445SGunnar Mills                                  const std::string& service,
742ac6a4445SGunnar Mills                                  const std::string& path)
743ac6a4445SGunnar Mills {
744ac6a4445SGunnar Mills     crow::connections::systemBus->async_method_call(
745ac6a4445SGunnar Mills         [aResp{std::move(aResp)}](
746ac6a4445SGunnar Mills             const boost::system::error_code ec,
747ac6a4445SGunnar Mills             const boost::container::flat_map<
748ac6a4445SGunnar Mills                 std::string, std::variant<std::string, uint64_t, uint32_t,
749ac6a4445SGunnar Mills                                           bool>>& properties) {
750ac6a4445SGunnar Mills             if (ec)
751ac6a4445SGunnar Mills             {
752ac6a4445SGunnar Mills                 BMCWEB_LOG_DEBUG << "DBUS response error";
753ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
754ac6a4445SGunnar Mills 
755ac6a4445SGunnar Mills                 return;
756ac6a4445SGunnar Mills             }
757ac6a4445SGunnar Mills 
758ac6a4445SGunnar Mills             nlohmann::json& partition =
759ac6a4445SGunnar Mills                 aResp->res.jsonValue["Regions"].emplace_back(
760ac6a4445SGunnar Mills                     nlohmann::json::object());
761ac6a4445SGunnar Mills             for (const auto& [key, val] : properties)
762ac6a4445SGunnar Mills             {
763ac6a4445SGunnar Mills                 if (key == "MemoryClassification")
764ac6a4445SGunnar Mills                 {
765ac6a4445SGunnar Mills                     const std::string* value = std::get_if<std::string>(&val);
766ac6a4445SGunnar Mills                     if (value == nullptr)
767ac6a4445SGunnar Mills                     {
768ac6a4445SGunnar Mills                         messages::internalError(aResp->res);
769601af5edSChicago Duan                         return;
770ac6a4445SGunnar Mills                     }
771ac6a4445SGunnar Mills                     partition[key] = *value;
772ac6a4445SGunnar Mills                 }
773ac6a4445SGunnar Mills                 else if (key == "OffsetInKiB")
774ac6a4445SGunnar Mills                 {
775ac6a4445SGunnar Mills                     const uint64_t* value = std::get_if<uint64_t>(&val);
776ac6a4445SGunnar Mills                     if (value == nullptr)
777ac6a4445SGunnar Mills                     {
778ac6a4445SGunnar Mills                         messages::internalError(aResp->res);
779601af5edSChicago Duan                         return;
780ac6a4445SGunnar Mills                     }
781ac6a4445SGunnar Mills 
782ac6a4445SGunnar Mills                     partition["OffsetMiB"] = (*value >> 10);
783ac6a4445SGunnar Mills                 }
784ac6a4445SGunnar Mills                 else if (key == "PartitionId")
785ac6a4445SGunnar Mills                 {
786ac6a4445SGunnar Mills                     const std::string* value = std::get_if<std::string>(&val);
787ac6a4445SGunnar Mills                     if (value == nullptr)
788ac6a4445SGunnar Mills                     {
789ac6a4445SGunnar Mills                         messages::internalError(aResp->res);
790601af5edSChicago Duan                         return;
791ac6a4445SGunnar Mills                     }
792ac6a4445SGunnar Mills                     partition["RegionId"] = *value;
793ac6a4445SGunnar Mills                 }
794ac6a4445SGunnar Mills 
795ac6a4445SGunnar Mills                 else if (key == "PassphraseState")
796ac6a4445SGunnar Mills                 {
797ac6a4445SGunnar Mills                     const bool* value = std::get_if<bool>(&val);
798ac6a4445SGunnar Mills                     if (value == nullptr)
799ac6a4445SGunnar Mills                     {
800ac6a4445SGunnar Mills                         messages::internalError(aResp->res);
801601af5edSChicago Duan                         return;
802ac6a4445SGunnar Mills                     }
803ac6a4445SGunnar Mills                     partition["PassphraseEnabled"] = *value;
804ac6a4445SGunnar Mills                 }
805ac6a4445SGunnar Mills                 else if (key == "SizeInKiB")
806ac6a4445SGunnar Mills                 {
807ac6a4445SGunnar Mills                     const uint64_t* value = std::get_if<uint64_t>(&val);
808ac6a4445SGunnar Mills                     if (value == nullptr)
809ac6a4445SGunnar Mills                     {
810ac6a4445SGunnar Mills                         messages::internalError(aResp->res);
811ac6a4445SGunnar Mills                         BMCWEB_LOG_DEBUG
812ac6a4445SGunnar Mills                             << "Invalid property type for SizeInKiB";
813601af5edSChicago Duan                         return;
814ac6a4445SGunnar Mills                     }
815ac6a4445SGunnar Mills                     partition["SizeMiB"] = (*value >> 10);
816ac6a4445SGunnar Mills                 }
817ac6a4445SGunnar Mills             }
818ac6a4445SGunnar Mills         },
819ac6a4445SGunnar Mills 
820ac6a4445SGunnar Mills         service, path, "org.freedesktop.DBus.Properties", "GetAll",
821ac6a4445SGunnar Mills         "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition");
822ac6a4445SGunnar Mills }
823ac6a4445SGunnar Mills 
8248d1b46d7Szhanghch05 inline void getDimmData(std::shared_ptr<bmcweb::AsyncResp> aResp,
825ac6a4445SGunnar Mills                         const std::string& dimmId)
826ac6a4445SGunnar Mills {
827ac6a4445SGunnar Mills     BMCWEB_LOG_DEBUG << "Get available system dimm resources.";
828ac6a4445SGunnar Mills     crow::connections::systemBus->async_method_call(
829ac6a4445SGunnar Mills         [dimmId, aResp{std::move(aResp)}](
830ac6a4445SGunnar Mills             const boost::system::error_code ec,
831ac6a4445SGunnar Mills             const boost::container::flat_map<
832ac6a4445SGunnar Mills                 std::string, boost::container::flat_map<
833ac6a4445SGunnar Mills                                  std::string, std::vector<std::string>>>&
834ac6a4445SGunnar Mills                 subtree) {
835ac6a4445SGunnar Mills             if (ec)
836ac6a4445SGunnar Mills             {
837ac6a4445SGunnar Mills                 BMCWEB_LOG_DEBUG << "DBUS response error";
838ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
839ac6a4445SGunnar Mills 
840ac6a4445SGunnar Mills                 return;
841ac6a4445SGunnar Mills             }
842ac6a4445SGunnar Mills             bool found = false;
843ac6a4445SGunnar Mills             for (const auto& [path, object] : subtree)
844ac6a4445SGunnar Mills             {
845ac6a4445SGunnar Mills                 if (path.find(dimmId) != std::string::npos)
846ac6a4445SGunnar Mills                 {
847ac6a4445SGunnar Mills                     for (const auto& [service, interfaces] : object)
848ac6a4445SGunnar Mills                     {
849ac6a4445SGunnar Mills                         if (!found &&
850ac6a4445SGunnar Mills                             (std::find(
851ac6a4445SGunnar Mills                                  interfaces.begin(), interfaces.end(),
852ac6a4445SGunnar Mills                                  "xyz.openbmc_project.Inventory.Item.Dimm") !=
853ac6a4445SGunnar Mills                              interfaces.end()))
854ac6a4445SGunnar Mills                         {
855ac6a4445SGunnar Mills                             getDimmDataByService(aResp, dimmId, service, path);
856ac6a4445SGunnar Mills                             found = true;
857ac6a4445SGunnar Mills                         }
858ac6a4445SGunnar Mills 
859ac6a4445SGunnar Mills                         // partitions are separate as there can be multiple per
860ac6a4445SGunnar Mills                         // device, i.e.
861ac6a4445SGunnar Mills                         // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition1
862ac6a4445SGunnar Mills                         // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition2
863*0fda0f12SGeorge Liu                         if (std::find(
864*0fda0f12SGeorge Liu                                 interfaces.begin(), interfaces.end(),
865*0fda0f12SGeorge Liu                                 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition") !=
866ac6a4445SGunnar Mills                             interfaces.end())
867ac6a4445SGunnar Mills                         {
868ac6a4445SGunnar Mills                             getDimmPartitionData(aResp, service, path);
869ac6a4445SGunnar Mills                         }
870ac6a4445SGunnar Mills                     }
871ac6a4445SGunnar Mills                 }
872ac6a4445SGunnar Mills             }
873ac6a4445SGunnar Mills             // Object not found
874ac6a4445SGunnar Mills             if (!found)
875ac6a4445SGunnar Mills             {
876ac6a4445SGunnar Mills                 messages::resourceNotFound(aResp->res, "Memory", dimmId);
877ac6a4445SGunnar Mills             }
878ac6a4445SGunnar Mills             return;
879ac6a4445SGunnar Mills         },
880ac6a4445SGunnar Mills         "xyz.openbmc_project.ObjectMapper",
881ac6a4445SGunnar Mills         "/xyz/openbmc_project/object_mapper",
882ac6a4445SGunnar Mills         "xyz.openbmc_project.ObjectMapper", "GetSubTree",
883ac6a4445SGunnar Mills         "/xyz/openbmc_project/inventory", 0,
884ac6a4445SGunnar Mills         std::array<const char*, 2>{
885ac6a4445SGunnar Mills             "xyz.openbmc_project.Inventory.Item.Dimm",
886ac6a4445SGunnar Mills             "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition"});
887ac6a4445SGunnar Mills }
888ac6a4445SGunnar Mills 
8897e860f15SJohn Edward Broadbent inline void requestRoutesMemoryCollection(App& app)
890ac6a4445SGunnar Mills {
891ac6a4445SGunnar Mills     /**
892ac6a4445SGunnar Mills      * Functions triggers appropriate requests on DBus
893ac6a4445SGunnar Mills      */
8947e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Memory/")
895ed398213SEd Tanous         .privileges(redfish::privileges::getMemoryCollection)
8967e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
8977e860f15SJohn Edward Broadbent             [](const crow::Request&,
8987e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
8998d1b46d7Szhanghch05                 asyncResp->res.jsonValue["@odata.type"] =
9008d1b46d7Szhanghch05                     "#MemoryCollection.MemoryCollection";
9018d1b46d7Szhanghch05                 asyncResp->res.jsonValue["Name"] = "Memory Module Collection";
9028d1b46d7Szhanghch05                 asyncResp->res.jsonValue["@odata.id"] =
9038d1b46d7Szhanghch05                     "/redfish/v1/Systems/system/Memory";
904ac6a4445SGunnar Mills 
90505030b8eSGunnar Mills                 collection_util::getCollectionMembers(
90605030b8eSGunnar Mills                     asyncResp, "/redfish/v1/Systems/system/Memory",
90705030b8eSGunnar Mills                     {"xyz.openbmc_project.Inventory.Item.Dimm"});
9087e860f15SJohn Edward Broadbent             });
909ac6a4445SGunnar Mills }
910ac6a4445SGunnar Mills 
9117e860f15SJohn Edward Broadbent inline void requestRoutesMemory(App& app)
9127e860f15SJohn Edward Broadbent {
913ac6a4445SGunnar Mills     /**
914ac6a4445SGunnar Mills      * Functions triggers appropriate requests on DBus
915ac6a4445SGunnar Mills      */
9167e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Memory/<str>/")
917ed398213SEd Tanous         .privileges(redfish::privileges::getMemory)
9187e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
9197e860f15SJohn Edward Broadbent             [](const crow::Request&,
9207e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
9217e860f15SJohn Edward Broadbent                const std::string& dimmId) {
9227e860f15SJohn Edward Broadbent                 asyncResp->res.jsonValue["@odata.type"] =
9237e860f15SJohn Edward Broadbent                     "#Memory.v1_11_0.Memory";
9248d1b46d7Szhanghch05                 asyncResp->res.jsonValue["@odata.id"] =
925ac6a4445SGunnar Mills                     "/redfish/v1/Systems/system/Memory/" + dimmId;
926ac6a4445SGunnar Mills 
927ac6a4445SGunnar Mills                 getDimmData(asyncResp, dimmId);
9287e860f15SJohn Edward Broadbent             });
929ac6a4445SGunnar Mills }
930ac6a4445SGunnar Mills 
931ac6a4445SGunnar Mills } // namespace redfish
932