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 #include <string> 23 24 static constexpr const char* mdrDefaultFile = "/var/lib/smbios/smbios2"; 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 = 2'000'000; // 2-seconds. 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* cpuSuffix = "/chassis/motherboard/cpu"; 161 162 static constexpr const char* dimmSuffix = "/chassis/motherboard/dimm"; 163 164 static constexpr const char* pcieSuffix = "/chassis/motherboard/pcieslot"; 165 166 static constexpr const char* systemSuffix = "/chassis/motherboard/bios"; 167 168 constexpr std::array<SMBIOSVersion, 4> supportedSMBIOSVersions{ 169 SMBIOSVersion{3, 2}, SMBIOSVersion{3, 3}, SMBIOSVersion{3, 4}, 170 SMBIOSVersion{3, 5}}; 171 172 typedef enum 173 { 174 biosType = 0, 175 systemType = 1, 176 baseboardType = 2, 177 chassisType = 3, 178 processorsType = 4, 179 memoryControllerType = 5, 180 memoryModuleInformationType = 6, 181 cacheType = 7, 182 portConnectorType = 8, 183 systemSlots = 9, 184 onBoardDevicesType = 10, 185 oemStringsType = 11, 186 systemCconfigurationOptionsType = 12, 187 biosLanguageType = 13, 188 groupAssociatonsType = 14, 189 systemEventLogType = 15, 190 physicalMemoryArrayType = 16, 191 memoryDeviceType = 17, 192 } SmbiosType; 193 194 static constexpr uint8_t separateLen = 2; 195 196 static inline uint8_t* smbiosNextPtr(uint8_t* smbiosDataIn) 197 { 198 if (smbiosDataIn == nullptr) 199 { 200 return nullptr; 201 } 202 uint8_t* smbiosData = smbiosDataIn + *(smbiosDataIn + 1); 203 int len = 0; 204 while ((*smbiosData | *(smbiosData + 1)) != 0) 205 { 206 smbiosData++; 207 len++; 208 if (len >= mdrSMBIOSSize) // To avoid endless loop 209 { 210 return nullptr; 211 } 212 } 213 return smbiosData + separateLen; 214 } 215 216 // When first time run getSMBIOSTypePtr, need to send the RegionS[].regionData 217 // to smbiosDataIn 218 static inline uint8_t* getSMBIOSTypePtr(uint8_t* smbiosDataIn, uint8_t typeId, 219 size_t size = 0) 220 { 221 if (smbiosDataIn == nullptr) 222 { 223 return nullptr; 224 } 225 char* smbiosData = reinterpret_cast<char*>(smbiosDataIn); 226 while ((*smbiosData != '\0') || (*(smbiosData + 1) != '\0')) 227 { 228 uint32_t len = *(smbiosData + 1); 229 if (*smbiosData != typeId) 230 { 231 smbiosData += len; 232 while ((*smbiosData != '\0') || (*(smbiosData + 1) != '\0')) 233 { 234 smbiosData++; 235 len++; 236 if (len >= mdrSMBIOSSize) // To avoid endless loop 237 { 238 return nullptr; 239 } 240 } 241 smbiosData += separateLen; 242 continue; 243 } 244 if (len < size) 245 { 246 phosphor::logging::log<phosphor::logging::level::ERR>( 247 "Record size mismatch!"); 248 return nullptr; 249 } 250 return reinterpret_cast<uint8_t*>(smbiosData); 251 } 252 return nullptr; 253 } 254 255 static inline std::string positionToString(uint8_t positionNum, 256 uint8_t structLen, uint8_t* dataIn) 257 { 258 if (dataIn == nullptr || positionNum == 0) 259 { 260 return ""; 261 } 262 uint16_t limit = mdrSMBIOSSize; // set a limit to avoid endless loop 263 264 char* target = reinterpret_cast<char*>(dataIn + structLen); 265 if (target == nullptr) 266 { 267 return ""; 268 } 269 for (uint8_t index = 1; index < positionNum; index++) 270 { 271 for (; *target != '\0'; target++) 272 { 273 limit--; 274 // When target = dataIn + structLen + limit, 275 // following target++ will be nullptr 276 if (limit < 1 || target == nullptr) 277 { 278 return ""; 279 } 280 } 281 target++; 282 if (target == nullptr || *target == '\0') 283 { 284 return ""; // 0x00 0x00 means end of the entry. 285 } 286 } 287 288 std::string result = target; 289 return result; 290 } 291