blob: c2f1b4bc9fe2b9e411a6f513f70654ec7a9ba2f0 [file] [log] [blame]
Cheng C Yang3e3269a2019-12-02 15:11:30 +08001/*
Zhikui Ren18a5ab92020-09-01 21:35:20 -07002// Copyright (c) 2018 Intel Corporation
Cheng C Yang3e3269a2019-12-02 15:11:30 +08003//
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
Zhikui Ren18a5ab92020-09-01 21:35:20 -070019#include <phosphor-logging/elog-errors.hpp>
20
Cheng C Yang3e3269a2019-12-02 15:11:30 +080021#include <array>
Josh Lehan027277a2023-09-11 05:28:19 -070022#include <string>
Cheng C Yang3e3269a2019-12-02 15:11:30 +080023
Josh Lehan027277a2023-09-11 05:28:19 -070024static constexpr const char* mdrDefaultFile = "/var/lib/smbios/smbios2";
Zhikui Ren18a5ab92020-09-01 21:35:20 -070025
Cheng C Yangeecaf822019-12-19 00:34:23 +080026static constexpr uint16_t mdrSMBIOSSize = 32 * 1024;
Cheng C Yang3e3269a2019-12-02 15:11:30 +080027
Zhikui Ren18a5ab92020-09-01 21:35:20 -070028constexpr uint16_t smbiosAgentId = 0x0101;
29constexpr int firstAgentIndex = 1;
Cheng C Yang2ca7a0f2019-12-19 10:46:42 +080030
Zhikui Ren18a5ab92020-09-01 21:35:20 -070031constexpr uint8_t maxDirEntries = 4;
32constexpr uint32_t mdr2SMSize = 0x00100000;
33constexpr uint32_t mdr2SMBaseAddress = 0x9FF00000;
Cheng C Yang2ca7a0f2019-12-19 10:46:42 +080034
Josh Lehanf079e832023-09-19 15:52:52 -070035constexpr uint8_t mdrDirVersion = 1;
Zhikui Ren18a5ab92020-09-01 21:35:20 -070036constexpr uint8_t mdrTypeII = 2;
37
38constexpr uint8_t mdr2Version = 2;
39constexpr uint8_t smbiosAgentVersion = 1;
Josh Lehanf079e832023-09-19 15:52:52 -070040constexpr uint8_t smbiosDirVersion = 1;
Zhikui Ren18a5ab92020-09-01 21:35:20 -070041
42constexpr uint32_t pageMask = 0xf000;
43constexpr int smbiosDirIndex = 0;
44
45constexpr uint32_t smbiosTableVersion = 15;
46constexpr uint32_t smbiosTableTimestamp = 0x45464748;
47constexpr uint32_t smbiosSMMemoryOffset = 0;
48constexpr uint32_t smbiosSMMemorySize = 1024 * 1024;
49constexpr uint32_t smbiosTableStorageSize = 64 * 1024;
Yaswanth Reddy Md8dd1202023-08-08 11:20:12 +000050constexpr uint32_t defaultTimeout = 2'000'000; // 2-seconds.
Zhikui Ren18a5ab92020-09-01 21:35:20 -070051
52enum class MDR2SMBIOSStatusEnum
53{
54 mdr2Init = 0,
55 mdr2Loaded = 1,
56 mdr2Updated = 2,
57 mdr2Updating = 3
58};
59
60enum class MDR2DirLockEnum
61{
62 mdr2DirUnlock = 0,
63 mdr2DirLock = 1
64};
Cheng C Yang2ca7a0f2019-12-19 10:46:42 +080065
Cheng C Yang3e3269a2019-12-02 15:11:30 +080066enum class DirDataRequestEnum
67{
68 dirDataNotRequested = 0x00,
69 dirDataRequested = 0x01
70};
71
72enum class FlagStatus
73{
74 flagIsInvalid = 0,
75 flagIsValid = 1,
76 flagIsLocked = 2
77};
78
Zhikui Ren18a5ab92020-09-01 21:35:20 -070079typedef struct
80{
81 uint8_t dataInfo[16];
82} DataIdStruct;
83
84typedef struct
85{
86 DataIdStruct id;
87 uint32_t size;
88 uint32_t dataSetSize;
89 uint8_t dataVersion;
90 uint32_t timestamp;
91} Mdr2DirEntry;
92
93typedef 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
105typedef 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
116struct MDRSMBIOSHeader
117{
118 uint8_t dirVer;
119 uint8_t mdrType;
120 uint32_t timestamp;
121 uint32_t dataSize;
122} __attribute__((packed));
123
Arun P. Mohanan0435a482022-02-01 21:45:55 +0530124typedef struct
125{
126 uint8_t majorVersion;
127 uint8_t minorVersion;
128} SMBIOSVersion;
129
Brandon Kime4ea3772022-02-23 20:21:10 -0800130struct EntryPointStructure21
Arun P. Mohanan0435a482022-02-01 21:45:55 +0530131{
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
Brandon Kime4ea3772022-02-23 20:21:10 -0800147struct 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
Prithvi Pai6f9e7a72025-03-14 13:05:02 +0530160struct StructureHeader
161{
162 uint8_t type;
163 uint8_t length;
164 uint16_t handle;
165} __attribute__((packed));
166
Josh Lehan027277a2023-09-11 05:28:19 -0700167static constexpr const char* cpuSuffix = "/chassis/motherboard/cpu";
Zhikui Ren18a5ab92020-09-01 21:35:20 -0700168
Josh Lehan027277a2023-09-11 05:28:19 -0700169static constexpr const char* dimmSuffix = "/chassis/motherboard/dimm";
Zhikui Ren18a5ab92020-09-01 21:35:20 -0700170
Josh Lehan027277a2023-09-11 05:28:19 -0700171static constexpr const char* pcieSuffix = "/chassis/motherboard/pcieslot";
Jie Yang08e4a6d2021-08-23 13:07:41 -0700172
Josh Lehan027277a2023-09-11 05:28:19 -0700173static constexpr const char* systemSuffix = "/chassis/motherboard/bios";
Zhikui Ren18a5ab92020-09-01 21:35:20 -0700174
Prithvi Pai5af42bb2025-02-11 17:59:07 +0530175static constexpr const char* tpmSuffix = "/chassis/motherboard/tpm";
176
Prithvi Pai6f9e7a72025-03-14 13:05:02 +0530177static constexpr const char* firmwarePath = "/xyz/openbmc_project/software";
178
Jayaprakash Mutyala669e4c32025-01-20 06:09:05 +0000179constexpr std::array<SMBIOSVersion, 8> supportedSMBIOSVersions{
Manojkiran Eda7a2cf162024-11-12 11:49:26 +0530180 SMBIOSVersion{3, 0}, SMBIOSVersion{3, 2}, SMBIOSVersion{3, 3},
Quang Nguyen80498222024-12-02 14:39:44 +0700181 SMBIOSVersion{3, 4}, SMBIOSVersion{3, 5}, SMBIOSVersion{3, 6},
Jayaprakash Mutyala669e4c32025-01-20 06:09:05 +0000182 SMBIOSVersion{3, 7}, SMBIOSVersion{3, 8}};
Arun P. Mohanan0435a482022-02-01 21:45:55 +0530183
Cheng C Yang3e3269a2019-12-02 15:11:30 +0800184typedef enum
185{
186 biosType = 0,
187 systemType = 1,
188 baseboardType = 2,
189 chassisType = 3,
190 processorsType = 4,
191 memoryControllerType = 5,
192 memoryModuleInformationType = 6,
193 cacheType = 7,
194 portConnectorType = 8,
195 systemSlots = 9,
196 onBoardDevicesType = 10,
197 oemStringsType = 11,
198 systemCconfigurationOptionsType = 12,
199 biosLanguageType = 13,
200 groupAssociatonsType = 14,
201 systemEventLogType = 15,
202 physicalMemoryArrayType = 16,
203 memoryDeviceType = 17,
Prithvi Pai6f9e7a72025-03-14 13:05:02 +0530204 systemPowerSupply = 39,
205 onboardDevicesExtended = 41,
Prithvi Pai5af42bb2025-02-11 17:59:07 +0530206 tpmDeviceType = 43,
Prithvi Pai6f9e7a72025-03-14 13:05:02 +0530207 firmwareInventoryInformationType = 45,
Cheng C Yang3e3269a2019-12-02 15:11:30 +0800208} SmbiosType;
Cheng C Yang43c6a1d2019-12-19 00:48:34 +0800209
210static constexpr uint8_t separateLen = 2;
211
212static inline uint8_t* smbiosNextPtr(uint8_t* smbiosDataIn)
213{
214 if (smbiosDataIn == nullptr)
215 {
216 return nullptr;
217 }
218 uint8_t* smbiosData = smbiosDataIn + *(smbiosDataIn + 1);
219 int len = 0;
220 while ((*smbiosData | *(smbiosData + 1)) != 0)
221 {
222 smbiosData++;
223 len++;
224 if (len >= mdrSMBIOSSize) // To avoid endless loop
225 {
226 return nullptr;
227 }
228 }
229 return smbiosData + separateLen;
230}
231
232// When first time run getSMBIOSTypePtr, need to send the RegionS[].regionData
233// to smbiosDataIn
Zhikui Ren18a5ab92020-09-01 21:35:20 -0700234static inline uint8_t* getSMBIOSTypePtr(uint8_t* smbiosDataIn, uint8_t typeId,
235 size_t size = 0)
Cheng C Yang43c6a1d2019-12-19 00:48:34 +0800236{
237 if (smbiosDataIn == nullptr)
238 {
239 return nullptr;
240 }
241 char* smbiosData = reinterpret_cast<char*>(smbiosDataIn);
242 while ((*smbiosData != '\0') || (*(smbiosData + 1) != '\0'))
243 {
Zhikui Ren18a5ab92020-09-01 21:35:20 -0700244 uint32_t len = *(smbiosData + 1);
Cheng C Yang43c6a1d2019-12-19 00:48:34 +0800245 if (*smbiosData != typeId)
246 {
Cheng C Yang43c6a1d2019-12-19 00:48:34 +0800247 smbiosData += len;
248 while ((*smbiosData != '\0') || (*(smbiosData + 1) != '\0'))
249 {
250 smbiosData++;
251 len++;
252 if (len >= mdrSMBIOSSize) // To avoid endless loop
253 {
254 return nullptr;
255 }
256 }
257 smbiosData += separateLen;
258 continue;
259 }
Zhikui Ren18a5ab92020-09-01 21:35:20 -0700260 if (len < size)
261 {
262 phosphor::logging::log<phosphor::logging::level::ERR>(
263 "Record size mismatch!");
264 return nullptr;
265 }
Cheng C Yang43c6a1d2019-12-19 00:48:34 +0800266 return reinterpret_cast<uint8_t*>(smbiosData);
267 }
268 return nullptr;
269}
270
Prithvi Pai6f9e7a72025-03-14 13:05:02 +0530271static inline uint8_t* smbiosSkipEntryPoint(uint8_t* smbiosDataIn)
272{
273 const std::string anchorString30 = "_SM3_";
274 if (smbiosDataIn == nullptr)
275 {
276 return nullptr;
277 }
278
279 // Jump to starting address of the SMBIOS Structure Table from Entry Point
280 auto anchor = reinterpret_cast<const char*>(smbiosDataIn);
281 if (std::string_view(anchor, anchorString30.length())
282 .compare(anchorString30) == 0)
283 {
284 auto epStructure =
285 reinterpret_cast<const EntryPointStructure30*>(smbiosDataIn);
286 if (epStructure->structTableAddr < mdrSMBIOSSize)
287 {
288 smbiosDataIn += epStructure->structTableAddr;
289 }
290 }
291
292 return smbiosDataIn;
293}
294
295static inline uint8_t* smbiosHandlePtr(uint8_t* smbiosDataIn, uint16_t handle)
296{
297 auto ptr = smbiosSkipEntryPoint(smbiosDataIn);
298 struct StructureHeader* header;
299 while (ptr != nullptr)
300 {
301 header = reinterpret_cast<struct StructureHeader*>(ptr);
302 if (header->length < sizeof(StructureHeader))
303 {
304 return nullptr;
305 }
306
307 if (header->handle == handle)
308 {
309 return ptr;
310 }
311 ptr = smbiosNextPtr(ptr);
312 }
313 return nullptr;
314}
315
Cheng C Yang43c6a1d2019-12-19 00:48:34 +0800316static inline std::string positionToString(uint8_t positionNum,
317 uint8_t structLen, uint8_t* dataIn)
318{
Gokul Sanker V G473d8902022-02-18 01:13:53 +0530319 if (dataIn == nullptr || positionNum == 0)
Cheng C Yang43c6a1d2019-12-19 00:48:34 +0800320 {
321 return "";
322 }
323 uint16_t limit = mdrSMBIOSSize; // set a limit to avoid endless loop
324
325 char* target = reinterpret_cast<char*>(dataIn + structLen);
Kuiying Wang59bb9d92020-10-27 15:30:46 +0800326 if (target == nullptr)
327 {
328 return "";
329 }
Cheng C Yang43c6a1d2019-12-19 00:48:34 +0800330 for (uint8_t index = 1; index < positionNum; index++)
331 {
332 for (; *target != '\0'; target++)
333 {
334 limit--;
Kuiying Wang59bb9d92020-10-27 15:30:46 +0800335 // When target = dataIn + structLen + limit,
336 // following target++ will be nullptr
337 if (limit < 1 || target == nullptr)
Cheng C Yang43c6a1d2019-12-19 00:48:34 +0800338 {
339 return "";
340 }
341 }
342 target++;
Kuiying Wang59bb9d92020-10-27 15:30:46 +0800343 if (target == nullptr || *target == '\0')
Cheng C Yang43c6a1d2019-12-19 00:48:34 +0800344 {
345 return ""; // 0x00 0x00 means end of the entry.
346 }
347 }
348
349 std::string result = target;
350 return result;
351}