xref: /openbmc/smbios-mdr/include/smbios_mdrv2.hpp (revision 669e4c3c7868a58f81b4e3523e2f8e1d7710f159)
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  constexpr std::array<SMBIOSVersion, 8> supportedSMBIOSVersions{
169      SMBIOSVersion{3, 0}, SMBIOSVersion{3, 2}, SMBIOSVersion{3, 3},
170      SMBIOSVersion{3, 4}, SMBIOSVersion{3, 5}, SMBIOSVersion{3, 6},
171      SMBIOSVersion{3, 7}, SMBIOSVersion{3, 8}};
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  
smbiosNextPtr(uint8_t * smbiosDataIn)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
getSMBIOSTypePtr(uint8_t * smbiosDataIn,uint8_t typeId,size_t size=0)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              smbiosData += len;
233              while ((*smbiosData != '\0') || (*(smbiosData + 1) != '\0'))
234              {
235                  smbiosData++;
236                  len++;
237                  if (len >= mdrSMBIOSSize) // To avoid endless loop
238                  {
239                      return nullptr;
240                  }
241              }
242              smbiosData += separateLen;
243              continue;
244          }
245          if (len < size)
246          {
247              phosphor::logging::log<phosphor::logging::level::ERR>(
248                  "Record size mismatch!");
249              return nullptr;
250          }
251          return reinterpret_cast<uint8_t*>(smbiosData);
252      }
253      return nullptr;
254  }
255  
positionToString(uint8_t positionNum,uint8_t structLen,uint8_t * dataIn)256  static inline std::string positionToString(uint8_t positionNum,
257                                             uint8_t structLen, uint8_t* dataIn)
258  {
259      if (dataIn == nullptr || positionNum == 0)
260      {
261          return "";
262      }
263      uint16_t limit = mdrSMBIOSSize; // set a limit to avoid endless loop
264  
265      char* target = reinterpret_cast<char*>(dataIn + structLen);
266      if (target == nullptr)
267      {
268          return "";
269      }
270      for (uint8_t index = 1; index < positionNum; index++)
271      {
272          for (; *target != '\0'; target++)
273          {
274              limit--;
275              // When target = dataIn + structLen + limit,
276              // following target++ will be nullptr
277              if (limit < 1 || target == nullptr)
278              {
279                  return "";
280              }
281          }
282          target++;
283          if (target == nullptr || *target == '\0')
284          {
285              return ""; // 0x00 0x00 means end of the entry.
286          }
287      }
288  
289      std::string result = target;
290      return result;
291  }
292