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 mdrTypeII = 2; 36 37 constexpr uint8_t mdr2Version = 2; 38 constexpr uint8_t smbiosAgentVersion = 1; 39 40 constexpr uint32_t pageMask = 0xf000; 41 constexpr int smbiosDirIndex = 0; 42 43 constexpr uint32_t smbiosTableVersion = 15; 44 constexpr uint32_t smbiosTableTimestamp = 0x45464748; 45 constexpr uint32_t smbiosSMMemoryOffset = 0; 46 constexpr uint32_t smbiosSMMemorySize = 1024 * 1024; 47 constexpr uint32_t smbiosTableStorageSize = 64 * 1024; 48 constexpr uint32_t defaultTimeout = 20000; 49 50 enum class MDR2SMBIOSStatusEnum 51 { 52 mdr2Init = 0, 53 mdr2Loaded = 1, 54 mdr2Updated = 2, 55 mdr2Updating = 3 56 }; 57 58 enum class MDR2DirLockEnum 59 { 60 mdr2DirUnlock = 0, 61 mdr2DirLock = 1 62 }; 63 64 enum class DirDataRequestEnum 65 { 66 dirDataNotRequested = 0x00, 67 dirDataRequested = 0x01 68 }; 69 70 enum class FlagStatus 71 { 72 flagIsInvalid = 0, 73 flagIsValid = 1, 74 flagIsLocked = 2 75 }; 76 77 typedef struct 78 { 79 uint8_t dataInfo[16]; 80 } DataIdStruct; 81 82 typedef struct 83 { 84 DataIdStruct id; 85 uint32_t size; 86 uint32_t dataSetSize; 87 uint8_t dataVersion; 88 uint32_t timestamp; 89 } Mdr2DirEntry; 90 91 typedef struct 92 { 93 Mdr2DirEntry common; 94 MDR2SMBIOSStatusEnum stage; 95 MDR2DirLockEnum lock; 96 uint16_t lockHandle; 97 uint32_t xferBuff; 98 uint32_t xferSize; 99 uint32_t maxDataSize; 100 uint8_t* dataStorage; 101 } Mdr2DirLocalStruct; 102 103 typedef struct 104 { 105 uint8_t agentVersion; 106 uint8_t dirVersion; 107 uint8_t dirEntries; 108 uint8_t status; // valid / locked / etc 109 uint8_t remoteDirVersion; 110 uint16_t sessionHandle; 111 Mdr2DirLocalStruct dir[maxDirEntries]; 112 } Mdr2DirStruct; 113 114 struct MDRSMBIOSHeader 115 { 116 uint8_t dirVer; 117 uint8_t mdrType; 118 uint32_t timestamp; 119 uint32_t dataSize; 120 } __attribute__((packed)); 121 122 typedef struct 123 { 124 uint8_t majorVersion; 125 uint8_t minorVersion; 126 } SMBIOSVersion; 127 128 struct EntryPointStructure21 129 { 130 uint32_t anchorString; 131 uint8_t epChecksum; 132 uint8_t epLength; 133 SMBIOSVersion smbiosVersion; 134 uint16_t maxStructSize; 135 uint8_t epRevision; 136 uint8_t formattedArea[5]; 137 uint8_t intermediateAnchorString[5]; 138 uint8_t intermediateChecksum; 139 uint16_t structTableLength; 140 uint32_t structTableAddress; 141 uint16_t noOfSmbiosStruct; 142 uint8_t smbiosBDCRevision; 143 } __attribute__((packed)); 144 145 struct EntryPointStructure30 146 { 147 uint8_t anchorString[5]; 148 uint8_t epChecksum; 149 uint8_t epLength; 150 SMBIOSVersion smbiosVersion; 151 uint8_t smbiosDocRev; 152 uint8_t epRevision; 153 uint8_t reserved; 154 uint32_t structTableMaxSize; 155 uint64_t structTableAddr; 156 } __attribute__((packed)); 157 158 static constexpr const char* cpuPath = 159 "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu"; 160 161 static constexpr const char* dimmPath = 162 "/xyz/openbmc_project/inventory/system/chassis/motherboard/dimm"; 163 164 static constexpr const char* pciePath = 165 "/xyz/openbmc_project/inventory/system/chassis/motherboard/pcieslot"; 166 167 static constexpr const char* systemPath = 168 "/xyz/openbmc_project/inventory/system/chassis/motherboard/bios"; 169 170 constexpr std::array<SMBIOSVersion, 3> supportedSMBIOSVersions{ 171 SMBIOSVersion{3, 2}, SMBIOSVersion{3, 3}, SMBIOSVersion{3, 5}}; 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 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 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 233 smbiosData += len; 234 while ((*smbiosData != '\0') || (*(smbiosData + 1) != '\0')) 235 { 236 smbiosData++; 237 len++; 238 if (len >= mdrSMBIOSSize) // To avoid endless loop 239 { 240 return nullptr; 241 } 242 } 243 smbiosData += separateLen; 244 continue; 245 } 246 if (len < size) 247 { 248 phosphor::logging::log<phosphor::logging::level::ERR>( 249 "Record size mismatch!"); 250 return nullptr; 251 } 252 return reinterpret_cast<uint8_t*>(smbiosData); 253 } 254 return nullptr; 255 } 256 257 static inline std::string positionToString(uint8_t positionNum, 258 uint8_t structLen, uint8_t* dataIn) 259 { 260 if (dataIn == nullptr || positionNum == 0) 261 { 262 return ""; 263 } 264 uint16_t limit = mdrSMBIOSSize; // set a limit to avoid endless loop 265 266 char* target = reinterpret_cast<char*>(dataIn + structLen); 267 if (target == nullptr) 268 { 269 return ""; 270 } 271 for (uint8_t index = 1; index < positionNum; index++) 272 { 273 for (; *target != '\0'; target++) 274 { 275 limit--; 276 // When target = dataIn + structLen + limit, 277 // following target++ will be nullptr 278 if (limit < 1 || target == nullptr) 279 { 280 return ""; 281 } 282 } 283 target++; 284 if (target == nullptr || *target == '\0') 285 { 286 return ""; // 0x00 0x00 means end of the entry. 287 } 288 } 289 290 std::string result = target; 291 return result; 292 } 293