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 static constexpr const char* cpuPath = 123 "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu"; 124 125 static constexpr const char* dimmPath = 126 "/xyz/openbmc_project/inventory/system/chassis/motherboard/dimm"; 127 128 static constexpr const char* pciePath = 129 "/xyz/openbmc_project/inventory/system/chassis/motherboard/pcieslot"; 130 131 static constexpr const char* systemPath = 132 "/xyz/openbmc_project/inventory/system/chassis/motherboard/bios"; 133 134 typedef enum 135 { 136 biosType = 0, 137 systemType = 1, 138 baseboardType = 2, 139 chassisType = 3, 140 processorsType = 4, 141 memoryControllerType = 5, 142 memoryModuleInformationType = 6, 143 cacheType = 7, 144 portConnectorType = 8, 145 systemSlots = 9, 146 onBoardDevicesType = 10, 147 oemStringsType = 11, 148 systemCconfigurationOptionsType = 12, 149 biosLanguageType = 13, 150 groupAssociatonsType = 14, 151 systemEventLogType = 15, 152 physicalMemoryArrayType = 16, 153 memoryDeviceType = 17, 154 } SmbiosType; 155 156 static constexpr uint8_t separateLen = 2; 157 158 static inline uint8_t* smbiosNextPtr(uint8_t* smbiosDataIn) 159 { 160 if (smbiosDataIn == nullptr) 161 { 162 return nullptr; 163 } 164 uint8_t* smbiosData = smbiosDataIn + *(smbiosDataIn + 1); 165 int len = 0; 166 while ((*smbiosData | *(smbiosData + 1)) != 0) 167 { 168 smbiosData++; 169 len++; 170 if (len >= mdrSMBIOSSize) // To avoid endless loop 171 { 172 return nullptr; 173 } 174 } 175 return smbiosData + separateLen; 176 } 177 178 // When first time run getSMBIOSTypePtr, need to send the RegionS[].regionData 179 // to smbiosDataIn 180 static inline uint8_t* getSMBIOSTypePtr(uint8_t* smbiosDataIn, uint8_t typeId, 181 size_t size = 0) 182 { 183 if (smbiosDataIn == nullptr) 184 { 185 return nullptr; 186 } 187 char* smbiosData = reinterpret_cast<char*>(smbiosDataIn); 188 while ((*smbiosData != '\0') || (*(smbiosData + 1) != '\0')) 189 { 190 uint32_t len = *(smbiosData + 1); 191 if (*smbiosData != typeId) 192 { 193 194 smbiosData += len; 195 while ((*smbiosData != '\0') || (*(smbiosData + 1) != '\0')) 196 { 197 smbiosData++; 198 len++; 199 if (len >= mdrSMBIOSSize) // To avoid endless loop 200 { 201 return nullptr; 202 } 203 } 204 smbiosData += separateLen; 205 continue; 206 } 207 if (len < size) 208 { 209 phosphor::logging::log<phosphor::logging::level::ERR>( 210 "Record size mismatch!"); 211 return nullptr; 212 } 213 return reinterpret_cast<uint8_t*>(smbiosData); 214 } 215 return nullptr; 216 } 217 218 static inline std::string positionToString(uint8_t positionNum, 219 uint8_t structLen, uint8_t* dataIn) 220 { 221 if (dataIn == nullptr) 222 { 223 return ""; 224 } 225 uint16_t limit = mdrSMBIOSSize; // set a limit to avoid endless loop 226 227 char* target = reinterpret_cast<char*>(dataIn + structLen); 228 if (target == nullptr) 229 { 230 return ""; 231 } 232 for (uint8_t index = 1; index < positionNum; index++) 233 { 234 for (; *target != '\0'; target++) 235 { 236 limit--; 237 // When target = dataIn + structLen + limit, 238 // following target++ will be nullptr 239 if (limit < 1 || target == nullptr) 240 { 241 return ""; 242 } 243 } 244 target++; 245 if (target == nullptr || *target == '\0') 246 { 247 return ""; // 0x00 0x00 means end of the entry. 248 } 249 } 250 251 std::string result = target; 252 return result; 253 } 254