blob: 9e5be61a8db302189be5c6867d22a662e0319778 [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;
jayaprakash Mutyala40fec612019-06-19 11:53:03 +000038static constexpr size_t dataInfoSize = 16;
Vernon Mauerya3702c12019-05-22 13:20:59 -070039
Vernon Mauerya3702c12019-05-22 13:20:59 -070040static void register_netfn_smbiosmdrv2_functions() __attribute__((constructor));
Vernon Mauerya3702c12019-05-22 13:20:59 -070041
42int MDRV2::agentLookup(const uint16_t &agentId)
43{
44 int agentIndex = -1;
45
46 if (lastAgentId == agentId)
47 {
48 return lastAgentIndex;
49 }
50
51 if (agentId == smbiosAgentId)
52 {
53 return firstAgentIndex;
54 }
55
56 return agentIndex;
57}
58
59int MDRV2::sdplusMdrv2GetProperty(const std::string &name,
60 sdbusplus::message::variant<uint8_t> &value,
61 const std::string &service)
62{
Vernon Mauery15419dd2019-05-24 09:40:30 -070063 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
Vernon Mauerya3702c12019-05-22 13:20:59 -070064 sdbusplus::message::message method =
Vernon Mauery15419dd2019-05-24 09:40:30 -070065 bus->new_method_call(service.c_str(), mdrv2Path, dbusProperties, "Get");
Vernon Mauerya3702c12019-05-22 13:20:59 -070066 method.append(mdrv2Interface, name);
67
Vernon Mauery15419dd2019-05-24 09:40:30 -070068 sdbusplus::message::message reply = bus->call(method);
Vernon Mauerya3702c12019-05-22 13:20:59 -070069
70 try
71 {
Vernon Mauery15419dd2019-05-24 09:40:30 -070072 sdbusplus::message::message reply = bus->call(method);
Vernon Mauerya3702c12019-05-22 13:20:59 -070073 reply.read(value);
74 }
Vernon Maueryc7d517e2019-06-18 14:27:00 -070075 catch (sdbusplus::exception_t &e)
Vernon Mauerya3702c12019-05-22 13:20:59 -070076 {
77 phosphor::logging::log<phosphor::logging::level::ERR>(
Vernon Maueryc7d517e2019-06-18 14:27:00 -070078 "Error get property, sdbusplus call failed",
79 phosphor::logging::entry("ERROR=%s", e.what()));
Vernon Mauerya3702c12019-05-22 13:20:59 -070080 return -1;
81 }
82
83 return 0;
84}
85
86int MDRV2::syncDirCommonData(uint8_t idIndex, uint32_t size,
87 const std::string &service)
88{
89 std::vector<uint32_t> commonData;
Vernon Mauery15419dd2019-05-24 09:40:30 -070090 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
Vernon Mauerya3702c12019-05-22 13:20:59 -070091 sdbusplus::message::message method =
Vernon Mauery15419dd2019-05-24 09:40:30 -070092 bus->new_method_call(service.c_str(), mdrv2Path, mdrv2Interface,
93 "SynchronizeDirectoryCommonData");
Vernon Mauerya3702c12019-05-22 13:20:59 -070094 method.append(idIndex, size);
95
96 try
97 {
Vernon Mauery15419dd2019-05-24 09:40:30 -070098 sdbusplus::message::message reply = bus->call(method);
Vernon Mauerya3702c12019-05-22 13:20:59 -070099 reply.read(commonData);
100 }
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700101 catch (sdbusplus::exception_t &e)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700102 {
103 phosphor::logging::log<phosphor::logging::level::ERR>(
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700104 "Error sync dir common data with service",
105 phosphor::logging::entry("ERROR=%s", e.what()));
Vernon Mauerya3702c12019-05-22 13:20:59 -0700106 return -1;
107 }
108
109 if (commonData.size() < syncDirCommonSize)
110 {
111 phosphor::logging::log<phosphor::logging::level::ERR>(
112 "Error sync dir common data - data length invalid");
113 return -1;
114 }
115 smbiosDir.dir[idIndex].common.dataSetSize = commonData.at(0);
116 smbiosDir.dir[idIndex].common.dataVersion = commonData.at(1);
117 smbiosDir.dir[idIndex].common.timestamp = commonData.at(2);
118
119 return 0;
120}
121
122int MDRV2::findDataId(const uint8_t *dataInfo, const size_t &len,
123 const std::string &service)
124{
125 int idIndex = -1;
126
127 if (dataInfo == nullptr)
128 {
129 phosphor::logging::log<phosphor::logging::level::ERR>(
130 "Error dataInfo, input is null point");
131 return -1;
132 }
133
Vernon Mauery15419dd2019-05-24 09:40:30 -0700134 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
135 sdbusplus::message::message method = bus->new_method_call(
Vernon Mauerya3702c12019-05-22 13:20:59 -0700136 service.c_str(), mdrv2Path, mdrv2Interface, "FindIdIndex");
137 std::vector<uint8_t> info;
138 info.resize(len);
139 std::copy(dataInfo, dataInfo + len, info.data());
140 method.append(info);
141
142 try
143 {
Vernon Mauery15419dd2019-05-24 09:40:30 -0700144 sdbusplus::message::message reply = bus->call(method);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700145 reply.read(idIndex);
146 }
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700147 catch (sdbusplus::exception_t &e)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700148 {
149 phosphor::logging::log<phosphor::logging::level::ERR>(
150 "Error find id index",
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700151 phosphor::logging::entry("ERROR=%s", e.what()),
Vernon Mauerya3702c12019-05-22 13:20:59 -0700152 phosphor::logging::entry("SERVICE=%s", service.c_str()),
153 phosphor::logging::entry("PATH=%s", mdrv2Path));
154 return -1;
155 }
156
157 return idIndex;
158}
159
160uint16_t MDRV2::getSessionHandle(Mdr2DirStruct *dir)
161{
162 if (dir == NULL)
163 {
164 phosphor::logging::log<phosphor::logging::level::ERR>(
165 "Empty dir point");
166 return 0;
167 }
168 dir->sessionHandle++;
169 if (dir->sessionHandle == 0)
170 {
171 dir->sessionHandle = 1;
172 }
173
174 return dir->sessionHandle;
175}
176
177int MDRV2::findLockHandle(const uint16_t &lockHandle)
178{
179 int idIndex = -1;
180
181 for (int index = 0; index < smbiosDir.dirEntries; index++)
182 {
183 if (lockHandle == smbiosDir.dir[index].lockHandle)
184 {
185 return index;
186 }
187 }
188
189 return idIndex;
190}
191
192bool MDRV2::smbiosIsUpdating(uint8_t index)
193{
194 if (index > maxDirEntries)
195 {
196 return false;
197 }
198 if (smbiosDir.dir[index].stage == MDR2SMBIOSStatusEnum::mdr2Updating)
199 {
200 return true;
201 }
202
203 return false;
204}
205
206uint32_t MDRV2::calcChecksum32(uint8_t *buf, uint32_t len)
207{
208 uint32_t sum = 0;
209
210 if (buf == nullptr)
211 {
212 return invalidChecksum;
213 }
214
215 for (uint32_t index = 0; index < len; index++)
216 {
217 sum += buf[index];
218 }
219
220 return sum;
221}
222
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000223/** @brief implements mdr2 agent status command
224 * @param agentId
225 * @param dirVersion
226 *
227 * @returns IPMI completion code plus response data
228 * - mdrVersion
229 * - agentVersion
230 * - dirVersion
231 * - dirEntries
232 * - dataRequest
233 */
234ipmi::RspType<uint8_t, uint8_t, uint8_t, uint8_t, uint8_t>
235 mdr2AgentStatus(uint16_t agentId, uint8_t dirVersion)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700236{
Vernon Mauerya3702c12019-05-22 13:20:59 -0700237 if (mdrv2 == nullptr)
238 {
239 mdrv2 = std::make_unique<MDRV2>();
240 }
241
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000242 int agentIndex = mdrv2->agentLookup(agentId);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700243 if (agentIndex == -1)
244 {
245 phosphor::logging::log<phosphor::logging::level::ERR>(
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000246 "Unknown agent id", phosphor::logging::entry("ID=%x", agentId));
247 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700248 }
249
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000250 constexpr uint8_t mdrVersion = mdr2Version;
251 constexpr uint8_t agentVersion = smbiosAgentVersion;
252 uint8_t dirVersionResp = mdrv2->smbiosDir.dirVersion;
253 uint8_t dirEntries = mdrv2->smbiosDir.dirEntries;
254 uint8_t dataRequest;
Vernon Mauerya3702c12019-05-22 13:20:59 -0700255
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000256 if (mdrv2->smbiosDir.remoteDirVersion != dirVersion)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700257 {
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000258 mdrv2->smbiosDir.remoteDirVersion = dirVersion;
259 dataRequest =
Vernon Mauerya3702c12019-05-22 13:20:59 -0700260 static_cast<uint8_t>(DirDataRequestEnum::dirDataRequested);
261 }
262 else
263 {
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000264 dataRequest =
Vernon Mauerya3702c12019-05-22 13:20:59 -0700265 static_cast<uint8_t>(DirDataRequestEnum::dirDataNotRequested);
266 }
267
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000268 return ipmi::responseSuccess(mdrVersion, agentVersion, dirVersionResp,
269 dirEntries, dataRequest);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700270}
271
jayaprakash Mutyaladad548b2019-06-12 15:29:39 +0000272/** @brief implements mdr2 get directory command
273 * @param agentId
274 * @param dirIndex
275 * @returns IPMI completion code plus response data
276 * - dataOut
277 */
278ipmi::RspType<std::vector<uint8_t>> mdr2GetDir(uint16_t agentId,
279 uint8_t dirIndex)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700280{
Vernon Mauery15419dd2019-05-24 09:40:30 -0700281 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
282 std::string service = ipmi::getService(*bus, mdrv2Interface, mdrv2Path);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700283
284 if (mdrv2 == nullptr)
285 {
286 mdrv2 = std::make_unique<MDRV2>();
287 }
288
jayaprakash Mutyaladad548b2019-06-12 15:29:39 +0000289 int agentIndex = mdrv2->agentLookup(agentId);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700290 if (agentIndex == -1)
291 {
292 phosphor::logging::log<phosphor::logging::level::ERR>(
jayaprakash Mutyaladad548b2019-06-12 15:29:39 +0000293 "Unknown agent id", phosphor::logging::entry("ID=%x", agentId));
294 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700295 }
296
jayaprakash Mutyaladad548b2019-06-12 15:29:39 +0000297 std::variant<uint8_t> value = 0;
Vernon Mauerya3702c12019-05-22 13:20:59 -0700298 if (0 != mdrv2->sdplusMdrv2GetProperty("DirectoryEntries", value, service))
299 {
300 phosphor::logging::log<phosphor::logging::level::ERR>(
301 "Error getting DirEnries");
jayaprakash Mutyaladad548b2019-06-12 15:29:39 +0000302 return ipmi::responseUnspecifiedError();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700303 }
jayaprakash Mutyaladad548b2019-06-12 15:29:39 +0000304 if (dirIndex > std::get<uint8_t>(value))
Vernon Mauerya3702c12019-05-22 13:20:59 -0700305 {
jayaprakash Mutyaladad548b2019-06-12 15:29:39 +0000306 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700307 }
308
Vernon Mauery15419dd2019-05-24 09:40:30 -0700309 sdbusplus::message::message method = bus->new_method_call(
Vernon Mauerya3702c12019-05-22 13:20:59 -0700310 service.c_str(), mdrv2Path, mdrv2Interface, "GetDirectoryInformation");
311
jayaprakash Mutyaladad548b2019-06-12 15:29:39 +0000312 method.append(dirIndex);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700313
jayaprakash Mutyaladad548b2019-06-12 15:29:39 +0000314 std::vector<uint8_t> dataOut;
Vernon Mauerya3702c12019-05-22 13:20:59 -0700315 try
316 {
Vernon Mauery15419dd2019-05-24 09:40:30 -0700317 sdbusplus::message::message reply = bus->call(method);
jayaprakash Mutyaladad548b2019-06-12 15:29:39 +0000318 reply.read(dataOut);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700319 }
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700320 catch (sdbusplus::exception_t &e)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700321 {
322 phosphor::logging::log<phosphor::logging::level::ERR>(
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700323 "Error get dir", phosphor::logging::entry("ERROR=%s", e.what()),
Vernon Mauerya3702c12019-05-22 13:20:59 -0700324 phosphor::logging::entry("SERVICE=%s", service.c_str()),
325 phosphor::logging::entry("PATH=%s", mdrv2Path));
jayaprakash Mutyaladad548b2019-06-12 15:29:39 +0000326 return ipmi::responseResponseError();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700327 }
328
jayaprakash Mutyaladad548b2019-06-12 15:29:39 +0000329 constexpr size_t getDirRespSize = 6;
330 if (dataOut.size() < getDirRespSize)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700331 {
332 phosphor::logging::log<phosphor::logging::level::ERR>(
333 "Error get dir, response length invalid");
jayaprakash Mutyaladad548b2019-06-12 15:29:39 +0000334 return ipmi::responseUnspecifiedError();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700335 }
336
jayaprakash Mutyaladad548b2019-06-12 15:29:39 +0000337 if (dataOut.size() > MAX_IPMI_BUFFER) // length + completion code should no
338 // more than MAX_IPMI_BUFFER
Vernon Mauerya3702c12019-05-22 13:20:59 -0700339 {
340 phosphor::logging::log<phosphor::logging::level::ERR>(
341 "Data length send from service is invalid");
jayaprakash Mutyaladad548b2019-06-12 15:29:39 +0000342 return ipmi::responseResponseError();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700343 }
344
jayaprakash Mutyaladad548b2019-06-12 15:29:39 +0000345 return ipmi::responseSuccess(dataOut);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700346}
347
348ipmi_ret_t cmd_mdr2_send_dir(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
349 ipmi_request_t request, ipmi_response_t response,
350 ipmi_data_len_t data_len, ipmi_context_t context)
351{
352 auto requestData = reinterpret_cast<const MDRiiSendDirRequest *>(request);
353 std::vector<uint8_t> idVector;
354 bool teminate = false;
355
356 if (*data_len != sizeof(MDRiiSendDirRequest))
357 {
358 *data_len = 0;
359 return IPMI_CC_REQ_DATA_LEN_INVALID;
360 }
361
362 *data_len = 0;
363
Vernon Mauery15419dd2019-05-24 09:40:30 -0700364 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
365 std::string service = ipmi::getService(*bus, mdrv2Interface, mdrv2Path);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700366
367 if (mdrv2 == nullptr)
368 {
369 mdrv2 = std::make_unique<MDRV2>();
370 }
371
372 int agentIndex = mdrv2->agentLookup(requestData->agentId);
373 if (agentIndex == -1)
374 {
375 phosphor::logging::log<phosphor::logging::level::ERR>(
376 "Unknown agent id",
377 phosphor::logging::entry("ID=%x", requestData->agentId));
378 return IPMI_CC_PARM_OUT_OF_RANGE;
379 }
380
381 if ((requestData->dirIndex + requestData->returnedEntries) > maxDirEntries)
382 {
383 phosphor::logging::log<phosphor::logging::level::ERR>(
384 "Too many directory entries");
385 return IPMI_CC_STORGE_LEAK;
386 }
387
Vernon Mauery15419dd2019-05-24 09:40:30 -0700388 sdbusplus::message::message method = bus->new_method_call(
Vernon Mauerya3702c12019-05-22 13:20:59 -0700389 service.c_str(), mdrv2Path, mdrv2Interface, "SendDirectoryInformation");
390 method.append(requestData->dirVersion, requestData->dirIndex,
391 requestData->returnedEntries, requestData->remainingEntries);
392 uint8_t *reqPoint;
393 for (int index = 0; index < requestData->returnedEntries; index++)
394 {
395 reqPoint = (uint8_t *)&(requestData->data[index]);
396 std::copy(reqPoint, sizeof(Mdr2DirEntry) + reqPoint, idVector.data());
397 }
398 method.append(idVector);
399
400 try
401 {
Vernon Mauery15419dd2019-05-24 09:40:30 -0700402 sdbusplus::message::message reply = bus->call(method);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700403 reply.read(teminate);
404 }
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700405 catch (sdbusplus::exception_t &e)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700406 {
407 phosphor::logging::log<phosphor::logging::level::ERR>(
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700408 "Error send dir", phosphor::logging::entry("ERROR=%s", e.what()),
Vernon Mauerya3702c12019-05-22 13:20:59 -0700409 phosphor::logging::entry("SERVICE=%s", service.c_str()),
410 phosphor::logging::entry("PATH=%s", mdrv2Path));
411 return IPMI_CC_RESPONSE_ERROR;
412 }
413
414 *data_len = 1;
415 if (teminate == false)
416 *(static_cast<uint8_t *>(response)) = 0;
417 else
418 *(static_cast<uint8_t *>(response)) = 1;
419 return IPMI_CC_OK;
420}
421
422ipmi_ret_t cmd_mdr2_get_data_info(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
423 ipmi_request_t request,
424 ipmi_response_t response,
425 ipmi_data_len_t data_len,
426 ipmi_context_t context)
427{
428 auto requestData =
429 reinterpret_cast<const MDRiiGetDataInfoRequest *>(request);
430 auto dataOut = reinterpret_cast<uint8_t *>(response);
431 std::vector<uint8_t> res;
432
433 if (*data_len < sizeof(MDRiiGetDataInfoRequest))
434 {
435 *data_len = 0;
436 return IPMI_CC_REQ_DATA_LEN_INVALID;
437 }
438
439 *data_len = 0;
440
Vernon Mauery15419dd2019-05-24 09:40:30 -0700441 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
442 std::string service = ipmi::getService(*bus, mdrv2Interface, mdrv2Path);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700443
444 if (mdrv2 == nullptr)
445 {
446 mdrv2 = std::make_unique<MDRV2>();
447 }
448
449 int agentIndex = mdrv2->agentLookup(requestData->agentId);
450 if (agentIndex == -1)
451 {
452 phosphor::logging::log<phosphor::logging::level::ERR>(
453 "Unknown agent id",
454 phosphor::logging::entry("ID=%x", requestData->agentId));
455 return IPMI_CC_PARM_OUT_OF_RANGE;
456 }
457
458 int idIndex =
459 mdrv2->findDataId(requestData->dataSetInfo.dataInfo,
460 sizeof(requestData->dataSetInfo.dataInfo), service);
461
462 if ((idIndex < 0) || (idIndex >= maxDirEntries))
463 {
464 phosphor::logging::log<phosphor::logging::level::ERR>(
465 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
466 return IPMI_CC_PARM_OUT_OF_RANGE;
467 }
468
Vernon Mauery15419dd2019-05-24 09:40:30 -0700469 sdbusplus::message::message method = bus->new_method_call(
Vernon Mauerya3702c12019-05-22 13:20:59 -0700470 service.c_str(), mdrv2Path, mdrv2Interface, "GetDataInformation");
471
472 method.append(idIndex);
473
474 try
475 {
Vernon Mauery15419dd2019-05-24 09:40:30 -0700476 sdbusplus::message::message reply = bus->call(method);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700477 reply.read(res);
478 }
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700479 catch (sdbusplus::exception_t &e)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700480 {
481 phosphor::logging::log<phosphor::logging::level::ERR>(
482 "Error get data info",
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700483 phosphor::logging::entry("ERROR=%s", e.what()),
Vernon Mauerya3702c12019-05-22 13:20:59 -0700484 phosphor::logging::entry("SERVICE=%s", service.c_str()),
485 phosphor::logging::entry("PATH=%s", mdrv2Path));
486 return IPMI_CC_RESPONSE_ERROR;
487 }
488
489 if (res.size() != sizeof(MDRiiGetDataInfoResponse))
490 {
491 phosphor::logging::log<phosphor::logging::level::ERR>(
492 "Get data info response length not invalid");
493 return IPMI_CC_UNSPECIFIED_ERROR;
494 }
495 *data_len = static_cast<size_t>(res.size());
496 std::copy(&res[0], &res[*data_len], dataOut);
497
498 return IPMI_CC_OK;
499}
500
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000501/** @brief implements mdr2 data info offer command
502 * @param agentId - Offer a agent ID to get the "Data Set ID"
503 *
504 * @returns IPMI completion code plus response data
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000505 * - dataOut - data Set Id
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000506 */
507ipmi::RspType<std::vector<uint8_t>> mdr2DataInfoOffer(uint16_t agentId)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700508{
Vernon Mauery15419dd2019-05-24 09:40:30 -0700509 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
510 std::string service = ipmi::getService(*bus, mdrv2Interface, mdrv2Path);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700511
512 if (mdrv2 == nullptr)
513 {
514 mdrv2 = std::make_unique<MDRV2>();
515 }
516
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000517 int agentIndex = mdrv2->agentLookup(agentId);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700518 if (agentIndex == -1)
519 {
520 phosphor::logging::log<phosphor::logging::level::ERR>(
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000521 "Unknown agent id", phosphor::logging::entry("ID=%x", agentId));
522 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700523 }
524
Vernon Mauery15419dd2019-05-24 09:40:30 -0700525 sdbusplus::message::message method = bus->new_method_call(
Vernon Mauerya3702c12019-05-22 13:20:59 -0700526 service.c_str(), mdrv2Path, mdrv2Interface, "GetDataOffer");
527
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000528 std::vector<uint8_t> dataOut;
Vernon Mauerya3702c12019-05-22 13:20:59 -0700529 try
530 {
Vernon Mauery15419dd2019-05-24 09:40:30 -0700531 sdbusplus::message::message reply = bus->call(method);
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000532 reply.read(dataOut);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700533 }
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700534 catch (sdbusplus::exception_t &e)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700535 {
536 phosphor::logging::log<phosphor::logging::level::ERR>(
537 "Error send data info offer",
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700538 phosphor::logging::entry("ERROR=%s", e.what()),
Vernon Mauerya3702c12019-05-22 13:20:59 -0700539 phosphor::logging::entry("SERVICE=%s", service.c_str()),
540 phosphor::logging::entry("PATH=%s", mdrv2Path));
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000541 return ipmi::responseResponseError();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700542 }
543
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000544 constexpr size_t respInfoSize = 16;
545 if (dataOut.size() != respInfoSize)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700546 {
547 phosphor::logging::log<phosphor::logging::level::ERR>(
548 "Error send data info offer, return length invalid");
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000549 return ipmi::responseUnspecifiedError();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700550 }
551
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000552 return ipmi::responseSuccess(dataOut);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700553}
554
555ipmi_ret_t cmd_mdr2_send_data_info(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
556 ipmi_request_t request,
557 ipmi_response_t response,
558 ipmi_data_len_t data_len,
559 ipmi_context_t context)
560{
561 auto requestData =
562 reinterpret_cast<const MDRiiSendDataInfoRequest *>(request);
563 bool entryChanged = true;
564
565 if (*data_len != sizeof(MDRiiSendDataInfoRequest))
566 {
567 *data_len = 0;
568 return IPMI_CC_REQ_DATA_LEN_INVALID;
569 }
570
571 *data_len = 0;
572
573 if (requestData->dataLength > smbiosTableStorageSize)
574 {
575 phosphor::logging::log<phosphor::logging::level::ERR>(
576 "Requested data length is out of SMBIOS Table storage size.");
577 return IPMI_CC_PARM_OUT_OF_RANGE;
578 }
579
Vernon Mauery15419dd2019-05-24 09:40:30 -0700580 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
581 std::string service = ipmi::getService(*bus, mdrv2Interface, mdrv2Path);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700582
583 if (mdrv2 == nullptr)
584 {
585 mdrv2 = std::make_unique<MDRV2>();
586 }
587
588 int agentIndex = mdrv2->agentLookup(requestData->agentId);
589 if (agentIndex == -1)
590 {
591 phosphor::logging::log<phosphor::logging::level::ERR>(
592 "Unknown agent id",
593 phosphor::logging::entry("ID=%x", requestData->agentId));
594 return IPMI_CC_PARM_OUT_OF_RANGE;
595 }
596
597 int idIndex =
598 mdrv2->findDataId(requestData->dataSetInfo.dataInfo,
599 sizeof(requestData->dataSetInfo.dataInfo), service);
600
601 if ((idIndex < 0) || (idIndex >= maxDirEntries))
602 {
603 phosphor::logging::log<phosphor::logging::level::ERR>(
604 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
605 return IPMI_CC_PARM_OUT_OF_RANGE;
606 }
607
Vernon Mauery15419dd2019-05-24 09:40:30 -0700608 sdbusplus::message::message method = bus->new_method_call(
Vernon Mauerya3702c12019-05-22 13:20:59 -0700609 service.c_str(), mdrv2Path, mdrv2Interface, "SendDataInformation");
610
611 method.append((uint8_t)idIndex, requestData->validFlag,
612 requestData->dataLength, requestData->dataVersion,
613 requestData->timeStamp);
614
615 try
616 {
Vernon Mauery15419dd2019-05-24 09:40:30 -0700617 sdbusplus::message::message reply = bus->call(method);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700618 reply.read(entryChanged);
619 }
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700620 catch (sdbusplus::exception_t &e)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700621 {
622 phosphor::logging::log<phosphor::logging::level::ERR>(
623 "Error send data info",
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700624 phosphor::logging::entry("ERROR=%s", e.what()),
Vernon Mauerya3702c12019-05-22 13:20:59 -0700625 phosphor::logging::entry("SERVICE=%s", service.c_str()),
626 phosphor::logging::entry("PATH=%s", mdrv2Path));
627 return IPMI_CC_RESPONSE_ERROR;
628 }
629
630 *data_len = 1;
631
632 if (entryChanged)
633 {
634 *(static_cast<uint8_t *>(response)) = 1;
635 }
636 else
637 {
638 *(static_cast<uint8_t *>(response)) = 0;
639 }
640
641 return IPMI_CC_OK;
642}
643
644ipmi_ret_t cmd_mdr2_get_data_block(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
645 ipmi_request_t request,
646 ipmi_response_t response,
647 ipmi_data_len_t data_len,
648 ipmi_context_t context)
649{
650 auto requestData =
651 reinterpret_cast<const MDRiiGetDataBlockRequest *>(request);
652 auto responseData = reinterpret_cast<MDRiiGetDataBlockResponse *>(response);
653 std::tuple<uint8_t, uint32_t, uint32_t, std::vector<uint8_t>> res;
654 std::vector<uint8_t> resData;
655 uint8_t status = 1;
656
657 if (*data_len != sizeof(MDRiiGetDataBlockRequest))
658 {
659 *data_len = 0;
660 return IPMI_CC_REQ_DATA_LEN_INVALID;
661 }
662
663 *data_len = 0;
664
Vernon Mauerya3702c12019-05-22 13:20:59 -0700665 if (mdrv2 == nullptr)
666 {
667 mdrv2 = std::make_unique<MDRV2>();
668 }
669
670 int agentIndex = mdrv2->agentLookup(requestData->agentId);
671 if (agentIndex == -1)
672 {
673 phosphor::logging::log<phosphor::logging::level::ERR>(
674 "Unknown agent id",
675 phosphor::logging::entry("ID=%x", requestData->agentId));
676 return IPMI_CC_PARM_OUT_OF_RANGE;
677 }
678
679 int idIndex = mdrv2->findLockHandle(requestData->lockHandle);
680
681 if ((idIndex < 0) || (idIndex >= maxDirEntries))
682 {
683 phosphor::logging::log<phosphor::logging::level::ERR>(
684 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
685 return IPMI_CC_PARM_OUT_OF_RANGE;
686 }
687
688 if (requestData->xferOffset >= mdrv2->smbiosDir.dir[idIndex].common.size)
689 {
690 phosphor::logging::log<phosphor::logging::level::ERR>(
691 "Offset is outside of range.");
692 return IPMI_CC_PARM_OUT_OF_RANGE;
693 }
694
695 size_t outSize =
696 (requestData->xferLength > mdrv2->smbiosDir.dir[idIndex].xferSize)
697 ? mdrv2->smbiosDir.dir[idIndex].xferSize
698 : requestData->xferLength;
699 if (outSize > UINT_MAX - requestData->xferOffset)
700 {
701 phosphor::logging::log<phosphor::logging::level::ERR>(
702 "Out size and offset are out of range");
703 return IPMI_CC_PARM_OUT_OF_RANGE;
704 }
705 if ((requestData->xferOffset + outSize) >
706 mdrv2->smbiosDir.dir[idIndex].common.size)
707 {
708 outSize =
709 mdrv2->smbiosDir.dir[idIndex].common.size - requestData->xferOffset;
710 }
711
712 responseData->xferLength = outSize;
713 if (responseData->xferLength > requestData->xferLength)
714 {
715 phosphor::logging::log<phosphor::logging::level::ERR>(
716 "Get data block unexpected error.");
717 return IPMI_CC_UNSPECIFIED_ERROR;
718 }
719
720 if ((requestData->xferOffset + outSize) >
721 UINT_MAX -
722 reinterpret_cast<size_t>(mdrv2->smbiosDir.dir[idIndex].dataStorage))
723 {
724 phosphor::logging::log<phosphor::logging::level::ERR>(
725 "Input data to calculate checksum is out of range");
726 return IPMI_CC_PARM_OUT_OF_RANGE;
727 }
728
729 uint32_t u32Checksum = mdrv2->calcChecksum32(
730 mdrv2->smbiosDir.dir[idIndex].dataStorage + requestData->xferOffset,
731 outSize);
732 if (u32Checksum == invalidChecksum)
733 {
734 phosphor::logging::log<phosphor::logging::level::ERR>(
735 "Get data block failed - invalid checksum");
736 return IPMI_CC_OEM_INVALID_CHECKSUM;
737 }
738 responseData->checksum = u32Checksum;
739
740 *data_len = sizeof(responseData->xferLength) +
741 sizeof(responseData->checksum) + outSize;
742
743 if (*data_len > MAX_IPMI_BUFFER) // length + completion code should no more
744 // than MAX_IPMI_BUFFER
745 {
746 phosphor::logging::log<phosphor::logging::level::ERR>(
747 "Data length send from service is invalid");
748 *data_len = 0;
749 return IPMI_CC_RESPONSE_ERROR;
750 }
751
752 std::copy(
753 &mdrv2->smbiosDir.dir[idIndex].dataStorage[requestData->xferOffset],
754 &mdrv2->smbiosDir.dir[idIndex]
755 .dataStorage[requestData->xferOffset + outSize],
756 responseData->data);
757
758 return IPMI_CC_OK;
759}
760
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000761/** @brief implements mdr2 send data block command
762 * @param agentId
763 * @param lockHandle
764 * @param xferOffset
765 * @param xferLength
766 * @param checksum
767 *
768 * @returns IPMI completion code
769 */
770ipmi::RspType<> mdr2SendDataBlock(uint16_t agentId, uint16_t lockHandle,
771 uint32_t xferOffset, uint32_t xferLength,
772 uint32_t checksum)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700773{
Vernon Mauerya3702c12019-05-22 13:20:59 -0700774 if (mdrv2 == nullptr)
775 {
776 mdrv2 = std::make_unique<MDRV2>();
777 }
778
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000779 int agentIndex = mdrv2->agentLookup(agentId);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700780 if (agentIndex == -1)
781 {
782 phosphor::logging::log<phosphor::logging::level::ERR>(
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000783 "Unknown agent id", phosphor::logging::entry("ID=%x", agentId));
784 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700785 }
786
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000787 int idIndex = mdrv2->findLockHandle(lockHandle);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700788
789 if ((idIndex < 0) || (idIndex >= maxDirEntries))
790 {
791 phosphor::logging::log<phosphor::logging::level::ERR>(
792 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000793 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700794 }
795
796 if (mdrv2->smbiosIsUpdating(idIndex))
797 {
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000798 if (xferOffset > UINT_MAX - xferLength)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700799 {
800 phosphor::logging::log<phosphor::logging::level::ERR>(
801 "Offset and length are out of range");
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000802 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700803 }
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000804 if (((xferOffset + xferLength) >
Vernon Mauerya3702c12019-05-22 13:20:59 -0700805 mdrv2->smbiosDir.dir[idIndex].maxDataSize) ||
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000806 ((xferOffset + xferLength) >
Vernon Mauerya3702c12019-05-22 13:20:59 -0700807 mdrv2->smbiosDir.dir[idIndex].common.dataSetSize))
808 {
809 phosphor::logging::log<phosphor::logging::level::ERR>(
810 "Send data block Invalid offset/length");
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000811 return ipmi::responseReqDataLenExceeded();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700812 }
813 if (reinterpret_cast<size_t>(
814 mdrv2->smbiosDir.dir[idIndex].dataStorage) >
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000815 UINT_MAX - xferOffset)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700816 {
817 phosphor::logging::log<phosphor::logging::level::ERR>(
818 "Offset is out of range");
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000819 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700820 }
821 uint8_t *destAddr =
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000822 mdrv2->smbiosDir.dir[idIndex].dataStorage + xferOffset;
Vernon Mauerya3702c12019-05-22 13:20:59 -0700823 uint8_t *sourceAddr = reinterpret_cast<uint8_t *>(mdrv2->area->vPtr);
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000824 uint32_t calcChecksum = mdrv2->calcChecksum32(sourceAddr, xferLength);
825 if (calcChecksum != checksum)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700826 {
827 phosphor::logging::log<phosphor::logging::level::ERR>(
828 "Send data block Invalid checksum");
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000829 return ipmi::response(ccOemInvalidChecksum);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700830 }
831 else
832 {
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000833 if (reinterpret_cast<size_t>(sourceAddr) > UINT_MAX - xferLength)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700834 {
835 phosphor::logging::log<phosphor::logging::level::ERR>(
836 "Length is out of range");
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000837 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700838 }
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000839 std::copy(sourceAddr, sourceAddr + xferLength, destAddr);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700840 }
841 }
842 else
843 {
844 phosphor::logging::log<phosphor::logging::level::ERR>(
845 "Send data block failed, other data is updating");
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000846 return ipmi::responseDestinationUnavailable();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700847 }
848
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000849 return ipmi::responseSuccess();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700850}
851
852bool MDRV2::storeDatatoFlash(MDRSMBIOSHeader *mdrHdr, uint8_t *data)
853{
854 std::ofstream smbiosFile(mdrType2File,
855 std::ios_base::binary | std::ios_base::trunc);
856 if (!smbiosFile.good())
857 {
858 phosphor::logging::log<phosphor::logging::level::ERR>(
859 "Write data from flash error - Open MDRV2 table file failure");
860 return false;
861 }
862
863 try
864 {
865 smbiosFile.write(reinterpret_cast<char *>(mdrHdr),
866 sizeof(MDRSMBIOSHeader));
867 smbiosFile.write(reinterpret_cast<char *>(data), mdrHdr->dataSize);
868 }
869 catch (std::ofstream::failure &e)
870 {
871 phosphor::logging::log<phosphor::logging::level::ERR>(
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700872 "Write data from flash error - write data error",
873 phosphor::logging::entry("ERROR=%s", e.what()));
Vernon Mauerya3702c12019-05-22 13:20:59 -0700874 return false;
875 }
876
877 return true;
878}
879
880void SharedMemoryArea::Initialize(uint32_t addr, uint32_t areaSize)
881{
882 int memDriver = 0;
883
884 // open mem driver for the system memory access
885 memDriver = open("/dev/vgasharedmem", O_RDONLY);
886 if (memDriver < 0)
887 {
888 phosphor::logging::log<phosphor::logging::level::ERR>(
889 "Cannot access mem driver");
890 throw std::system_error(EIO, std::generic_category());
891 }
892
893 // map the system memory
894 vPtr = mmap(NULL, // where to map to: don't mind
895 areaSize, // how many bytes ?
896 PROT_READ, // want to read and write
897 MAP_SHARED, // no copy on write
898 memDriver, // handle to /dev/mem
899 (physicalAddr & pageMask)); // hopefully the Text-buffer :-)
900
901 close(memDriver);
902 if (vPtr == MAP_FAILED)
903 {
904 phosphor::logging::log<phosphor::logging::level::ERR>(
905 "Failed to map share memory");
906 throw std::system_error(EIO, std::generic_category());
907 }
908 size = areaSize;
909 physicalAddr = addr;
910}
911
912bool MDRV2::smbiosUnlock(uint8_t index)
913{
914 bool ret;
915 switch (smbiosDir.dir[index].stage)
916 {
917 case MDR2SMBIOSStatusEnum::mdr2Updating:
918 smbiosDir.dir[index].stage = MDR2SMBIOSStatusEnum::mdr2Updated;
919 smbiosDir.dir[index].lock = MDR2DirLockEnum::mdr2DirUnlock;
920
921 timer->stop();
922 smbiosDir.dir[index].lockHandle = 0;
923 ret = true;
924 break;
925
926 case MDR2SMBIOSStatusEnum::mdr2Updated:
927 case MDR2SMBIOSStatusEnum::mdr2Loaded:
928 smbiosDir.dir[index].lock = MDR2DirLockEnum::mdr2DirUnlock;
929
930 timer->stop();
931
932 smbiosDir.dir[index].lockHandle = 0;
933 ret = true;
934 break;
935
936 default:
937 break;
938 }
939
940 return ret;
941}
942
943bool MDRV2::smbiosTryLock(uint8_t flag, uint8_t index, uint16_t *session,
944 uint16_t timeout)
945{
946 bool ret = false;
947 uint32_t u32Status = 0;
948
949 if (timeout == 0)
950 {
951 timeout = defaultTimeout;
952 }
953 std::chrono::microseconds usec(timeout * sysClock);
954
955 switch (smbiosDir.dir[index].stage)
956 {
957 case MDR2SMBIOSStatusEnum::mdr2Updating:
958 if (smbiosDir.dir[index].lock != MDR2DirLockEnum::mdr2DirLock)
959 {
960 smbiosDir.dir[index].lock = MDR2DirLockEnum::mdr2DirLock;
961 timer->start(usec);
962 lockIndex = index;
963
964 *session = getSessionHandle(&smbiosDir);
965 smbiosDir.dir[index].lockHandle = *session;
966 ret = true;
967 }
968 break;
969 case MDR2SMBIOSStatusEnum::mdr2Init:
970 if (flag)
971 {
972 smbiosDir.dir[index].stage = MDR2SMBIOSStatusEnum::mdr2Updating;
973 smbiosDir.dir[index].lock = MDR2DirLockEnum::mdr2DirUnlock;
974 timer->start(usec);
975 lockIndex = index;
976
977 *session = getSessionHandle(&smbiosDir);
978 smbiosDir.dir[index].lockHandle = *session;
979 ret = true;
980 }
981 break;
982
983 case MDR2SMBIOSStatusEnum::mdr2Updated:
984 case MDR2SMBIOSStatusEnum::mdr2Loaded:
985 if (smbiosDir.dir[index].lock != MDR2DirLockEnum::mdr2DirLock)
986 {
987 if (flag)
988 {
989 smbiosDir.dir[index].stage =
990 MDR2SMBIOSStatusEnum::mdr2Updating;
991 smbiosDir.dir[index].lock = MDR2DirLockEnum::mdr2DirUnlock;
992 }
993 else
994 {
995 smbiosDir.dir[index].lock = MDR2DirLockEnum::mdr2DirLock;
996 }
997
998 timer->start(usec);
999 lockIndex = index;
1000
1001 *session = getSessionHandle(&smbiosDir);
1002 smbiosDir.dir[index].lockHandle = *session;
1003 ret = true;
1004 }
1005 break;
1006
1007 default:
1008 break;
1009 }
1010 return ret;
1011}
1012
1013void MDRV2::timeoutHandler()
1014{
1015 smbiosUnlock(lockIndex);
1016 mdrv2->area.reset(nullptr);
1017}
1018
jayaprakash Mutyala40fec612019-06-19 11:53:03 +00001019/** @brief implements mdr2 lock data command
1020 * @param agentId
1021 * @param dataInfo
1022 * @param timeout
1023 *
1024 * @returns IPMI completion code plus response data
1025 * - mdr2Version
1026 * - session
1027 * - dataLength
1028 * - xferAddress
1029 * - xferLength
1030 */
1031ipmi::RspType<uint8_t, // mdr2Version
1032 uint16_t, // session
1033 uint32_t, // dataLength
1034 uint32_t, // xferAddress
1035 uint32_t // xferLength
1036 >
1037 mdr2LockData(uint16_t agentId, std::array<uint8_t, dataInfoSize> dataInfo,
1038 uint16_t timeout)
Vernon Mauerya3702c12019-05-22 13:20:59 -07001039{
Vernon Mauerya3702c12019-05-22 13:20:59 -07001040 if (mdrv2 == nullptr)
1041 {
1042 mdrv2 = std::make_unique<MDRV2>();
1043 }
1044
jayaprakash Mutyala40fec612019-06-19 11:53:03 +00001045 int agentIndex = mdrv2->agentLookup(agentId);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001046 if (agentIndex == -1)
1047 {
1048 phosphor::logging::log<phosphor::logging::level::ERR>(
jayaprakash Mutyala40fec612019-06-19 11:53:03 +00001049 "Unknown agent id", phosphor::logging::entry("ID=%x", agentId));
1050 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001051 }
1052
Vernon Mauery15419dd2019-05-24 09:40:30 -07001053 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
1054 std::string service = ipmi::getService(*bus, mdrv2Interface, mdrv2Path);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001055
jayaprakash Mutyala40fec612019-06-19 11:53:03 +00001056 int idIndex = mdrv2->findDataId(dataInfo.data(), sizeof(dataInfo), service);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001057
1058 if ((idIndex < 0) || (idIndex >= maxDirEntries))
1059 {
1060 phosphor::logging::log<phosphor::logging::level::ERR>(
1061 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
jayaprakash Mutyala40fec612019-06-19 11:53:03 +00001062 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001063 }
1064
jayaprakash Mutyala40fec612019-06-19 11:53:03 +00001065 uint16_t session = 0;
1066 if (!mdrv2->smbiosTryLock(0, idIndex, &session, timeout))
Vernon Mauerya3702c12019-05-22 13:20:59 -07001067 {
1068 phosphor::logging::log<phosphor::logging::level::ERR>(
1069 "Lock Data failed - cannot lock idIndex");
jayaprakash Mutyala40fec612019-06-19 11:53:03 +00001070 return ipmi::responseCommandNotAvailable();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001071 }
1072
jayaprakash Mutyala40fec612019-06-19 11:53:03 +00001073 uint32_t dataLength = mdrv2->smbiosDir.dir[idIndex].common.size;
1074 uint32_t xferAddress = mdrv2->smbiosDir.dir[idIndex].xferBuff;
1075 uint32_t xferLength = mdrv2->smbiosDir.dir[idIndex].xferSize;
Vernon Mauerya3702c12019-05-22 13:20:59 -07001076
jayaprakash Mutyala40fec612019-06-19 11:53:03 +00001077 return ipmi::responseSuccess(mdr2Version, session, dataLength, xferAddress,
1078 xferLength);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001079}
1080
jayaprakash Mutyaladad548b2019-06-12 15:29:39 +00001081/** @brief implements mdr2 unlock data command
1082 * @param agentId
1083 * @param lockHandle
1084 *
1085 * @returns IPMI completion code
1086 */
1087ipmi::RspType<> mdr2UnlockData(uint16_t agentId, uint16_t lockHandle)
Vernon Mauerya3702c12019-05-22 13:20:59 -07001088{
1089 phosphor::logging::log<phosphor::logging::level::ERR>("unlock data");
Vernon Mauerya3702c12019-05-22 13:20:59 -07001090
Vernon Mauerya3702c12019-05-22 13:20:59 -07001091 if (mdrv2 == nullptr)
1092 {
1093 mdrv2 = std::make_unique<MDRV2>();
1094 }
1095
jayaprakash Mutyaladad548b2019-06-12 15:29:39 +00001096 int agentIndex = mdrv2->agentLookup(agentId);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001097 if (agentIndex == -1)
1098 {
1099 phosphor::logging::log<phosphor::logging::level::ERR>(
jayaprakash Mutyaladad548b2019-06-12 15:29:39 +00001100 "Unknown agent id", phosphor::logging::entry("ID=%x", agentId));
1101 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001102 }
1103
jayaprakash Mutyaladad548b2019-06-12 15:29:39 +00001104 int idIndex = mdrv2->findLockHandle(lockHandle);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001105
1106 if ((idIndex < 0) || (idIndex >= maxDirEntries))
1107 {
1108 phosphor::logging::log<phosphor::logging::level::ERR>(
1109 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
jayaprakash Mutyaladad548b2019-06-12 15:29:39 +00001110 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001111 }
1112
1113 if (!mdrv2->smbiosUnlock(idIndex))
1114 {
1115 phosphor::logging::log<phosphor::logging::level::ERR>(
1116 "Unlock Data failed - cannot unlock idIndex");
jayaprakash Mutyaladad548b2019-06-12 15:29:39 +00001117 return ipmi::responseCommandNotAvailable();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001118 }
1119
jayaprakash Mutyaladad548b2019-06-12 15:29:39 +00001120 return ipmi::responseSuccess();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001121}
1122
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001123/**
1124@brief This command is executed after POST BIOS to get the session info.
1125
1126@param - agentId, dataInfo, dataLength, xferAddress, xferLength, timeout.
1127
1128@return xferStartAck and session on success.
1129**/
1130ipmi::RspType<uint8_t, uint16_t>
1131 cmd_mdr2_data_start(uint16_t agentId, std::array<uint8_t, 16> dataInfo,
1132 uint32_t dataLength, uint32_t xferAddress,
1133 uint32_t xferLength, uint16_t timeout)
Vernon Mauerya3702c12019-05-22 13:20:59 -07001134{
Vernon Mauerya3702c12019-05-22 13:20:59 -07001135 uint16_t session = 0;
1136
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001137 if (dataLength > smbiosTableStorageSize)
Vernon Mauerya3702c12019-05-22 13:20:59 -07001138 {
1139 phosphor::logging::log<phosphor::logging::level::ERR>(
1140 "Requested data length is out of SMBIOS Table storage size.");
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001141 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001142 }
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001143 if ((xferLength + xferAddress) > mdriiSMSize)
Vernon Mauerya3702c12019-05-22 13:20:59 -07001144 {
1145 phosphor::logging::log<phosphor::logging::level::ERR>(
1146 "Invalid data address and size");
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001147 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001148 }
1149
Vernon Mauery15419dd2019-05-24 09:40:30 -07001150 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
1151 std::string service = ipmi::getService(*bus, mdrv2Interface, mdrv2Path);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001152
1153 if (mdrv2 == nullptr)
1154 {
1155 mdrv2 = std::make_unique<MDRV2>();
1156 }
1157
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001158 int agentIndex = mdrv2->agentLookup(agentId);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001159 if (agentIndex == -1)
1160 {
1161 phosphor::logging::log<phosphor::logging::level::ERR>(
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001162 "Unknown agent id", phosphor::logging::entry("ID=%x", agentId));
1163 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001164 }
1165
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001166 int idIndex = mdrv2->findDataId(dataInfo.data(), sizeof(dataInfo), service);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001167
1168 if ((idIndex < 0) || (idIndex >= maxDirEntries))
1169 {
1170 phosphor::logging::log<phosphor::logging::level::ERR>(
1171 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001172 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001173 }
1174
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001175 if (mdrv2->smbiosTryLock(1, idIndex, &session, timeout))
Vernon Mauerya3702c12019-05-22 13:20:59 -07001176 {
1177 try
1178 {
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001179 mdrv2->area =
1180 std::make_unique<SharedMemoryArea>(xferAddress, xferLength);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001181 }
1182 catch (const std::system_error &e)
1183 {
1184 mdrv2->smbiosUnlock(idIndex);
1185 phosphor::logging::log<phosphor::logging::level::ERR>(
Vernon Maueryc7d517e2019-06-18 14:27:00 -07001186 "Unable to access share memory",
1187 phosphor::logging::entry("ERROR=%s", e.what()));
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001188 return ipmi::responseUnspecifiedError();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001189 }
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001190 mdrv2->smbiosDir.dir[idIndex].common.size = dataLength;
Vernon Mauerya3702c12019-05-22 13:20:59 -07001191 mdrv2->smbiosDir.dir[idIndex].lockHandle = session;
1192 if (-1 ==
1193 mdrv2->syncDirCommonData(
1194 idIndex, mdrv2->smbiosDir.dir[idIndex].common.size, service))
1195 {
1196 phosphor::logging::log<phosphor::logging::level::ERR>(
1197 "Unable to sync data to service");
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001198 return ipmi::responseResponseError();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001199 }
1200 }
1201 else
1202 {
1203 phosphor::logging::log<phosphor::logging::level::ERR>(
1204 "Canot lock smbios");
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001205 return ipmi::responseUnspecifiedError();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001206 }
1207
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001208 static constexpr uint8_t xferStartAck = 1;
Vernon Mauerya3702c12019-05-22 13:20:59 -07001209
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001210 return ipmi::responseSuccess(xferStartAck, session);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001211}
1212
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001213/**
1214@brief This command is executed to close the session.
1215
1216@param - agentId, lockHandle.
1217
1218@return completion code on success.
1219**/
1220ipmi::RspType<> cmd_mdr2_data_done(uint16_t agentId, uint16_t lockHandle)
Vernon Mauerya3702c12019-05-22 13:20:59 -07001221{
Vernon Mauerya3702c12019-05-22 13:20:59 -07001222
1223 if (mdrv2 == nullptr)
1224 {
1225 mdrv2 = std::make_unique<MDRV2>();
1226 }
1227
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001228 int agentIndex = mdrv2->agentLookup(agentId);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001229 if (agentIndex == -1)
1230 {
1231 phosphor::logging::log<phosphor::logging::level::ERR>(
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001232 "Unknown agent id", phosphor::logging::entry("ID=%x", agentId));
1233 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001234 }
1235
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001236 int idIndex = mdrv2->findLockHandle(lockHandle);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001237
1238 if ((idIndex < 0) || (idIndex >= maxDirEntries))
1239 {
1240 phosphor::logging::log<phosphor::logging::level::ERR>(
1241 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001242 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001243 }
1244
1245 if (!mdrv2->smbiosUnlock(idIndex))
1246 {
1247 phosphor::logging::log<phosphor::logging::level::ERR>(
1248 "Send data done failed - cannot unlock idIndex");
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001249 return ipmi::responseDestinationUnavailable();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001250 }
1251
1252 mdrv2->area.reset(nullptr);
1253 MDRSMBIOSHeader mdr2Smbios;
1254 mdr2Smbios.mdrType = mdrTypeII;
1255 mdr2Smbios.dirVer = mdrv2->smbiosDir.dir[0].common.dataVersion;
1256 mdr2Smbios.timestamp = mdrv2->smbiosDir.dir[0].common.timestamp;
1257 mdr2Smbios.dataSize = mdrv2->smbiosDir.dir[0].common.size;
1258
1259 if (access(smbiosPath, 0) == -1)
1260 {
1261 int flag = mkdir(smbiosPath, S_IRWXU);
1262 if (flag != 0)
1263 {
1264 phosphor::logging::log<phosphor::logging::level::ERR>(
1265 "create folder failed for writting smbios file");
1266 }
1267 }
1268 if (!mdrv2->storeDatatoFlash(
1269 &mdr2Smbios, mdrv2->smbiosDir.dir[smbiosDirIndex].dataStorage))
1270 {
1271 phosphor::logging::log<phosphor::logging::level::ERR>(
1272 "MDR2 Store data to flash failed");
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001273 return ipmi::responseDestinationUnavailable();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001274 }
Vernon Mauerya3702c12019-05-22 13:20:59 -07001275 bool status = false;
Vernon Mauery15419dd2019-05-24 09:40:30 -07001276 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
1277 std::string service = ipmi::getService(*bus, mdrv2Interface, mdrv2Path);
1278 sdbusplus::message::message method = bus->new_method_call(
Vernon Mauerya3702c12019-05-22 13:20:59 -07001279 service.c_str(), mdrv2Path, mdrv2Interface, "AgentSynchronizeData");
1280
1281 try
1282 {
Vernon Mauery15419dd2019-05-24 09:40:30 -07001283 sdbusplus::message::message reply = bus->call(method);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001284 reply.read(status);
1285 }
Vernon Maueryc7d517e2019-06-18 14:27:00 -07001286 catch (sdbusplus::exception_t &e)
Vernon Mauerya3702c12019-05-22 13:20:59 -07001287 {
1288 phosphor::logging::log<phosphor::logging::level::ERR>(
1289 "Error Sync data with service",
Vernon Maueryc7d517e2019-06-18 14:27:00 -07001290 phosphor::logging::entry("ERROR=%s", e.what()),
Vernon Mauerya3702c12019-05-22 13:20:59 -07001291 phosphor::logging::entry("SERVICE=%s", service.c_str()),
1292 phosphor::logging::entry("PATH=%s", mdrv2Path));
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001293 return ipmi::responseResponseError();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001294 }
1295
1296 if (!status)
1297 {
1298 phosphor::logging::log<phosphor::logging::level::ERR>(
1299 "Sync data with service failure");
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001300 return ipmi::responseUnspecifiedError();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001301 }
1302
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001303 return ipmi::responseSuccess();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001304}
1305
1306static void register_netfn_smbiosmdrv2_functions(void)
1307{
1308 // MDR V2 Command
1309 // <Get MDRII Status Command>
jayaprakash Mutyala853d8292019-05-31 18:17:42 +00001310 ipmi::registerHandler(ipmi::prioOemBase, NETFUN_INTEL_APP_OEM,
1311 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_AGENT_STATUS,
1312 ipmi::Privilege::Operator, mdr2AgentStatus);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001313
1314 // <Get MDRII Directory Command>
jayaprakash Mutyaladad548b2019-06-12 15:29:39 +00001315 ipmi::registerHandler(ipmi::prioOemBase, NETFUN_INTEL_APP_OEM,
1316 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_GET_DIR,
1317 ipmi::Privilege::Operator, mdr2GetDir);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001318
1319 // <Send MDRII Directory Command>
1320 ipmi_register_callback(NETFUN_INTEL_APP_OEM,
1321 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_SEND_DIR, NULL,
1322 cmd_mdr2_send_dir, PRIVILEGE_OPERATOR);
1323
1324 // <Get MDRII Data Info Command>
1325 ipmi_register_callback(NETFUN_INTEL_APP_OEM,
1326 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_GET_DATA_INFO,
1327 NULL, cmd_mdr2_get_data_info, PRIVILEGE_OPERATOR);
1328
1329 // <Send MDRII Info Offer>
jayaprakash Mutyala853d8292019-05-31 18:17:42 +00001330 ipmi::registerHandler(
1331 ipmi::prioOemBase, NETFUN_INTEL_APP_OEM,
1332 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_SEND_DATA_INFO_OFFER,
1333 ipmi::Privilege::Operator, mdr2DataInfoOffer);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001334
1335 // <Send MDRII Data Info>
1336 ipmi_register_callback(NETFUN_INTEL_APP_OEM,
1337 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_SEND_DATA_INFO,
1338 NULL, cmd_mdr2_send_data_info, PRIVILEGE_OPERATOR);
1339
1340 // <Get MDRII Data Block Command>
1341 ipmi_register_callback(NETFUN_INTEL_APP_OEM,
1342 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_GET_DATA_BLOCK,
1343 NULL, cmd_mdr2_get_data_block, PRIVILEGE_OPERATOR);
1344
1345 // <Send MDRII Data Block>
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +00001346 ipmi::registerHandler(ipmi::prioOemBase, NETFUN_INTEL_APP_OEM,
1347 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_SEND_DATA_BLOCK,
1348 ipmi::Privilege::Operator, mdr2SendDataBlock);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001349
1350 // <Lock MDRII Data Command>
jayaprakash Mutyala40fec612019-06-19 11:53:03 +00001351 ipmi::registerHandler(ipmi::prioOemBase, NETFUN_INTEL_APP_OEM,
1352 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_LOCK_DATA,
1353 ipmi::Privilege::Operator, mdr2LockData);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001354
1355 // <Unlock MDRII Data Command>
jayaprakash Mutyaladad548b2019-06-12 15:29:39 +00001356 ipmi::registerHandler(ipmi::prioOemBase, NETFUN_INTEL_APP_OEM,
1357 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_UNLOCK_DATA,
1358 ipmi::Privilege::Operator, mdr2UnlockData);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001359
1360 // <Send MDRII Data Start>
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001361 ipmi::registerHandler(ipmi::prioOemBase, NETFUN_INTEL_APP_OEM,
1362 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_DATA_START,
1363 ipmi::Privilege::Operator, cmd_mdr2_data_start);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001364
1365 // <Send MDRII Data Done>
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001366 ipmi::registerHandler(ipmi::prioOemBase, NETFUN_INTEL_APP_OEM,
1367 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_DATA_DONE,
1368 ipmi::Privilege::Operator, cmd_mdr2_data_done);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001369}