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