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