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