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 #include <ipmid/api.h>
19 #include <sys/mman.h>
20 
21 #include <oemcommands.hpp>
22 #include <sdbusplus/timer.hpp>
23 #include <types.hpp>
24 
25 static constexpr const char* mdrType2File = "/var/lib/smbios/smbios2";
26 static constexpr const char* smbiosPath = "/var/lib/smbios";
27 static constexpr const size_t msgPayloadSize =
28     1024 * 60; // Total size will transfer for smbios table
29 static constexpr const size_t mdriiSMSize = 0x00100000;
30 
31 static constexpr const uint16_t smbiosAgentId =
32     0x0101; // Agent ID for smbios entry
33 static constexpr const int firstAgentIndex = 1;
34 
35 static constexpr const uint8_t maxDirEntries = 4; // Maximum directory entries
36 static constexpr const uint32_t mdr2SMSize =
37     0x00100000;                                   // Size of VGA share memory
38 static constexpr const uint32_t mdr2SMBaseAddress =
39     0x9FF00000; // Base address of VGA share memory
40 
41 static constexpr const uint8_t mdrTypeII = 2;          // MDR V2 type
42 
43 static constexpr const uint8_t mdr2Version = 2;        // MDR V2 versoin
44 static constexpr const uint8_t smbiosAgentVersion = 1; // Agent version of
45                                                        // smbios
46 
47 static constexpr const uint32_t pageMask =
48     0xf000; // To make data become n times of page
49 static constexpr const int smbiosDirIndex = 0; // SMBIOS directory index
50 
51 static constexpr const uint32_t smbiosTableVersion =
52     15;          // Version of smbios table
53 static constexpr const uint32_t smbiosTableTimestamp =
54     0x45464748;  // Time stamp when smbios table created
55 static constexpr const size_t smbiosSMMemoryOffset =
56     0;           // Offset of VGA share memory
57 static constexpr const size_t smbiosSMMemorySize =
58     1024 * 1024; // Total size of VGA share memory
59 static constexpr const size_t smbiosTableStorageSize =
60     64 * 1024;   // Total size of smbios table
61 static constexpr const uint32_t defaultTimeout = 4000;
62 static constexpr const uint16_t sysClock = 1000;
63 static constexpr const int lastAgentIndex = -1;
64 static constexpr const uint16_t lastAgentId = 0xFFFF;
65 constexpr const uint32_t invalidChecksum = 0xffffffff;
66 constexpr const char* dbusProperties = "org.freedesktop.DBus.Properties";
67 constexpr const char* mdrv2Path = "/xyz/openbmc_project/Smbios/MDR_V2";
68 constexpr const char* mdrv2Interface = "xyz.openbmc_project.Smbios.MDR_V2";
69 
70 enum class MDR2SMBIOSStatusEnum
71 {
72     mdr2Init = 0,
73     mdr2Loaded = 1,
74     mdr2Updated = 2,
75     mdr2Updating = 3
76 };
77 
78 enum class DirDataRequestEnum
79 {
80     dirDataNotRequested = 0x00,
81     dirDataRequested = 0x01
82 };
83 
84 enum MDR2DirLockEnum
85 {
86     mdr2DirUnlock = 0,
87     mdr2DirLock = 1
88 };
89 
90 #pragma pack(push)
91 #pragma pack(1)
92 
93 struct MDRSMBIOSHeader
94 {
95     uint8_t dirVer;
96     uint8_t mdrType;
97     uint32_t timestamp;
98     uint32_t dataSize;
99 };
100 
101 struct DataIdStruct
102 {
103     uint8_t dataInfo[16];
104 };
105 
106 struct Mdr2DirEntry
107 {
108     DataIdStruct id;
109     uint32_t size;
110     uint32_t dataSetSize;
111     uint32_t dataVersion;
112     uint32_t timestamp;
113 };
114 
115 struct Mdr2DirLocalStruct
116 {
117     Mdr2DirEntry common;
118     MDR2SMBIOSStatusEnum stage;
119     MDR2DirLockEnum lock;
120     uint16_t lockHandle;
121     uint32_t xferBuff;
122     uint32_t xferSize;
123     uint32_t maxDataSize;
124     uint8_t* dataStorage;
125 };
126 
127 struct Mdr2DirStruct
128 {
129     uint8_t agentVersion;
130     uint8_t dirVersion;
131     uint8_t dirEntries;
132     uint8_t status; // valid / locked / etc
133     uint8_t remoteDirVersion;
134     uint16_t sessionHandle;
135     Mdr2DirLocalStruct dir[maxDirEntries];
136 };
137 
138 // Three members include dataSetSize, dataVersion and timestamp
139 static constexpr const size_t syncDirCommonSize = 3;
140 
141 // ====================== MDR II Pull Command Structures ======================
142 struct MDRiiGetDataInfoRequest
143 {
144     uint16_t agentId;
145     DataIdStruct dataSetInfo;
146 };
147 
148 // MDR II data set information inquiry response
149 struct MDRiiGetDataInfoResponse
150 {
151     uint8_t mdrVersion;
152     DataIdStruct dataSetId;
153     uint8_t validFlag;
154     uint32_t dataLength;
155     uint8_t dataVersion;
156     uint32_t timeStamp;
157 };
158 
159 // ====================== MDR II Push Command Structures ======================
160 // MDR II Client send data set info offer response
161 struct MDRiiOfferDataInfoResponse
162 {
163     DataIdStruct dataSetInfo;
164 };
165 
166 // MDR II Push Agent send data set info command
167 struct MDRiiSendDataInfoRequest
168 {
169     uint16_t agentId;
170     DataIdStruct dataSetInfo;
171     uint8_t validFlag;
172     uint32_t dataLength;
173     uint32_t dataVersion; // Roughly equivalent to the "file name"
174     uint32_t
175         timeStamp; // More info on the identity of this particular set of data
176 };
177 
178 // MDR II Pull Agent lock data set command
179 struct MDRiiLockDataRequest
180 {
181     uint16_t agentId;
182     DataIdStruct dataSetInfo;
183     uint16_t timeout;
184 };
185 
186 // MDR II Pull Agent lock data set response
187 struct MDRiiLockDataResponse
188 {
189     uint8_t mdrVersion;
190     uint16_t lockHandle;
191     uint32_t dataLength;
192     uint32_t xferAddress;
193     uint32_t xferLength;
194 };
195 
196 // MDR II Push Agent send data start command
197 struct MDRiiDataStartRequest
198 {
199     uint16_t agentId;
200     DataIdStruct dataSetInfo;
201     uint32_t dataLength;
202     uint32_t xferAddress;
203     uint32_t xferLength;
204     uint16_t timeout;
205 };
206 
207 // MDR II Client send data start response
208 struct MDRiiDataStartResponse
209 {
210     uint8_t xferStartAck;
211     uint16_t sessionHandle;
212 };
213 
214 // MDR II
215 struct MDRiiDataDoneRequest
216 {
217     uint16_t agentId;
218     uint16_t lockHandle;
219 };
220 
221 #pragma pack(pop)
222 
223 class SharedMemoryArea
224 {
225   public:
226     SharedMemoryArea(uint32_t addr, uint32_t areaSize) :
227         vPtr(nullptr), physicalAddr(addr), size(areaSize)
228     {
229         Initialize(addr, areaSize);
230     }
231 
232     ~SharedMemoryArea()
233     {
234         if ((vPtr != nullptr) && (vPtr != MAP_FAILED))
235         {
236             if (0 != munmap(vPtr, size))
237             {
238                 phosphor::logging::log<phosphor::logging::level::ERR>(
239                     "Ummap share memory failed");
240             }
241         }
242     }
243 
244     void* vPtr;
245 
246   private:
247     uint32_t physicalAddr;
248     uint32_t size;
249 
250     void Initialize(uint32_t addr, uint32_t areaSize);
251 };
252 
253 class MDRV2
254 {
255   public:
256     MDRV2()
257     {
258         timer =
259             std::make_unique<phosphor::Timer>([&](void) { timeoutHandler(); });
260     }
261 
262     int agentLookup(const uint16_t& agentId);
263     int findLockHandle(const uint16_t& lockHandle);
264     int syncDirCommonData(uint8_t idIndex, uint32_t size,
265                           const std::string& service);
266     int findDataId(const uint8_t* dataInfo, const size_t& len,
267                    const std::string& service);
268     uint16_t getSessionHandle(Mdr2DirStruct* dir);
269     bool smbiosIsUpdating(uint8_t index);
270     uint32_t calcChecksum32(uint8_t* buf, uint32_t len);
271     bool storeDatatoFlash(MDRSMBIOSHeader* mdrHdr, uint8_t* data);
272     bool smbiosUnlock(uint8_t index);
273     void timeoutHandler();
274     bool smbiosTryLock(uint8_t flag, uint8_t index, uint16_t* session,
275                        uint16_t timeout);
276     int sdplusMdrv2GetProperty(const std::string& name,
277                                ipmi::DbusVariant& value,
278                                const std::string& service);
279 
280     Mdr2DirStruct smbiosDir{smbiosAgentVersion,
281                             1,
282                             1,
283                             1,
284                             0,
285                             0,
286                             {40,
287                              41,
288                              42,
289                              43,
290                              44,
291                              45,
292                              46,
293                              47,
294                              48,
295                              49,
296                              50,
297                              51,
298                              52,
299                              53,
300                              54,
301                              0x42,
302                              0,
303                              smbiosTableStorageSize,
304                              smbiosTableVersion,
305                              smbiosTableTimestamp,
306                              MDR2SMBIOSStatusEnum::mdr2Init,
307                              MDR2DirLockEnum::mdr2DirUnlock,
308                              0,
309                              smbiosSMMemoryOffset,
310                              smbiosSMMemorySize,
311                              smbiosTableStorageSize,
312                              smbiosTableStorage}};
313     std::unique_ptr<SharedMemoryArea> area;
314     std::unique_ptr<phosphor::Timer> timer;
315 
316   private:
317     uint8_t lockIndex = 0;
318     uint8_t smbiosTableStorage[smbiosTableStorageSize];
319 };
320