blob: d97ccf475b7ff81304fbea41a6b106a65773152c [file] [log] [blame]
Vernon Mauerya3702c12019-05-22 13:20:59 -07001/*
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#include <errno.h>
18#include <fcntl.h>
Vernon Mauerya3702c12019-05-22 13:20:59 -070019#include <limits.h>
20#include <sys/stat.h>
21#include <sys/types.h>
22#include <unistd.h>
23
24#include <commandutils.hpp>
25#include <cstdint>
26#include <fstream>
jayaprakash Mutyala853d8292019-05-31 18:17:42 +000027#include <ipmid/api.hpp>
Vernon Mauerya3702c12019-05-22 13:20:59 -070028#include <ipmid/utils.hpp>
29#include <phosphor-logging/log.hpp>
Vernon Mauerya3702c12019-05-22 13:20:59 -070030#include <sdbusplus/message/types.hpp>
31#include <smbiosmdrv2handler.hpp>
32#include <string>
33#include <vector>
34#include <xyz/openbmc_project/Common/error.hpp>
Vernon Mauerya3702c12019-05-22 13:20:59 -070035
36std::unique_ptr<MDRV2> mdrv2 = nullptr;
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +000037static constexpr const uint8_t ccOemInvalidChecksum = 0x85;
Vernon Mauerya3702c12019-05-22 13:20:59 -070038
Vernon Mauerya3702c12019-05-22 13:20:59 -070039static void register_netfn_smbiosmdrv2_functions() __attribute__((constructor));
Vernon Mauerya3702c12019-05-22 13:20:59 -070040
41int MDRV2::agentLookup(const uint16_t &agentId)
42{
43 int agentIndex = -1;
44
45 if (lastAgentId == agentId)
46 {
47 return lastAgentIndex;
48 }
49
50 if (agentId == smbiosAgentId)
51 {
52 return firstAgentIndex;
53 }
54
55 return agentIndex;
56}
57
58int MDRV2::sdplusMdrv2GetProperty(const std::string &name,
59 sdbusplus::message::variant<uint8_t> &value,
60 const std::string &service)
61{
Vernon Mauery15419dd2019-05-24 09:40:30 -070062 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
Vernon Mauerya3702c12019-05-22 13:20:59 -070063 sdbusplus::message::message method =
Vernon Mauery15419dd2019-05-24 09:40:30 -070064 bus->new_method_call(service.c_str(), mdrv2Path, dbusProperties, "Get");
Vernon Mauerya3702c12019-05-22 13:20:59 -070065 method.append(mdrv2Interface, name);
66
Vernon Mauery15419dd2019-05-24 09:40:30 -070067 sdbusplus::message::message reply = bus->call(method);
Vernon Mauerya3702c12019-05-22 13:20:59 -070068
69 try
70 {
Vernon Mauery15419dd2019-05-24 09:40:30 -070071 sdbusplus::message::message reply = bus->call(method);
Vernon Mauerya3702c12019-05-22 13:20:59 -070072 reply.read(value);
73 }
Vernon Maueryc7d517e2019-06-18 14:27:00 -070074 catch (sdbusplus::exception_t &e)
Vernon Mauerya3702c12019-05-22 13:20:59 -070075 {
76 phosphor::logging::log<phosphor::logging::level::ERR>(
Vernon Maueryc7d517e2019-06-18 14:27:00 -070077 "Error get property, sdbusplus call failed",
78 phosphor::logging::entry("ERROR=%s", e.what()));
Vernon Mauerya3702c12019-05-22 13:20:59 -070079 return -1;
80 }
81
82 return 0;
83}
84
85int MDRV2::syncDirCommonData(uint8_t idIndex, uint32_t size,
86 const std::string &service)
87{
88 std::vector<uint32_t> commonData;
Vernon Mauery15419dd2019-05-24 09:40:30 -070089 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
Vernon Mauerya3702c12019-05-22 13:20:59 -070090 sdbusplus::message::message method =
Vernon Mauery15419dd2019-05-24 09:40:30 -070091 bus->new_method_call(service.c_str(), mdrv2Path, mdrv2Interface,
92 "SynchronizeDirectoryCommonData");
Vernon Mauerya3702c12019-05-22 13:20:59 -070093 method.append(idIndex, size);
94
95 try
96 {
Vernon Mauery15419dd2019-05-24 09:40:30 -070097 sdbusplus::message::message reply = bus->call(method);
Vernon Mauerya3702c12019-05-22 13:20:59 -070098 reply.read(commonData);
99 }
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700100 catch (sdbusplus::exception_t &e)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700101 {
102 phosphor::logging::log<phosphor::logging::level::ERR>(
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700103 "Error sync dir common data with service",
104 phosphor::logging::entry("ERROR=%s", e.what()));
Vernon Mauerya3702c12019-05-22 13:20:59 -0700105 return -1;
106 }
107
108 if (commonData.size() < syncDirCommonSize)
109 {
110 phosphor::logging::log<phosphor::logging::level::ERR>(
111 "Error sync dir common data - data length invalid");
112 return -1;
113 }
114 smbiosDir.dir[idIndex].common.dataSetSize = commonData.at(0);
115 smbiosDir.dir[idIndex].common.dataVersion = commonData.at(1);
116 smbiosDir.dir[idIndex].common.timestamp = commonData.at(2);
117
118 return 0;
119}
120
121int MDRV2::findDataId(const uint8_t *dataInfo, const size_t &len,
122 const std::string &service)
123{
124 int idIndex = -1;
125
126 if (dataInfo == nullptr)
127 {
128 phosphor::logging::log<phosphor::logging::level::ERR>(
129 "Error dataInfo, input is null point");
130 return -1;
131 }
132
Vernon Mauery15419dd2019-05-24 09:40:30 -0700133 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
134 sdbusplus::message::message method = bus->new_method_call(
Vernon Mauerya3702c12019-05-22 13:20:59 -0700135 service.c_str(), mdrv2Path, mdrv2Interface, "FindIdIndex");
136 std::vector<uint8_t> info;
137 info.resize(len);
138 std::copy(dataInfo, dataInfo + len, info.data());
139 method.append(info);
140
141 try
142 {
Vernon Mauery15419dd2019-05-24 09:40:30 -0700143 sdbusplus::message::message reply = bus->call(method);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700144 reply.read(idIndex);
145 }
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700146 catch (sdbusplus::exception_t &e)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700147 {
148 phosphor::logging::log<phosphor::logging::level::ERR>(
149 "Error find id index",
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700150 phosphor::logging::entry("ERROR=%s", e.what()),
Vernon Mauerya3702c12019-05-22 13:20:59 -0700151 phosphor::logging::entry("SERVICE=%s", service.c_str()),
152 phosphor::logging::entry("PATH=%s", mdrv2Path));
153 return -1;
154 }
155
156 return idIndex;
157}
158
159uint16_t MDRV2::getSessionHandle(Mdr2DirStruct *dir)
160{
161 if (dir == NULL)
162 {
163 phosphor::logging::log<phosphor::logging::level::ERR>(
164 "Empty dir point");
165 return 0;
166 }
167 dir->sessionHandle++;
168 if (dir->sessionHandle == 0)
169 {
170 dir->sessionHandle = 1;
171 }
172
173 return dir->sessionHandle;
174}
175
176int MDRV2::findLockHandle(const uint16_t &lockHandle)
177{
178 int idIndex = -1;
179
180 for (int index = 0; index < smbiosDir.dirEntries; index++)
181 {
182 if (lockHandle == smbiosDir.dir[index].lockHandle)
183 {
184 return index;
185 }
186 }
187
188 return idIndex;
189}
190
191bool MDRV2::smbiosIsUpdating(uint8_t index)
192{
193 if (index > maxDirEntries)
194 {
195 return false;
196 }
197 if (smbiosDir.dir[index].stage == MDR2SMBIOSStatusEnum::mdr2Updating)
198 {
199 return true;
200 }
201
202 return false;
203}
204
205uint32_t MDRV2::calcChecksum32(uint8_t *buf, uint32_t len)
206{
207 uint32_t sum = 0;
208
209 if (buf == nullptr)
210 {
211 return invalidChecksum;
212 }
213
214 for (uint32_t index = 0; index < len; index++)
215 {
216 sum += buf[index];
217 }
218
219 return sum;
220}
221
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000222/** @brief implements mdr2 agent status command
223 * @param agentId
224 * @param dirVersion
225 *
226 * @returns IPMI completion code plus response data
227 * - mdrVersion
228 * - agentVersion
229 * - dirVersion
230 * - dirEntries
231 * - dataRequest
232 */
233ipmi::RspType<uint8_t, uint8_t, uint8_t, uint8_t, uint8_t>
234 mdr2AgentStatus(uint16_t agentId, uint8_t dirVersion)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700235{
Vernon Mauerya3702c12019-05-22 13:20:59 -0700236 if (mdrv2 == nullptr)
237 {
238 mdrv2 = std::make_unique<MDRV2>();
239 }
240
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000241 int agentIndex = mdrv2->agentLookup(agentId);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700242 if (agentIndex == -1)
243 {
244 phosphor::logging::log<phosphor::logging::level::ERR>(
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000245 "Unknown agent id", phosphor::logging::entry("ID=%x", agentId));
246 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700247 }
248
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000249 constexpr uint8_t mdrVersion = mdr2Version;
250 constexpr uint8_t agentVersion = smbiosAgentVersion;
251 uint8_t dirVersionResp = mdrv2->smbiosDir.dirVersion;
252 uint8_t dirEntries = mdrv2->smbiosDir.dirEntries;
253 uint8_t dataRequest;
Vernon Mauerya3702c12019-05-22 13:20:59 -0700254
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000255 if (mdrv2->smbiosDir.remoteDirVersion != dirVersion)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700256 {
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000257 mdrv2->smbiosDir.remoteDirVersion = dirVersion;
258 dataRequest =
Vernon Mauerya3702c12019-05-22 13:20:59 -0700259 static_cast<uint8_t>(DirDataRequestEnum::dirDataRequested);
260 }
261 else
262 {
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000263 dataRequest =
Vernon Mauerya3702c12019-05-22 13:20:59 -0700264 static_cast<uint8_t>(DirDataRequestEnum::dirDataNotRequested);
265 }
266
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000267 return ipmi::responseSuccess(mdrVersion, agentVersion, dirVersionResp,
268 dirEntries, dataRequest);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700269}
270
271ipmi_ret_t cmd_mdr2_get_dir(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
272 ipmi_request_t request, ipmi_response_t response,
273 ipmi_data_len_t data_len, ipmi_context_t context)
274{
275 auto requestData = reinterpret_cast<const MDRiiGetDirRequest *>(request);
276 auto dataOut = reinterpret_cast<uint8_t *>(response);
277 std::vector<uint8_t> dirInfo;
278
279 if (*data_len != sizeof(MDRiiGetDirRequest))
280 {
281 *data_len = 0;
282 return IPMI_CC_REQ_DATA_LEN_INVALID;
283 }
284
285 *data_len = 0;
286
Vernon Mauery15419dd2019-05-24 09:40:30 -0700287 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
288 std::string service = ipmi::getService(*bus, mdrv2Interface, mdrv2Path);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700289
290 if (mdrv2 == nullptr)
291 {
292 mdrv2 = std::make_unique<MDRV2>();
293 }
294
295 int agentIndex = mdrv2->agentLookup(requestData->agentId);
296 if (agentIndex == -1)
297 {
298 phosphor::logging::log<phosphor::logging::level::ERR>(
299 "Unknown agent id",
300 phosphor::logging::entry("ID=%x", requestData->agentId));
301 return IPMI_CC_PARM_OUT_OF_RANGE;
302 }
303
304 sdbusplus::message::variant<uint8_t> value = 0;
305 if (0 != mdrv2->sdplusMdrv2GetProperty("DirectoryEntries", value, service))
306 {
307 phosphor::logging::log<phosphor::logging::level::ERR>(
308 "Error getting DirEnries");
309 return IPMI_CC_UNSPECIFIED_ERROR;
310 }
Vernon Mauery8166c8d2019-05-23 11:22:30 -0700311 if (requestData->dirIndex > std::get<uint8_t>(value))
Vernon Mauerya3702c12019-05-22 13:20:59 -0700312 {
313 return IPMI_CC_PARM_OUT_OF_RANGE;
314 }
315
Vernon Mauery15419dd2019-05-24 09:40:30 -0700316 sdbusplus::message::message method = bus->new_method_call(
Vernon Mauerya3702c12019-05-22 13:20:59 -0700317 service.c_str(), mdrv2Path, mdrv2Interface, "GetDirectoryInformation");
318
319 method.append(requestData->dirIndex);
320
321 try
322 {
Vernon Mauery15419dd2019-05-24 09:40:30 -0700323 sdbusplus::message::message reply = bus->call(method);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700324 reply.read(dirInfo);
325 }
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700326 catch (sdbusplus::exception_t &e)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700327 {
328 phosphor::logging::log<phosphor::logging::level::ERR>(
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700329 "Error get dir", phosphor::logging::entry("ERROR=%s", e.what()),
Vernon Mauerya3702c12019-05-22 13:20:59 -0700330 phosphor::logging::entry("SERVICE=%s", service.c_str()),
331 phosphor::logging::entry("PATH=%s", mdrv2Path));
332 return IPMI_CC_RESPONSE_ERROR;
333 }
334
335 if (dirInfo.size() < sizeof(MDRiiGetDirResponse))
336 {
337 phosphor::logging::log<phosphor::logging::level::ERR>(
338 "Error get dir, response length invalid");
339 return IPMI_CC_UNSPECIFIED_ERROR;
340 }
341
342 auto responseData = reinterpret_cast<MDRiiGetDirResponse *>(dirInfo.data());
343
344 *data_len = dirInfo.size();
345
346 if (*data_len > MAX_IPMI_BUFFER) // length + completion code should no more
347 // than MAX_IPMI_BUFFER
348 {
349 phosphor::logging::log<phosphor::logging::level::ERR>(
350 "Data length send from service is invalid");
351 *data_len = 0;
352 return IPMI_CC_RESPONSE_ERROR;
353 }
354
355 std::copy(&dirInfo[0], &dirInfo[*data_len], dataOut);
356
357 return IPMI_CC_OK;
358}
359
360ipmi_ret_t cmd_mdr2_send_dir(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
361 ipmi_request_t request, ipmi_response_t response,
362 ipmi_data_len_t data_len, ipmi_context_t context)
363{
364 auto requestData = reinterpret_cast<const MDRiiSendDirRequest *>(request);
365 std::vector<uint8_t> idVector;
366 bool teminate = false;
367
368 if (*data_len != sizeof(MDRiiSendDirRequest))
369 {
370 *data_len = 0;
371 return IPMI_CC_REQ_DATA_LEN_INVALID;
372 }
373
374 *data_len = 0;
375
Vernon Mauery15419dd2019-05-24 09:40:30 -0700376 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
377 std::string service = ipmi::getService(*bus, mdrv2Interface, mdrv2Path);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700378
379 if (mdrv2 == nullptr)
380 {
381 mdrv2 = std::make_unique<MDRV2>();
382 }
383
384 int agentIndex = mdrv2->agentLookup(requestData->agentId);
385 if (agentIndex == -1)
386 {
387 phosphor::logging::log<phosphor::logging::level::ERR>(
388 "Unknown agent id",
389 phosphor::logging::entry("ID=%x", requestData->agentId));
390 return IPMI_CC_PARM_OUT_OF_RANGE;
391 }
392
393 if ((requestData->dirIndex + requestData->returnedEntries) > maxDirEntries)
394 {
395 phosphor::logging::log<phosphor::logging::level::ERR>(
396 "Too many directory entries");
397 return IPMI_CC_STORGE_LEAK;
398 }
399
Vernon Mauery15419dd2019-05-24 09:40:30 -0700400 sdbusplus::message::message method = bus->new_method_call(
Vernon Mauerya3702c12019-05-22 13:20:59 -0700401 service.c_str(), mdrv2Path, mdrv2Interface, "SendDirectoryInformation");
402 method.append(requestData->dirVersion, requestData->dirIndex,
403 requestData->returnedEntries, requestData->remainingEntries);
404 uint8_t *reqPoint;
405 for (int index = 0; index < requestData->returnedEntries; index++)
406 {
407 reqPoint = (uint8_t *)&(requestData->data[index]);
408 std::copy(reqPoint, sizeof(Mdr2DirEntry) + reqPoint, idVector.data());
409 }
410 method.append(idVector);
411
412 try
413 {
Vernon Mauery15419dd2019-05-24 09:40:30 -0700414 sdbusplus::message::message reply = bus->call(method);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700415 reply.read(teminate);
416 }
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700417 catch (sdbusplus::exception_t &e)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700418 {
419 phosphor::logging::log<phosphor::logging::level::ERR>(
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700420 "Error send dir", phosphor::logging::entry("ERROR=%s", e.what()),
Vernon Mauerya3702c12019-05-22 13:20:59 -0700421 phosphor::logging::entry("SERVICE=%s", service.c_str()),
422 phosphor::logging::entry("PATH=%s", mdrv2Path));
423 return IPMI_CC_RESPONSE_ERROR;
424 }
425
426 *data_len = 1;
427 if (teminate == false)
428 *(static_cast<uint8_t *>(response)) = 0;
429 else
430 *(static_cast<uint8_t *>(response)) = 1;
431 return IPMI_CC_OK;
432}
433
434ipmi_ret_t cmd_mdr2_get_data_info(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
435 ipmi_request_t request,
436 ipmi_response_t response,
437 ipmi_data_len_t data_len,
438 ipmi_context_t context)
439{
440 auto requestData =
441 reinterpret_cast<const MDRiiGetDataInfoRequest *>(request);
442 auto dataOut = reinterpret_cast<uint8_t *>(response);
443 std::vector<uint8_t> res;
444
445 if (*data_len < sizeof(MDRiiGetDataInfoRequest))
446 {
447 *data_len = 0;
448 return IPMI_CC_REQ_DATA_LEN_INVALID;
449 }
450
451 *data_len = 0;
452
Vernon Mauery15419dd2019-05-24 09:40:30 -0700453 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
454 std::string service = ipmi::getService(*bus, mdrv2Interface, mdrv2Path);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700455
456 if (mdrv2 == nullptr)
457 {
458 mdrv2 = std::make_unique<MDRV2>();
459 }
460
461 int agentIndex = mdrv2->agentLookup(requestData->agentId);
462 if (agentIndex == -1)
463 {
464 phosphor::logging::log<phosphor::logging::level::ERR>(
465 "Unknown agent id",
466 phosphor::logging::entry("ID=%x", requestData->agentId));
467 return IPMI_CC_PARM_OUT_OF_RANGE;
468 }
469
470 int idIndex =
471 mdrv2->findDataId(requestData->dataSetInfo.dataInfo,
472 sizeof(requestData->dataSetInfo.dataInfo), service);
473
474 if ((idIndex < 0) || (idIndex >= maxDirEntries))
475 {
476 phosphor::logging::log<phosphor::logging::level::ERR>(
477 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
478 return IPMI_CC_PARM_OUT_OF_RANGE;
479 }
480
Vernon Mauery15419dd2019-05-24 09:40:30 -0700481 sdbusplus::message::message method = bus->new_method_call(
Vernon Mauerya3702c12019-05-22 13:20:59 -0700482 service.c_str(), mdrv2Path, mdrv2Interface, "GetDataInformation");
483
484 method.append(idIndex);
485
486 try
487 {
Vernon Mauery15419dd2019-05-24 09:40:30 -0700488 sdbusplus::message::message reply = bus->call(method);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700489 reply.read(res);
490 }
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700491 catch (sdbusplus::exception_t &e)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700492 {
493 phosphor::logging::log<phosphor::logging::level::ERR>(
494 "Error get data info",
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700495 phosphor::logging::entry("ERROR=%s", e.what()),
Vernon Mauerya3702c12019-05-22 13:20:59 -0700496 phosphor::logging::entry("SERVICE=%s", service.c_str()),
497 phosphor::logging::entry("PATH=%s", mdrv2Path));
498 return IPMI_CC_RESPONSE_ERROR;
499 }
500
501 if (res.size() != sizeof(MDRiiGetDataInfoResponse))
502 {
503 phosphor::logging::log<phosphor::logging::level::ERR>(
504 "Get data info response length not invalid");
505 return IPMI_CC_UNSPECIFIED_ERROR;
506 }
507 *data_len = static_cast<size_t>(res.size());
508 std::copy(&res[0], &res[*data_len], dataOut);
509
510 return IPMI_CC_OK;
511}
512
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000513/** @brief implements mdr2 data info offer command
514 * @param agentId - Offer a agent ID to get the "Data Set ID"
515 *
516 * @returns IPMI completion code plus response data
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000517 * - dataOut - data Set Id
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000518 */
519ipmi::RspType<std::vector<uint8_t>> mdr2DataInfoOffer(uint16_t agentId)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700520{
Vernon Mauery15419dd2019-05-24 09:40:30 -0700521 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
522 std::string service = ipmi::getService(*bus, mdrv2Interface, mdrv2Path);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700523
524 if (mdrv2 == nullptr)
525 {
526 mdrv2 = std::make_unique<MDRV2>();
527 }
528
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000529 int agentIndex = mdrv2->agentLookup(agentId);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700530 if (agentIndex == -1)
531 {
532 phosphor::logging::log<phosphor::logging::level::ERR>(
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000533 "Unknown agent id", phosphor::logging::entry("ID=%x", agentId));
534 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700535 }
536
Vernon Mauery15419dd2019-05-24 09:40:30 -0700537 sdbusplus::message::message method = bus->new_method_call(
Vernon Mauerya3702c12019-05-22 13:20:59 -0700538 service.c_str(), mdrv2Path, mdrv2Interface, "GetDataOffer");
539
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000540 std::vector<uint8_t> dataOut;
Vernon Mauerya3702c12019-05-22 13:20:59 -0700541 try
542 {
Vernon Mauery15419dd2019-05-24 09:40:30 -0700543 sdbusplus::message::message reply = bus->call(method);
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000544 reply.read(dataOut);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700545 }
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700546 catch (sdbusplus::exception_t &e)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700547 {
548 phosphor::logging::log<phosphor::logging::level::ERR>(
549 "Error send data info offer",
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700550 phosphor::logging::entry("ERROR=%s", e.what()),
Vernon Mauerya3702c12019-05-22 13:20:59 -0700551 phosphor::logging::entry("SERVICE=%s", service.c_str()),
552 phosphor::logging::entry("PATH=%s", mdrv2Path));
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000553 return ipmi::responseResponseError();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700554 }
555
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000556 constexpr size_t respInfoSize = 16;
557 if (dataOut.size() != respInfoSize)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700558 {
559 phosphor::logging::log<phosphor::logging::level::ERR>(
560 "Error send data info offer, return length invalid");
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000561 return ipmi::responseUnspecifiedError();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700562 }
563
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000564 return ipmi::responseSuccess(dataOut);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700565}
566
567ipmi_ret_t cmd_mdr2_send_data_info(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
568 ipmi_request_t request,
569 ipmi_response_t response,
570 ipmi_data_len_t data_len,
571 ipmi_context_t context)
572{
573 auto requestData =
574 reinterpret_cast<const MDRiiSendDataInfoRequest *>(request);
575 bool entryChanged = true;
576
577 if (*data_len != sizeof(MDRiiSendDataInfoRequest))
578 {
579 *data_len = 0;
580 return IPMI_CC_REQ_DATA_LEN_INVALID;
581 }
582
583 *data_len = 0;
584
585 if (requestData->dataLength > smbiosTableStorageSize)
586 {
587 phosphor::logging::log<phosphor::logging::level::ERR>(
588 "Requested data length is out of SMBIOS Table storage size.");
589 return IPMI_CC_PARM_OUT_OF_RANGE;
590 }
591
Vernon Mauery15419dd2019-05-24 09:40:30 -0700592 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
593 std::string service = ipmi::getService(*bus, mdrv2Interface, mdrv2Path);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700594
595 if (mdrv2 == nullptr)
596 {
597 mdrv2 = std::make_unique<MDRV2>();
598 }
599
600 int agentIndex = mdrv2->agentLookup(requestData->agentId);
601 if (agentIndex == -1)
602 {
603 phosphor::logging::log<phosphor::logging::level::ERR>(
604 "Unknown agent id",
605 phosphor::logging::entry("ID=%x", requestData->agentId));
606 return IPMI_CC_PARM_OUT_OF_RANGE;
607 }
608
609 int idIndex =
610 mdrv2->findDataId(requestData->dataSetInfo.dataInfo,
611 sizeof(requestData->dataSetInfo.dataInfo), service);
612
613 if ((idIndex < 0) || (idIndex >= maxDirEntries))
614 {
615 phosphor::logging::log<phosphor::logging::level::ERR>(
616 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
617 return IPMI_CC_PARM_OUT_OF_RANGE;
618 }
619
Vernon Mauery15419dd2019-05-24 09:40:30 -0700620 sdbusplus::message::message method = bus->new_method_call(
Vernon Mauerya3702c12019-05-22 13:20:59 -0700621 service.c_str(), mdrv2Path, mdrv2Interface, "SendDataInformation");
622
623 method.append((uint8_t)idIndex, requestData->validFlag,
624 requestData->dataLength, requestData->dataVersion,
625 requestData->timeStamp);
626
627 try
628 {
Vernon Mauery15419dd2019-05-24 09:40:30 -0700629 sdbusplus::message::message reply = bus->call(method);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700630 reply.read(entryChanged);
631 }
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700632 catch (sdbusplus::exception_t &e)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700633 {
634 phosphor::logging::log<phosphor::logging::level::ERR>(
635 "Error send data info",
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700636 phosphor::logging::entry("ERROR=%s", e.what()),
Vernon Mauerya3702c12019-05-22 13:20:59 -0700637 phosphor::logging::entry("SERVICE=%s", service.c_str()),
638 phosphor::logging::entry("PATH=%s", mdrv2Path));
639 return IPMI_CC_RESPONSE_ERROR;
640 }
641
642 *data_len = 1;
643
644 if (entryChanged)
645 {
646 *(static_cast<uint8_t *>(response)) = 1;
647 }
648 else
649 {
650 *(static_cast<uint8_t *>(response)) = 0;
651 }
652
653 return IPMI_CC_OK;
654}
655
656ipmi_ret_t cmd_mdr2_get_data_block(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
657 ipmi_request_t request,
658 ipmi_response_t response,
659 ipmi_data_len_t data_len,
660 ipmi_context_t context)
661{
662 auto requestData =
663 reinterpret_cast<const MDRiiGetDataBlockRequest *>(request);
664 auto responseData = reinterpret_cast<MDRiiGetDataBlockResponse *>(response);
665 std::tuple<uint8_t, uint32_t, uint32_t, std::vector<uint8_t>> res;
666 std::vector<uint8_t> resData;
667 uint8_t status = 1;
668
669 if (*data_len != sizeof(MDRiiGetDataBlockRequest))
670 {
671 *data_len = 0;
672 return IPMI_CC_REQ_DATA_LEN_INVALID;
673 }
674
675 *data_len = 0;
676
Vernon Mauerya3702c12019-05-22 13:20:59 -0700677 if (mdrv2 == nullptr)
678 {
679 mdrv2 = std::make_unique<MDRV2>();
680 }
681
682 int agentIndex = mdrv2->agentLookup(requestData->agentId);
683 if (agentIndex == -1)
684 {
685 phosphor::logging::log<phosphor::logging::level::ERR>(
686 "Unknown agent id",
687 phosphor::logging::entry("ID=%x", requestData->agentId));
688 return IPMI_CC_PARM_OUT_OF_RANGE;
689 }
690
691 int idIndex = mdrv2->findLockHandle(requestData->lockHandle);
692
693 if ((idIndex < 0) || (idIndex >= maxDirEntries))
694 {
695 phosphor::logging::log<phosphor::logging::level::ERR>(
696 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
697 return IPMI_CC_PARM_OUT_OF_RANGE;
698 }
699
700 if (requestData->xferOffset >= mdrv2->smbiosDir.dir[idIndex].common.size)
701 {
702 phosphor::logging::log<phosphor::logging::level::ERR>(
703 "Offset is outside of range.");
704 return IPMI_CC_PARM_OUT_OF_RANGE;
705 }
706
707 size_t outSize =
708 (requestData->xferLength > mdrv2->smbiosDir.dir[idIndex].xferSize)
709 ? mdrv2->smbiosDir.dir[idIndex].xferSize
710 : requestData->xferLength;
711 if (outSize > UINT_MAX - requestData->xferOffset)
712 {
713 phosphor::logging::log<phosphor::logging::level::ERR>(
714 "Out size and offset are out of range");
715 return IPMI_CC_PARM_OUT_OF_RANGE;
716 }
717 if ((requestData->xferOffset + outSize) >
718 mdrv2->smbiosDir.dir[idIndex].common.size)
719 {
720 outSize =
721 mdrv2->smbiosDir.dir[idIndex].common.size - requestData->xferOffset;
722 }
723
724 responseData->xferLength = outSize;
725 if (responseData->xferLength > requestData->xferLength)
726 {
727 phosphor::logging::log<phosphor::logging::level::ERR>(
728 "Get data block unexpected error.");
729 return IPMI_CC_UNSPECIFIED_ERROR;
730 }
731
732 if ((requestData->xferOffset + outSize) >
733 UINT_MAX -
734 reinterpret_cast<size_t>(mdrv2->smbiosDir.dir[idIndex].dataStorage))
735 {
736 phosphor::logging::log<phosphor::logging::level::ERR>(
737 "Input data to calculate checksum is out of range");
738 return IPMI_CC_PARM_OUT_OF_RANGE;
739 }
740
741 uint32_t u32Checksum = mdrv2->calcChecksum32(
742 mdrv2->smbiosDir.dir[idIndex].dataStorage + requestData->xferOffset,
743 outSize);
744 if (u32Checksum == invalidChecksum)
745 {
746 phosphor::logging::log<phosphor::logging::level::ERR>(
747 "Get data block failed - invalid checksum");
748 return IPMI_CC_OEM_INVALID_CHECKSUM;
749 }
750 responseData->checksum = u32Checksum;
751
752 *data_len = sizeof(responseData->xferLength) +
753 sizeof(responseData->checksum) + outSize;
754
755 if (*data_len > MAX_IPMI_BUFFER) // length + completion code should no more
756 // than MAX_IPMI_BUFFER
757 {
758 phosphor::logging::log<phosphor::logging::level::ERR>(
759 "Data length send from service is invalid");
760 *data_len = 0;
761 return IPMI_CC_RESPONSE_ERROR;
762 }
763
764 std::copy(
765 &mdrv2->smbiosDir.dir[idIndex].dataStorage[requestData->xferOffset],
766 &mdrv2->smbiosDir.dir[idIndex]
767 .dataStorage[requestData->xferOffset + outSize],
768 responseData->data);
769
770 return IPMI_CC_OK;
771}
772
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000773/** @brief implements mdr2 send data block command
774 * @param agentId
775 * @param lockHandle
776 * @param xferOffset
777 * @param xferLength
778 * @param checksum
779 *
780 * @returns IPMI completion code
781 */
782ipmi::RspType<> mdr2SendDataBlock(uint16_t agentId, uint16_t lockHandle,
783 uint32_t xferOffset, uint32_t xferLength,
784 uint32_t checksum)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700785{
Vernon Mauerya3702c12019-05-22 13:20:59 -0700786 if (mdrv2 == nullptr)
787 {
788 mdrv2 = std::make_unique<MDRV2>();
789 }
790
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000791 int agentIndex = mdrv2->agentLookup(agentId);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700792 if (agentIndex == -1)
793 {
794 phosphor::logging::log<phosphor::logging::level::ERR>(
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000795 "Unknown agent id", phosphor::logging::entry("ID=%x", agentId));
796 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700797 }
798
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000799 int idIndex = mdrv2->findLockHandle(lockHandle);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700800
801 if ((idIndex < 0) || (idIndex >= maxDirEntries))
802 {
803 phosphor::logging::log<phosphor::logging::level::ERR>(
804 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000805 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700806 }
807
808 if (mdrv2->smbiosIsUpdating(idIndex))
809 {
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000810 if (xferOffset > UINT_MAX - xferLength)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700811 {
812 phosphor::logging::log<phosphor::logging::level::ERR>(
813 "Offset and length are out of range");
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000814 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700815 }
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000816 if (((xferOffset + xferLength) >
Vernon Mauerya3702c12019-05-22 13:20:59 -0700817 mdrv2->smbiosDir.dir[idIndex].maxDataSize) ||
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000818 ((xferOffset + xferLength) >
Vernon Mauerya3702c12019-05-22 13:20:59 -0700819 mdrv2->smbiosDir.dir[idIndex].common.dataSetSize))
820 {
821 phosphor::logging::log<phosphor::logging::level::ERR>(
822 "Send data block Invalid offset/length");
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000823 return ipmi::responseReqDataLenExceeded();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700824 }
825 if (reinterpret_cast<size_t>(
826 mdrv2->smbiosDir.dir[idIndex].dataStorage) >
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000827 UINT_MAX - xferOffset)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700828 {
829 phosphor::logging::log<phosphor::logging::level::ERR>(
830 "Offset is out of range");
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000831 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700832 }
833 uint8_t *destAddr =
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000834 mdrv2->smbiosDir.dir[idIndex].dataStorage + xferOffset;
Vernon Mauerya3702c12019-05-22 13:20:59 -0700835 uint8_t *sourceAddr = reinterpret_cast<uint8_t *>(mdrv2->area->vPtr);
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000836 uint32_t calcChecksum = mdrv2->calcChecksum32(sourceAddr, xferLength);
837 if (calcChecksum != checksum)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700838 {
839 phosphor::logging::log<phosphor::logging::level::ERR>(
840 "Send data block Invalid checksum");
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000841 return ipmi::response(ccOemInvalidChecksum);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700842 }
843 else
844 {
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000845 if (reinterpret_cast<size_t>(sourceAddr) > UINT_MAX - xferLength)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700846 {
847 phosphor::logging::log<phosphor::logging::level::ERR>(
848 "Length is out of range");
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000849 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700850 }
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000851 std::copy(sourceAddr, sourceAddr + xferLength, destAddr);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700852 }
853 }
854 else
855 {
856 phosphor::logging::log<phosphor::logging::level::ERR>(
857 "Send data block failed, other data is updating");
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000858 return ipmi::responseDestinationUnavailable();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700859 }
860
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000861 return ipmi::responseSuccess();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700862}
863
864bool MDRV2::storeDatatoFlash(MDRSMBIOSHeader *mdrHdr, uint8_t *data)
865{
866 std::ofstream smbiosFile(mdrType2File,
867 std::ios_base::binary | std::ios_base::trunc);
868 if (!smbiosFile.good())
869 {
870 phosphor::logging::log<phosphor::logging::level::ERR>(
871 "Write data from flash error - Open MDRV2 table file failure");
872 return false;
873 }
874
875 try
876 {
877 smbiosFile.write(reinterpret_cast<char *>(mdrHdr),
878 sizeof(MDRSMBIOSHeader));
879 smbiosFile.write(reinterpret_cast<char *>(data), mdrHdr->dataSize);
880 }
881 catch (std::ofstream::failure &e)
882 {
883 phosphor::logging::log<phosphor::logging::level::ERR>(
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700884 "Write data from flash error - write data error",
885 phosphor::logging::entry("ERROR=%s", e.what()));
Vernon Mauerya3702c12019-05-22 13:20:59 -0700886 return false;
887 }
888
889 return true;
890}
891
892void SharedMemoryArea::Initialize(uint32_t addr, uint32_t areaSize)
893{
894 int memDriver = 0;
895
896 // open mem driver for the system memory access
897 memDriver = open("/dev/vgasharedmem", O_RDONLY);
898 if (memDriver < 0)
899 {
900 phosphor::logging::log<phosphor::logging::level::ERR>(
901 "Cannot access mem driver");
902 throw std::system_error(EIO, std::generic_category());
903 }
904
905 // map the system memory
906 vPtr = mmap(NULL, // where to map to: don't mind
907 areaSize, // how many bytes ?
908 PROT_READ, // want to read and write
909 MAP_SHARED, // no copy on write
910 memDriver, // handle to /dev/mem
911 (physicalAddr & pageMask)); // hopefully the Text-buffer :-)
912
913 close(memDriver);
914 if (vPtr == MAP_FAILED)
915 {
916 phosphor::logging::log<phosphor::logging::level::ERR>(
917 "Failed to map share memory");
918 throw std::system_error(EIO, std::generic_category());
919 }
920 size = areaSize;
921 physicalAddr = addr;
922}
923
924bool MDRV2::smbiosUnlock(uint8_t index)
925{
926 bool ret;
927 switch (smbiosDir.dir[index].stage)
928 {
929 case MDR2SMBIOSStatusEnum::mdr2Updating:
930 smbiosDir.dir[index].stage = MDR2SMBIOSStatusEnum::mdr2Updated;
931 smbiosDir.dir[index].lock = MDR2DirLockEnum::mdr2DirUnlock;
932
933 timer->stop();
934 smbiosDir.dir[index].lockHandle = 0;
935 ret = true;
936 break;
937
938 case MDR2SMBIOSStatusEnum::mdr2Updated:
939 case MDR2SMBIOSStatusEnum::mdr2Loaded:
940 smbiosDir.dir[index].lock = MDR2DirLockEnum::mdr2DirUnlock;
941
942 timer->stop();
943
944 smbiosDir.dir[index].lockHandle = 0;
945 ret = true;
946 break;
947
948 default:
949 break;
950 }
951
952 return ret;
953}
954
955bool MDRV2::smbiosTryLock(uint8_t flag, uint8_t index, uint16_t *session,
956 uint16_t timeout)
957{
958 bool ret = false;
959 uint32_t u32Status = 0;
960
961 if (timeout == 0)
962 {
963 timeout = defaultTimeout;
964 }
965 std::chrono::microseconds usec(timeout * sysClock);
966
967 switch (smbiosDir.dir[index].stage)
968 {
969 case MDR2SMBIOSStatusEnum::mdr2Updating:
970 if (smbiosDir.dir[index].lock != MDR2DirLockEnum::mdr2DirLock)
971 {
972 smbiosDir.dir[index].lock = MDR2DirLockEnum::mdr2DirLock;
973 timer->start(usec);
974 lockIndex = index;
975
976 *session = getSessionHandle(&smbiosDir);
977 smbiosDir.dir[index].lockHandle = *session;
978 ret = true;
979 }
980 break;
981 case MDR2SMBIOSStatusEnum::mdr2Init:
982 if (flag)
983 {
984 smbiosDir.dir[index].stage = MDR2SMBIOSStatusEnum::mdr2Updating;
985 smbiosDir.dir[index].lock = MDR2DirLockEnum::mdr2DirUnlock;
986 timer->start(usec);
987 lockIndex = index;
988
989 *session = getSessionHandle(&smbiosDir);
990 smbiosDir.dir[index].lockHandle = *session;
991 ret = true;
992 }
993 break;
994
995 case MDR2SMBIOSStatusEnum::mdr2Updated:
996 case MDR2SMBIOSStatusEnum::mdr2Loaded:
997 if (smbiosDir.dir[index].lock != MDR2DirLockEnum::mdr2DirLock)
998 {
999 if (flag)
1000 {
1001 smbiosDir.dir[index].stage =
1002 MDR2SMBIOSStatusEnum::mdr2Updating;
1003 smbiosDir.dir[index].lock = MDR2DirLockEnum::mdr2DirUnlock;
1004 }
1005 else
1006 {
1007 smbiosDir.dir[index].lock = MDR2DirLockEnum::mdr2DirLock;
1008 }
1009
1010 timer->start(usec);
1011 lockIndex = index;
1012
1013 *session = getSessionHandle(&smbiosDir);
1014 smbiosDir.dir[index].lockHandle = *session;
1015 ret = true;
1016 }
1017 break;
1018
1019 default:
1020 break;
1021 }
1022 return ret;
1023}
1024
1025void MDRV2::timeoutHandler()
1026{
1027 smbiosUnlock(lockIndex);
1028 mdrv2->area.reset(nullptr);
1029}
1030
1031ipmi_ret_t cmd_mdr2_lock_data(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1032 ipmi_request_t request, ipmi_response_t response,
1033 ipmi_data_len_t data_len, ipmi_context_t context)
1034{
1035 auto requestData = reinterpret_cast<const MDRiiLockDataRequest *>(request);
1036 auto responseData = reinterpret_cast<MDRiiLockDataResponse *>(response);
1037 uint16_t session = 0;
1038
1039 std::tuple<bool, uint8_t, uint16_t, uint32_t, uint32_t, uint32_t> res;
1040
1041 if (*data_len < sizeof(MDRiiLockDataRequest))
1042 {
1043 *data_len = 0;
1044 return IPMI_CC_REQ_DATA_LEN_INVALID;
1045 }
1046
1047 *data_len = 0;
1048
1049 if (mdrv2 == nullptr)
1050 {
1051 mdrv2 = std::make_unique<MDRV2>();
1052 }
1053
1054 int agentIndex = mdrv2->agentLookup(requestData->agentId);
1055 if (agentIndex == -1)
1056 {
1057 phosphor::logging::log<phosphor::logging::level::ERR>(
1058 "Unknown agent id",
1059 phosphor::logging::entry("ID=%x", requestData->agentId));
1060 return IPMI_CC_PARM_OUT_OF_RANGE;
1061 }
1062
Vernon Mauery15419dd2019-05-24 09:40:30 -07001063 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
1064 std::string service = ipmi::getService(*bus, mdrv2Interface, mdrv2Path);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001065
1066 int idIndex =
1067 mdrv2->findDataId(requestData->dataSetInfo.dataInfo,
1068 sizeof(requestData->dataSetInfo.dataInfo), service);
1069
1070 if ((idIndex < 0) || (idIndex >= maxDirEntries))
1071 {
1072 phosphor::logging::log<phosphor::logging::level::ERR>(
1073 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
1074 return IPMI_CC_PARM_OUT_OF_RANGE;
1075 }
1076
1077 if (!mdrv2->smbiosTryLock(0, idIndex, &session, requestData->timeout))
1078 {
1079 phosphor::logging::log<phosphor::logging::level::ERR>(
1080 "Lock Data failed - cannot lock idIndex");
1081 return IPMI_CC_PARAMETER_NOT_SUPPORT_IN_PRESENT_STATE;
1082 }
1083
1084 *data_len = sizeof(MDRiiLockDataResponse);
1085
1086 responseData->mdrVersion = mdr2Version;
1087 responseData->lockHandle = session;
1088 responseData->dataLength = mdrv2->smbiosDir.dir[idIndex].common.size;
1089 responseData->xferAddress = mdrv2->smbiosDir.dir[idIndex].xferBuff;
1090 responseData->xferLength = mdrv2->smbiosDir.dir[idIndex].xferSize;
1091
1092 return IPMI_CC_OK;
1093}
1094
1095ipmi_ret_t cmd_mdr2_unlock_data(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1096 ipmi_request_t request,
1097 ipmi_response_t response,
1098 ipmi_data_len_t data_len,
1099 ipmi_context_t context)
1100{
1101 phosphor::logging::log<phosphor::logging::level::ERR>("unlock data");
1102 auto requestData =
1103 reinterpret_cast<const MDRiiUnlockDataRequest *>(request);
1104
1105 if (*data_len != sizeof(MDRiiUnlockDataRequest))
1106 {
1107 *data_len = 0;
1108 return IPMI_CC_REQ_DATA_LEN_INVALID;
1109 }
1110
1111 *data_len = 0;
1112
Vernon Mauerya3702c12019-05-22 13:20:59 -07001113 if (mdrv2 == nullptr)
1114 {
1115 mdrv2 = std::make_unique<MDRV2>();
1116 }
1117
1118 int agentIndex = mdrv2->agentLookup(requestData->agentId);
1119 if (agentIndex == -1)
1120 {
1121 phosphor::logging::log<phosphor::logging::level::ERR>(
1122 "Unknown agent id",
1123 phosphor::logging::entry("ID=%x", requestData->agentId));
1124 return IPMI_CC_PARM_OUT_OF_RANGE;
1125 }
1126
1127 int idIndex = mdrv2->findLockHandle(requestData->lockHandle);
1128
1129 if ((idIndex < 0) || (idIndex >= maxDirEntries))
1130 {
1131 phosphor::logging::log<phosphor::logging::level::ERR>(
1132 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
1133 return IPMI_CC_PARM_OUT_OF_RANGE;
1134 }
1135
1136 if (!mdrv2->smbiosUnlock(idIndex))
1137 {
1138 phosphor::logging::log<phosphor::logging::level::ERR>(
1139 "Unlock Data failed - cannot unlock idIndex");
1140 return IPMI_CC_PARAMETER_NOT_SUPPORT_IN_PRESENT_STATE;
1141 }
1142
1143 return IPMI_CC_OK;
1144}
1145
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001146/**
1147@brief This command is executed after POST BIOS to get the session info.
1148
1149@param - agentId, dataInfo, dataLength, xferAddress, xferLength, timeout.
1150
1151@return xferStartAck and session on success.
1152**/
1153ipmi::RspType<uint8_t, uint16_t>
1154 cmd_mdr2_data_start(uint16_t agentId, std::array<uint8_t, 16> dataInfo,
1155 uint32_t dataLength, uint32_t xferAddress,
1156 uint32_t xferLength, uint16_t timeout)
Vernon Mauerya3702c12019-05-22 13:20:59 -07001157{
Vernon Mauerya3702c12019-05-22 13:20:59 -07001158 uint16_t session = 0;
1159
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001160 if (dataLength > smbiosTableStorageSize)
Vernon Mauerya3702c12019-05-22 13:20:59 -07001161 {
1162 phosphor::logging::log<phosphor::logging::level::ERR>(
1163 "Requested data length is out of SMBIOS Table storage size.");
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001164 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001165 }
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001166 if ((xferLength + xferAddress) > mdriiSMSize)
Vernon Mauerya3702c12019-05-22 13:20:59 -07001167 {
1168 phosphor::logging::log<phosphor::logging::level::ERR>(
1169 "Invalid data address and size");
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001170 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001171 }
1172
Vernon Mauery15419dd2019-05-24 09:40:30 -07001173 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
1174 std::string service = ipmi::getService(*bus, mdrv2Interface, mdrv2Path);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001175
1176 if (mdrv2 == nullptr)
1177 {
1178 mdrv2 = std::make_unique<MDRV2>();
1179 }
1180
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001181 int agentIndex = mdrv2->agentLookup(agentId);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001182 if (agentIndex == -1)
1183 {
1184 phosphor::logging::log<phosphor::logging::level::ERR>(
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001185 "Unknown agent id", phosphor::logging::entry("ID=%x", agentId));
1186 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001187 }
1188
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001189 int idIndex = mdrv2->findDataId(dataInfo.data(), sizeof(dataInfo), service);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001190
1191 if ((idIndex < 0) || (idIndex >= maxDirEntries))
1192 {
1193 phosphor::logging::log<phosphor::logging::level::ERR>(
1194 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001195 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001196 }
1197
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001198 if (mdrv2->smbiosTryLock(1, idIndex, &session, timeout))
Vernon Mauerya3702c12019-05-22 13:20:59 -07001199 {
1200 try
1201 {
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001202 mdrv2->area =
1203 std::make_unique<SharedMemoryArea>(xferAddress, xferLength);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001204 }
1205 catch (const std::system_error &e)
1206 {
1207 mdrv2->smbiosUnlock(idIndex);
1208 phosphor::logging::log<phosphor::logging::level::ERR>(
Vernon Maueryc7d517e2019-06-18 14:27:00 -07001209 "Unable to access share memory",
1210 phosphor::logging::entry("ERROR=%s", e.what()));
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001211 return ipmi::responseUnspecifiedError();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001212 }
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001213 mdrv2->smbiosDir.dir[idIndex].common.size = dataLength;
Vernon Mauerya3702c12019-05-22 13:20:59 -07001214 mdrv2->smbiosDir.dir[idIndex].lockHandle = session;
1215 if (-1 ==
1216 mdrv2->syncDirCommonData(
1217 idIndex, mdrv2->smbiosDir.dir[idIndex].common.size, service))
1218 {
1219 phosphor::logging::log<phosphor::logging::level::ERR>(
1220 "Unable to sync data to service");
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001221 return ipmi::responseResponseError();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001222 }
1223 }
1224 else
1225 {
1226 phosphor::logging::log<phosphor::logging::level::ERR>(
1227 "Canot lock smbios");
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001228 return ipmi::responseUnspecifiedError();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001229 }
1230
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001231 static constexpr uint8_t xferStartAck = 1;
Vernon Mauerya3702c12019-05-22 13:20:59 -07001232
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001233 return ipmi::responseSuccess(xferStartAck, session);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001234}
1235
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001236/**
1237@brief This command is executed to close the session.
1238
1239@param - agentId, lockHandle.
1240
1241@return completion code on success.
1242**/
1243ipmi::RspType<> cmd_mdr2_data_done(uint16_t agentId, uint16_t lockHandle)
Vernon Mauerya3702c12019-05-22 13:20:59 -07001244{
Vernon Mauerya3702c12019-05-22 13:20:59 -07001245
1246 if (mdrv2 == nullptr)
1247 {
1248 mdrv2 = std::make_unique<MDRV2>();
1249 }
1250
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001251 int agentIndex = mdrv2->agentLookup(agentId);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001252 if (agentIndex == -1)
1253 {
1254 phosphor::logging::log<phosphor::logging::level::ERR>(
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001255 "Unknown agent id", phosphor::logging::entry("ID=%x", agentId));
1256 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001257 }
1258
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001259 int idIndex = mdrv2->findLockHandle(lockHandle);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001260
1261 if ((idIndex < 0) || (idIndex >= maxDirEntries))
1262 {
1263 phosphor::logging::log<phosphor::logging::level::ERR>(
1264 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001265 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001266 }
1267
1268 if (!mdrv2->smbiosUnlock(idIndex))
1269 {
1270 phosphor::logging::log<phosphor::logging::level::ERR>(
1271 "Send data done failed - cannot unlock idIndex");
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001272 return ipmi::responseDestinationUnavailable();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001273 }
1274
1275 mdrv2->area.reset(nullptr);
1276 MDRSMBIOSHeader mdr2Smbios;
1277 mdr2Smbios.mdrType = mdrTypeII;
1278 mdr2Smbios.dirVer = mdrv2->smbiosDir.dir[0].common.dataVersion;
1279 mdr2Smbios.timestamp = mdrv2->smbiosDir.dir[0].common.timestamp;
1280 mdr2Smbios.dataSize = mdrv2->smbiosDir.dir[0].common.size;
1281
1282 if (access(smbiosPath, 0) == -1)
1283 {
1284 int flag = mkdir(smbiosPath, S_IRWXU);
1285 if (flag != 0)
1286 {
1287 phosphor::logging::log<phosphor::logging::level::ERR>(
1288 "create folder failed for writting smbios file");
1289 }
1290 }
1291 if (!mdrv2->storeDatatoFlash(
1292 &mdr2Smbios, mdrv2->smbiosDir.dir[smbiosDirIndex].dataStorage))
1293 {
1294 phosphor::logging::log<phosphor::logging::level::ERR>(
1295 "MDR2 Store data to flash failed");
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001296 return ipmi::responseDestinationUnavailable();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001297 }
Vernon Mauerya3702c12019-05-22 13:20:59 -07001298 bool status = false;
Vernon Mauery15419dd2019-05-24 09:40:30 -07001299 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
1300 std::string service = ipmi::getService(*bus, mdrv2Interface, mdrv2Path);
1301 sdbusplus::message::message method = bus->new_method_call(
Vernon Mauerya3702c12019-05-22 13:20:59 -07001302 service.c_str(), mdrv2Path, mdrv2Interface, "AgentSynchronizeData");
1303
1304 try
1305 {
Vernon Mauery15419dd2019-05-24 09:40:30 -07001306 sdbusplus::message::message reply = bus->call(method);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001307 reply.read(status);
1308 }
Vernon Maueryc7d517e2019-06-18 14:27:00 -07001309 catch (sdbusplus::exception_t &e)
Vernon Mauerya3702c12019-05-22 13:20:59 -07001310 {
1311 phosphor::logging::log<phosphor::logging::level::ERR>(
1312 "Error Sync data with service",
Vernon Maueryc7d517e2019-06-18 14:27:00 -07001313 phosphor::logging::entry("ERROR=%s", e.what()),
Vernon Mauerya3702c12019-05-22 13:20:59 -07001314 phosphor::logging::entry("SERVICE=%s", service.c_str()),
1315 phosphor::logging::entry("PATH=%s", mdrv2Path));
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001316 return ipmi::responseResponseError();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001317 }
1318
1319 if (!status)
1320 {
1321 phosphor::logging::log<phosphor::logging::level::ERR>(
1322 "Sync data with service failure");
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001323 return ipmi::responseUnspecifiedError();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001324 }
1325
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001326 return ipmi::responseSuccess();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001327}
1328
1329static void register_netfn_smbiosmdrv2_functions(void)
1330{
1331 // MDR V2 Command
1332 // <Get MDRII Status Command>
jayaprakash Mutyala853d8292019-05-31 18:17:42 +00001333 ipmi::registerHandler(ipmi::prioOemBase, NETFUN_INTEL_APP_OEM,
1334 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_AGENT_STATUS,
1335 ipmi::Privilege::Operator, mdr2AgentStatus);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001336
1337 // <Get MDRII Directory Command>
1338 ipmi_register_callback(NETFUN_INTEL_APP_OEM,
1339 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_GET_DIR, NULL,
1340 cmd_mdr2_get_dir, PRIVILEGE_OPERATOR);
1341
1342 // <Send MDRII Directory Command>
1343 ipmi_register_callback(NETFUN_INTEL_APP_OEM,
1344 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_SEND_DIR, NULL,
1345 cmd_mdr2_send_dir, PRIVILEGE_OPERATOR);
1346
1347 // <Get MDRII Data Info Command>
1348 ipmi_register_callback(NETFUN_INTEL_APP_OEM,
1349 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_GET_DATA_INFO,
1350 NULL, cmd_mdr2_get_data_info, PRIVILEGE_OPERATOR);
1351
1352 // <Send MDRII Info Offer>
jayaprakash Mutyala853d8292019-05-31 18:17:42 +00001353 ipmi::registerHandler(
1354 ipmi::prioOemBase, NETFUN_INTEL_APP_OEM,
1355 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_SEND_DATA_INFO_OFFER,
1356 ipmi::Privilege::Operator, mdr2DataInfoOffer);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001357
1358 // <Send MDRII Data Info>
1359 ipmi_register_callback(NETFUN_INTEL_APP_OEM,
1360 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_SEND_DATA_INFO,
1361 NULL, cmd_mdr2_send_data_info, PRIVILEGE_OPERATOR);
1362
1363 // <Get MDRII Data Block Command>
1364 ipmi_register_callback(NETFUN_INTEL_APP_OEM,
1365 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_GET_DATA_BLOCK,
1366 NULL, cmd_mdr2_get_data_block, PRIVILEGE_OPERATOR);
1367
1368 // <Send MDRII Data Block>
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +00001369 ipmi::registerHandler(ipmi::prioOemBase, NETFUN_INTEL_APP_OEM,
1370 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_SEND_DATA_BLOCK,
1371 ipmi::Privilege::Operator, mdr2SendDataBlock);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001372
1373 // <Lock MDRII Data Command>
1374 ipmi_register_callback(NETFUN_INTEL_APP_OEM,
1375 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_LOCK_DATA, NULL,
1376 cmd_mdr2_lock_data, PRIVILEGE_OPERATOR);
1377
1378 // <Unlock MDRII Data Command>
1379 ipmi_register_callback(NETFUN_INTEL_APP_OEM,
1380 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_UNLOCK_DATA,
1381 NULL, cmd_mdr2_unlock_data, PRIVILEGE_OPERATOR);
1382
1383 // <Send MDRII Data Start>
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001384 ipmi::registerHandler(ipmi::prioOemBase, NETFUN_INTEL_APP_OEM,
1385 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_DATA_START,
1386 ipmi::Privilege::Operator, cmd_mdr2_data_start);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001387
1388 // <Send MDRII Data Done>
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001389 ipmi::registerHandler(ipmi::prioOemBase, NETFUN_INTEL_APP_OEM,
1390 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_DATA_DONE,
1391 ipmi::Privilege::Operator, cmd_mdr2_data_done);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001392}