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 #pragma once 18 19 #include <phosphor-logging/elog-errors.hpp> 20 21 #include <array> 22 23 static constexpr const char* mdrType2File = "/var/lib/smbios/smbios2"; 24 static constexpr const char* smbiosPath = "/var/lib/smbios"; 25 26 static constexpr uint16_t mdrSMBIOSSize = 32 * 1024; 27 28 constexpr uint16_t smbiosAgentId = 0x0101; 29 constexpr int firstAgentIndex = 1; 30 31 constexpr uint8_t maxDirEntries = 4; 32 constexpr uint32_t mdr2SMSize = 0x00100000; 33 constexpr uint32_t mdr2SMBaseAddress = 0x9FF00000; 34 35 constexpr uint8_t mdrDirVersion = 1; 36 constexpr uint8_t mdrTypeII = 2; 37 38 constexpr uint8_t mdr2Version = 2; 39 constexpr uint8_t smbiosAgentVersion = 1; 40 constexpr uint8_t smbiosDirVersion = 1; 41 42 constexpr uint32_t pageMask = 0xf000; 43 constexpr int smbiosDirIndex = 0; 44 45 constexpr uint32_t smbiosTableVersion = 15; 46 constexpr uint32_t smbiosTableTimestamp = 0x45464748; 47 constexpr uint32_t smbiosSMMemoryOffset = 0; 48 constexpr uint32_t smbiosSMMemorySize = 1024 * 1024; 49 constexpr uint32_t smbiosTableStorageSize = 64 * 1024; 50 constexpr uint32_t defaultTimeout = 20000; 51 52 enum class MDR2SMBIOSStatusEnum 53 { 54 mdr2Init = 0, 55 mdr2Loaded = 1, 56 mdr2Updated = 2, 57 mdr2Updating = 3 58 }; 59 60 enum class MDR2DirLockEnum 61 { 62 mdr2DirUnlock = 0, 63 mdr2DirLock = 1 64 }; 65 66 enum class DirDataRequestEnum 67 { 68 dirDataNotRequested = 0x00, 69 dirDataRequested = 0x01 70 }; 71 72 enum class FlagStatus 73 { 74 flagIsInvalid = 0, 75 flagIsValid = 1, 76 flagIsLocked = 2 77 }; 78 79 typedef struct 80 { 81 uint8_t dataInfo[16]; 82 } DataIdStruct; 83 84 typedef struct 85 { 86 DataIdStruct id; 87 uint32_t size; 88 uint32_t dataSetSize; 89 uint8_t dataVersion; 90 uint32_t timestamp; 91 } Mdr2DirEntry; 92 93 typedef struct 94 { 95 Mdr2DirEntry common; 96 MDR2SMBIOSStatusEnum stage; 97 MDR2DirLockEnum lock; 98 uint16_t lockHandle; 99 uint32_t xferBuff; 100 uint32_t xferSize; 101 uint32_t maxDataSize; 102 uint8_t* dataStorage; 103 } Mdr2DirLocalStruct; 104 105 typedef struct 106 { 107 uint8_t agentVersion; 108 uint8_t dirVersion; 109 uint8_t dirEntries; 110 uint8_t status; // valid / locked / etc 111 uint8_t remoteDirVersion; 112 uint16_t sessionHandle; 113 Mdr2DirLocalStruct dir[maxDirEntries]; 114 } Mdr2DirStruct; 115 116 struct MDRSMBIOSHeader 117 { 118 uint8_t dirVer; 119 uint8_t mdrType; 120 uint32_t timestamp; 121 uint32_t dataSize; 122 } __attribute__((packed)); 123 124 typedef struct 125 { 126 uint8_t majorVersion; 127 uint8_t minorVersion; 128 } SMBIOSVersion; 129 130 struct EntryPointStructure21 131 { 132 uint32_t anchorString; 133 uint8_t epChecksum; 134 uint8_t epLength; 135 SMBIOSVersion smbiosVersion; 136 uint16_t maxStructSize; 137 uint8_t epRevision; 138 uint8_t formattedArea[5]; 139 uint8_t intermediateAnchorString[5]; 140 uint8_t intermediateChecksum; 141 uint16_t structTableLength; 142 uint32_t structTableAddress; 143 uint16_t noOfSmbiosStruct; 144 uint8_t smbiosBDCRevision; 145 } __attribute__((packed)); 146 147 struct EntryPointStructure30 148 { 149 uint8_t anchorString[5]; 150 uint8_t epChecksum; 151 uint8_t epLength; 152 SMBIOSVersion smbiosVersion; 153 uint8_t smbiosDocRev; 154 uint8_t epRevision; 155 uint8_t reserved; 156 uint32_t structTableMaxSize; 157 uint64_t structTableAddr; 158 } __attribute__((packed)); 159 160 static constexpr const char* cpuPath = 161 "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu"; 162 163 static constexpr const char* dimmPath = 164 "/xyz/openbmc_project/inventory/system/chassis/motherboard/dimm"; 165 166 static constexpr const char* pciePath = 167 "/xyz/openbmc_project/inventory/system/chassis/motherboard/pcieslot"; 168 169 static constexpr const char* systemPath = 170 "/xyz/openbmc_project/inventory/system/chassis/motherboard/bios"; 171 172 constexpr std::array<SMBIOSVersion, 3> supportedSMBIOSVersions{ 173 SMBIOSVersion{3, 2}, SMBIOSVersion{3, 3}, SMBIOSVersion{3, 5}}; 174 175 typedef enum 176 { 177 biosType = 0, 178 systemType = 1, 179 baseboardType = 2, 180 chassisType = 3, 181 processorsType = 4, 182 memoryControllerType = 5, 183 memoryModuleInformationType = 6, 184 cacheType = 7, 185 portConnectorType = 8, 186 systemSlots = 9, 187 onBoardDevicesType = 10, 188 oemStringsType = 11, 189 systemCconfigurationOptionsType = 12, 190 biosLanguageType = 13, 191 groupAssociatonsType = 14, 192 systemEventLogType = 15, 193 physicalMemoryArrayType = 16, 194 memoryDeviceType = 17, 195 } SmbiosType; 196 197 static constexpr uint8_t separateLen = 2; 198 199 static inline uint8_t* smbiosNextPtr(uint8_t* smbiosDataIn) 200 { 201 if (smbiosDataIn == nullptr) 202 { 203 return nullptr; 204 } 205 uint8_t* smbiosData = smbiosDataIn + *(smbiosDataIn + 1); 206 int len = 0; 207 while ((*smbiosData | *(smbiosData + 1)) != 0) 208 { 209 smbiosData++; 210 len++; 211 if (len >= mdrSMBIOSSize) // To avoid endless loop 212 { 213 return nullptr; 214 } 215 } 216 return smbiosData + separateLen; 217 } 218 219 // When first time run getSMBIOSTypePtr, need to send the RegionS[].regionData 220 // to smbiosDataIn 221 static inline uint8_t* getSMBIOSTypePtr(uint8_t* smbiosDataIn, uint8_t typeId, 222 size_t size = 0) 223 { 224 if (smbiosDataIn == nullptr) 225 { 226 return nullptr; 227 } 228 char* smbiosData = reinterpret_cast<char*>(smbiosDataIn); 229 while ((*smbiosData != '\0') || (*(smbiosData + 1) != '\0')) 230 { 231 uint32_t len = *(smbiosData + 1); 232 if (*smbiosData != typeId) 233 { 234 smbiosData += len; 235 while ((*smbiosData != '\0') || (*(smbiosData + 1) != '\0')) 236 { 237 smbiosData++; 238 len++; 239 if (len >= mdrSMBIOSSize) // To avoid endless loop 240 { 241 return nullptr; 242 } 243 } 244 smbiosData += separateLen; 245 continue; 246 } 247 if (len < size) 248 { 249 phosphor::logging::log<phosphor::logging::level::ERR>( 250 "Record size mismatch!"); 251 return nullptr; 252 } 253 return reinterpret_cast<uint8_t*>(smbiosData); 254 } 255 return nullptr; 256 } 257 258 static inline std::string positionToString(uint8_t positionNum, 259 uint8_t structLen, uint8_t* dataIn) 260 { 261 if (dataIn == nullptr || positionNum == 0) 262 { 263 return ""; 264 } 265 uint16_t limit = mdrSMBIOSSize; // set a limit to avoid endless loop 266 267 char* target = reinterpret_cast<char*>(dataIn + structLen); 268 if (target == nullptr) 269 { 270 return ""; 271 } 272 for (uint8_t index = 1; index < positionNum; index++) 273 { 274 for (; *target != '\0'; target++) 275 { 276 limit--; 277 // When target = dataIn + structLen + limit, 278 // following target++ will be nullptr 279 if (limit < 1 || target == nullptr) 280 { 281 return ""; 282 } 283 } 284 target++; 285 if (target == nullptr || *target == '\0') 286 { 287 return ""; // 0x00 0x00 means end of the entry. 288 } 289 } 290 291 std::string result = target; 292 return result; 293 } 294