1 /* 2 // Copyright (c) 2018 Intel Corporation 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 */ 16 17 #include "dimm.hpp" 18 19 #include "mdrv2.hpp" 20 21 namespace phosphor 22 { 23 namespace smbios 24 { 25 26 using DeviceType = 27 sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm::DeviceType; 28 29 static constexpr uint16_t maxOldDimmSize = 0x7fff; 30 void Dimm::memoryInfoUpdate(void) 31 { 32 uint8_t* dataIn = storage; 33 34 dataIn = getSMBIOSTypePtr(dataIn, memoryDeviceType); 35 36 if (dataIn == nullptr) 37 { 38 return; 39 } 40 for (uint8_t index = 0; index < dimmNum; index++) 41 { 42 dataIn = smbiosNextPtr(dataIn); 43 if (dataIn == nullptr) 44 { 45 return; 46 } 47 dataIn = getSMBIOSTypePtr(dataIn, memoryDeviceType); 48 if (dataIn == nullptr) 49 { 50 return; 51 } 52 } 53 54 auto memoryInfo = reinterpret_cast<struct MemoryInfo*>(dataIn); 55 56 memoryDataWidth(memoryInfo->dataWidth); 57 58 if (memoryInfo->size == maxOldDimmSize) 59 { 60 dimmSizeExt(memoryInfo->extendedSize); 61 } 62 else 63 { 64 dimmSize(memoryInfo->size); 65 } 66 67 dimmDeviceLocator(memoryInfo->deviceLocator, memoryInfo->length, dataIn); 68 dimmType(memoryInfo->memoryType); 69 dimmTypeDetail(memoryInfo->typeDetail); 70 maxMemorySpeedInMhz(memoryInfo->speed); 71 dimmManufacturer(memoryInfo->manufacturer, memoryInfo->length, dataIn); 72 dimmSerialNum(memoryInfo->serialNum, memoryInfo->length, dataIn); 73 dimmPartNum(memoryInfo->partNum, memoryInfo->length, dataIn); 74 memoryAttributes(memoryInfo->attributes); 75 memoryConfiguredSpeedInMhz(memoryInfo->confClockSpeed); 76 77 if (!motherboardPath.empty()) 78 { 79 std::vector<std::tuple<std::string, std::string, std::string>> assocs; 80 assocs.emplace_back("chassis", "memories", motherboardPath); 81 association::associations(assocs); 82 } 83 84 return; 85 } 86 87 uint16_t Dimm::memoryDataWidth(uint16_t value) 88 { 89 return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm:: 90 memoryDataWidth(value); 91 } 92 93 static constexpr uint16_t baseNewVersionDimmSize = 0x8000; 94 static constexpr uint16_t dimmSizeUnit = 1024; 95 void Dimm::dimmSize(const uint16_t size) 96 { 97 size_t result = size & maxOldDimmSize; 98 if (0 == (size & baseNewVersionDimmSize)) 99 { 100 result = result * dimmSizeUnit; 101 } 102 memorySizeInKB(result); 103 } 104 105 void Dimm::dimmSizeExt(size_t size) 106 { 107 size = size * dimmSizeUnit; 108 memorySizeInKB(size); 109 } 110 111 size_t Dimm::memorySizeInKB(size_t value) 112 { 113 return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm:: 114 memorySizeInKB(value); 115 } 116 117 void Dimm::dimmDeviceLocator(const uint8_t positionNum, const uint8_t structLen, 118 uint8_t* dataIn) 119 { 120 std::string result = positionToString(positionNum, structLen, dataIn); 121 122 memoryDeviceLocator(result); 123 124 locationCode(result); 125 } 126 127 std::string Dimm::memoryDeviceLocator(std::string value) 128 { 129 return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm:: 130 memoryDeviceLocator(value); 131 } 132 133 void Dimm::dimmType(const uint8_t type) 134 { 135 std::map<uint8_t, DeviceType>::const_iterator it = dimmTypeTable.find(type); 136 if (it == dimmTypeTable.end()) 137 { 138 memoryType(DeviceType::Unknown); 139 } 140 else 141 { 142 memoryType(it->second); 143 } 144 } 145 146 DeviceType Dimm::memoryType(DeviceType value) 147 { 148 return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm:: 149 memoryType(value); 150 } 151 152 void Dimm::dimmTypeDetail(uint16_t detail) 153 { 154 std::string result; 155 for (uint8_t index = 0; index < (8 * sizeof(detail)); index++) 156 { 157 if (detail & 0x01) 158 { 159 result += detailTable[index]; 160 } 161 detail >>= 1; 162 } 163 memoryTypeDetail(result); 164 } 165 166 std::string Dimm::memoryTypeDetail(std::string value) 167 { 168 return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm:: 169 memoryTypeDetail(value); 170 } 171 172 uint16_t Dimm::maxMemorySpeedInMhz(uint16_t value) 173 { 174 return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm:: 175 maxMemorySpeedInMhz(value); 176 } 177 178 void Dimm::dimmManufacturer(const uint8_t positionNum, const uint8_t structLen, 179 uint8_t* dataIn) 180 { 181 std::string result = positionToString(positionNum, structLen, dataIn); 182 183 bool val = true; 184 if (result == "NO DIMM") 185 { 186 val = false; 187 188 // No dimm presence so making manufacturer value as "" (instead of 189 // NO DIMM - as there won't be any manufacturer for DIMM which is not 190 // present). 191 result = ""; 192 } 193 manufacturer(result); 194 present(val); 195 functional(val); 196 } 197 198 std::string Dimm::manufacturer(std::string value) 199 { 200 return sdbusplus::xyz::openbmc_project::Inventory::Decorator::server:: 201 Asset::manufacturer(value); 202 } 203 204 bool Dimm::present(bool value) 205 { 206 return sdbusplus::xyz::openbmc_project::Inventory::server::Item::present( 207 value); 208 } 209 210 void Dimm::dimmSerialNum(const uint8_t positionNum, const uint8_t structLen, 211 uint8_t* dataIn) 212 { 213 std::string result = positionToString(positionNum, structLen, dataIn); 214 215 serialNumber(result); 216 } 217 218 std::string Dimm::serialNumber(std::string value) 219 { 220 return sdbusplus::xyz::openbmc_project::Inventory::Decorator::server:: 221 Asset::serialNumber(value); 222 } 223 224 void Dimm::dimmPartNum(const uint8_t positionNum, const uint8_t structLen, 225 uint8_t* dataIn) 226 { 227 std::string result = positionToString(positionNum, structLen, dataIn); 228 229 partNumber(result); 230 } 231 232 std::string Dimm::partNumber(std::string value) 233 { 234 return sdbusplus::xyz::openbmc_project::Inventory::Decorator::server:: 235 Asset::partNumber(value); 236 } 237 238 std::string Dimm::locationCode(std::string value) 239 { 240 return sdbusplus::xyz::openbmc_project::Inventory::Decorator::server:: 241 LocationCode::locationCode(value); 242 } 243 244 uint8_t Dimm::memoryAttributes(uint8_t value) 245 { 246 return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm:: 247 memoryAttributes(value); 248 } 249 250 uint16_t Dimm::memoryConfiguredSpeedInMhz(uint16_t value) 251 { 252 return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm:: 253 memoryConfiguredSpeedInMhz(value); 254 } 255 256 bool Dimm::functional(bool value) 257 { 258 return sdbusplus::xyz::openbmc_project::State::Decorator::server:: 259 OperationalStatus::functional(value); 260 } 261 262 } // namespace smbios 263 } // namespace phosphor 264