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