blob: afdb8973d3060a4820a938a41dc523bf7eb5fc75 [file] [log] [blame]
Cheng C Yangeecaf822019-12-19 00:34:23 +08001/*
2// Copyright (c) 2019 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#include "mdrv2.hpp"
18
19#include <sys/mman.h>
20
21#include <fstream>
22#include <phosphor-logging/elog-errors.hpp>
23#include <sdbusplus/exception.hpp>
24#include <xyz/openbmc_project/Smbios/MDR_V2/error.hpp>
25
26namespace phosphor
27{
28namespace smbios
29{
30
31std::vector<uint8_t> MDR_V2::getDirectoryInformation(uint8_t dirIndex)
32{
Cheng C Yang608e52d2019-12-19 00:39:50 +080033 std::vector<uint8_t> responseDir;
34 if (dirIndex > smbiosDir.dirEntries)
35 {
36 responseDir.push_back(0);
37 throw sdbusplus::xyz::openbmc_project::Smbios::MDR_V2::Error::
38 InvalidParameter();
39 }
40 responseDir.push_back(mdr2Version);
41 responseDir.push_back(smbiosDir.dirVersion);
42 uint8_t returnedEntries = smbiosDir.dirEntries - dirIndex;
43 responseDir.push_back(returnedEntries);
44 if ((dirIndex + returnedEntries) >= smbiosDir.dirEntries)
45 {
46 responseDir.push_back(0);
47 }
48 else
49 {
50 responseDir.push_back(smbiosDir.dirEntries - dirIndex -
51 returnedEntries);
52 }
53 for (uint8_t index = dirIndex; index < smbiosDir.dirEntries; index++)
54 {
55 for (uint8_t indexId = 0; indexId < sizeof(DataIdStruct); indexId++)
56 {
57 responseDir.push_back(
58 smbiosDir.dir[index].common.id.dataInfo[indexId]);
59 }
60 }
61
62 return responseDir;
Cheng C Yangeecaf822019-12-19 00:34:23 +080063}
64
65bool MDR_V2::smbiosIsAvailForUpdate(uint8_t index)
66{
67 bool ret = false;
68 if (index > maxDirEntries)
69 {
70 return ret;
71 }
72
73 switch (smbiosDir.dir[index].stage)
74 {
75 case MDR2SMBIOSStatusEnum::mdr2Updating:
76 ret = false;
77 break;
78
79 case MDR2SMBIOSStatusEnum::mdr2Init:
80 // This *looks* like there should be a break statement here,
81 // as the effects of the previous statement are a noop given
82 // the following code that this falls through to.
83 // We've elected not to change it, though, since it's been
84 // this way since the old generation, and it would affect
85 // the way the code functions.
86 // If it ain't broke, don't fix it.
87
88 case MDR2SMBIOSStatusEnum::mdr2Loaded:
89 case MDR2SMBIOSStatusEnum::mdr2Updated:
90 if (smbiosDir.dir[index].lock == MDR2DirLockEnum::mdr2DirLock)
91 {
92 ret = false;
93 }
94 else
95 {
96 ret = true;
97 }
98 break;
99
100 default:
101 break;
102 }
103
104 return ret;
105}
106
107std::vector<uint8_t> MDR_V2::getDataOffer()
108{
109 std::vector<uint8_t> offer(sizeof(DataIdStruct));
110 if (smbiosIsAvailForUpdate(0))
111 {
112 std::copy(smbiosDir.dir[0].common.id.dataInfo,
113 &smbiosDir.dir[0].common.id.dataInfo[16], offer.data());
114 }
115 else
116 {
117 phosphor::logging::log<phosphor::logging::level::ERR>(
118 "smbios is not ready for update");
119 throw sdbusplus::xyz::openbmc_project::Smbios::MDR_V2::Error::
120 UpdateInProgress();
121 }
122 return offer;
123}
124
125inline uint8_t MDR_V2::smbiosValidFlag(uint8_t index)
126{
127 FlagStatus ret = FlagStatus::flagIsInvalid;
128 MDR2SMBIOSStatusEnum stage = smbiosDir.dir[index].stage;
129 MDR2DirLockEnum lock = smbiosDir.dir[index].lock;
130
131 switch (stage)
132 {
133 case MDR2SMBIOSStatusEnum::mdr2Loaded:
134 case MDR2SMBIOSStatusEnum::mdr2Updated:
135 if (lock == MDR2DirLockEnum::mdr2DirLock)
136 {
137 ret = FlagStatus::flagIsLocked; // locked
138 }
139 else
140 {
141 ret = FlagStatus::flagIsValid; // valid
142 }
143 break;
144
145 case MDR2SMBIOSStatusEnum::mdr2Updating:
146 case MDR2SMBIOSStatusEnum::mdr2Init:
147 ret = FlagStatus::flagIsInvalid; // invalid
148 break;
149
150 default:
151 break;
152 }
153
154 return static_cast<uint8_t>(ret);
155}
156
157std::vector<uint8_t> MDR_V2::getDataInformation(uint8_t idIndex)
158{
159 std::vector<uint8_t> responseInfo;
160 responseInfo.push_back(mdr2Version);
161
162 if (idIndex >= maxDirEntries)
163 {
164 throw sdbusplus::xyz::openbmc_project::Smbios::MDR_V2::Error::
165 InvalidParameter();
166 }
167
168 for (uint8_t index = 0; index < sizeof(DataIdStruct); index++)
169 {
170 responseInfo.push_back(
171 smbiosDir.dir[idIndex].common.id.dataInfo[index]);
172 }
173 responseInfo.push_back(smbiosValidFlag(idIndex));
174 responseInfo.push_back(smbiosDir.dir[idIndex].common.size);
175 responseInfo.push_back(smbiosDir.dir[idIndex].common.dataVersion);
176 responseInfo.push_back(smbiosDir.dir[idIndex].common.timestamp);
177
178 return responseInfo;
179}
180
181bool MDR_V2::sendDirectoryInformation(uint8_t dirVersion, uint8_t dirIndex,
182 uint8_t returnedEntries,
183 uint8_t remainingEntries,
184 std::vector<uint8_t> dirEntry)
185{
Cheng C Yang608e52d2019-12-19 00:39:50 +0800186 bool teminate = false;
187 if ((dirIndex >= maxDirEntries) || (returnedEntries < 1))
188 {
189 phosphor::logging::log<phosphor::logging::level::ERR>(
190 "Send Dir info failed - input parameter invalid");
191 throw sdbusplus::xyz::openbmc_project::Smbios::MDR_V2::Error::
192 InvalidParameter();
193 }
194 if (dirEntry.size() < sizeof(Mdr2DirEntry))
195 {
196 phosphor::logging::log<phosphor::logging::level::ERR>(
197 "Directory size invalid");
198 throw sdbusplus::xyz::openbmc_project::Smbios::MDR_V2::Error::
199 InvalidParameter();
200 }
201 if (dirVersion == smbiosDir.dirVersion)
202 {
203 teminate = true;
204 }
205 else
206 {
207 if (remainingEntries > 0)
208 {
209 teminate = false;
210 }
211 else
212 {
213 teminate = true;
214 smbiosDir.dirVersion = dirVersion;
215 }
216 uint8_t idIndex = dirIndex;
217
218 uint8_t* pData = dirEntry.data();
219 if (pData == nullptr)
220 {
221 return false;
222 }
223 for (uint8_t index = 0; index < returnedEntries; index++)
224 {
225 auto data = reinterpret_cast<const Mdr2DirEntry*>(pData);
226 smbiosDir.dir[idIndex + index].common.dataVersion =
227 data->dataVersion;
228 std::copy(data->id.dataInfo,
229 data->id.dataInfo + sizeof(DataIdStruct),
230 smbiosDir.dir[idIndex + index].common.id.dataInfo);
231 smbiosDir.dir[idIndex + index].common.dataSetSize = data->size;
232 smbiosDir.dir[idIndex + index].common.timestamp = data->timestamp;
233 pData += sizeof(returnedEntries);
234 }
235 }
236 return teminate;
Cheng C Yangeecaf822019-12-19 00:34:23 +0800237}
238
239bool MDR_V2::sendDataInformation(uint8_t idIndex, uint8_t flag,
240 uint32_t dataLen, uint32_t dataVer,
241 uint32_t timeStamp)
242{
243 if (idIndex >= maxDirEntries)
244 {
245 throw sdbusplus::xyz::openbmc_project::Smbios::MDR_V2::Error::
246 InvalidParameter();
247 }
248 int entryChanged = 0;
249 if (smbiosDir.dir[idIndex].common.dataSetSize != dataLen)
250 {
251 entryChanged++;
252 smbiosDir.dir[idIndex].common.dataSetSize = dataLen;
253 }
254
255 if (smbiosDir.dir[idIndex].common.dataVersion != dataVer)
256 {
257 entryChanged++;
258 smbiosDir.dir[idIndex].common.dataVersion = dataVer;
259 }
260
261 if (smbiosDir.dir[idIndex].common.timestamp != timeStamp)
262 {
263 entryChanged++;
264 smbiosDir.dir[idIndex].common.timestamp = timeStamp;
265 }
266 if (entryChanged == 0)
267 {
268 return false;
269 }
270 return true;
271}
272
273int MDR_V2::findIdIndex(std::vector<uint8_t> dataInfo)
274{
275 if (dataInfo.size() != sizeof(DataIdStruct))
276 {
277 phosphor::logging::log<phosphor::logging::level::ERR>(
278 "Length of dataInfo invalid");
279 throw sdbusplus::xyz::openbmc_project::Smbios::MDR_V2::Error::
280 InvalidParameter();
281 }
282 std::array<uint8_t, 16> arrayDataInfo;
283
284 std::copy(dataInfo.begin(), dataInfo.end(), arrayDataInfo.begin());
285
286 for (int index = 0; index < smbiosDir.dirEntries; index++)
287 {
288 int info = 0;
289 for (; info < arrayDataInfo.size(); info++)
290 {
291 if (arrayDataInfo[info] !=
292 smbiosDir.dir[index].common.id.dataInfo[info])
293 {
294 break;
295 }
296 }
297 if (info == arrayDataInfo.size())
298 {
299 return index;
300 }
301 }
302 throw sdbusplus::xyz::openbmc_project::Smbios::MDR_V2::Error::InvalidId();
303}
304
305uint8_t MDR_V2::directoryEntries(uint8_t value)
306{
307 value = smbiosDir.dirEntries;
308 return sdbusplus::xyz::openbmc_project::Smbios::server::MDR_V2::
309 directoryEntries(value);
310}
311
312bool MDR_V2::agentSynchronizeData()
313{
314}
315
316std::vector<uint32_t> MDR_V2::synchronizeDirectoryCommonData(uint8_t idIndex,
317 uint32_t size)
318{
319}
320
321} // namespace smbios
322} // namespace phosphor