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