blob: 805306e5c0358873503c29644a8869d0077fc6bf [file] [log] [blame]
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001/*
2// Copyright (c) 2020 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
Arun Lal K Me7725612021-07-15 18:20:58 +000017#include "biosxml.hpp"
18
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +080019#include <openssl/sha.h>
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +080020
21#include <biosconfigcommands.hpp>
22#include <boost/crc.hpp>
23#include <boost/process/child.hpp>
24#include <boost/process/io.hpp>
25#include <ipmid/api.hpp>
26#include <ipmid/message.hpp>
27#include <ipmid/message/types.hpp>
28#include <ipmid/types.hpp>
29#include <ipmid/utils.hpp>
30#include <nlohmann/json.hpp>
31#include <oemcommands.hpp>
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +080032#include <sdbusplus/bus.hpp>
33#include <sdbusplus/message/types.hpp>
34
35#include <filesystem>
Suryakanth Sekarcc402592021-04-01 15:02:10 +053036#include <string_view>
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +080037
38namespace ipmi
39{
Arun Lal K Mb0caca02021-09-05 22:09:33 +000040static bool flushNVOOBdata();
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +080041static void registerBIOSConfigFunctions() __attribute__((constructor));
42
43// Define BIOS config related Completion Code
44using Cc = uint8_t;
45static constexpr Cc ipmiCCPayloadPayloadPacketMissed = 0x80;
46static constexpr Cc ipmiCCBIOSPasswordInitNotDone = 0x80;
47static constexpr Cc ipmiCCPayloadChecksumFailed = 0x81;
48static constexpr Cc ipmiCCNotSupportedInCurrentState = 0x82;
49static constexpr Cc ipmiCCPayloadPayloadInComplete = 0x83;
50static constexpr Cc ipmiCCBIOSCapabilityInitNotDone = 0x85;
51static constexpr Cc ipmiCCPayloadLengthIllegal = 0x85;
52
53static constexpr uint8_t userPasswordChanged = (1 << 5);
54static constexpr uint8_t adminPasswordChanged = (1 << 4);
Snehalatha Venkatesh6346e982022-03-09 06:49:18 +000055static constexpr uint8_t restoreDefaultValues = (1 << 7);
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +080056
57static constexpr const char* biosConfigFolder = "/var/oob";
58static constexpr const char* biosConfigNVPath = "/var/oob/nvoobdata.dat";
59static constexpr const uint8_t algoSHA384 = 2;
Ayushi Smriti32381872021-06-23 11:05:48 +053060static constexpr const uint8_t algoSHA256 = 1;
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +080061static constexpr const uint8_t biosCapOffsetBit = 0x3;
62static constexpr uint16_t maxGetPayloadDataSize = 4096;
63static constexpr const char* biosXMLFilePath = "/var/oob/bios.xml";
64static constexpr const char* biosXMLFilePath1 = "/var/oob/tempbios.xml";
65
66static constexpr const char* biosConfigBaseMgrPath =
67 "/xyz/openbmc_project/bios_config/manager";
68static constexpr const char* biosConfigIntf =
69 "xyz.openbmc_project.BIOSConfig.Manager";
70static constexpr const char* resetBIOSSettingsProp = "ResetBIOSSettings";
71/*baseBIOSTable
72map{attributeName,struct{attributeType,readonlyStatus,displayname,
73 description,menuPath,current,default,
74 array{struct{optionstring,optionvalue}}}}
75*/
Arun Lal K Me7725612021-07-15 18:20:58 +000076
77bios::BiosBaseTableType attributesData;
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +080078
79NVOOBdata gNVOOBdata;
80
81enum class PTState : uint8_t
82{
83 StartTransfer = 0,
84 InProgress = 1,
85 EndTransfer = 2,
86 UserAbort = 3
87};
88enum class PStatus : uint8_t
89{
90 Unknown = 0,
91 Valid = 1,
92 Corrupted = 2
93};
94enum class PType : uint8_t
95{
96 IntelXMLType0 = 0,
97 IntelXMLType1 = 1,
98 OTAPayload = 5,
99};
100
101//
102// GetPayload Payload status enumeration
103//
104enum class GetPayloadParameter : uint8_t
105{
106 GetPayloadInfo = 0, // 0
107 GetPayloadData = 1, // 1
108 GetPayloadStatus = 2
109};
110
Arun Lal K Mb0caca02021-09-05 22:09:33 +0000111namespace payload1
112{
113
114enum class AttributesType : uint8_t
115{
116 unknown = 0,
117 string,
Arun Lal K Md2d60ab2021-12-29 19:42:03 +0000118 integer,
119 enumeration
Arun Lal K Mb0caca02021-09-05 22:09:33 +0000120};
121
122using PendingAttributesType =
123 std::map<std::string,
124 std::tuple<std::string, std::variant<int64_t, std::string>>>;
125
126AttributesType getAttrType(const std::string_view typeDbus)
127{
128 if (typeDbus == "xyz.openbmc_project.BIOSConfig.Manager."
129 "AttributeType.String")
130 {
131 return AttributesType::string;
132 }
133 else if (typeDbus == "xyz.openbmc_project.BIOSConfig."
134 "Manager.AttributeType.Integer")
135 {
136 return AttributesType::integer;
137 }
Arun Lal K Md2d60ab2021-12-29 19:42:03 +0000138 else if (typeDbus == "xyz.openbmc_project.BIOSConfig."
139 "Manager.AttributeType.Enumeration")
140 {
141 return AttributesType::enumeration;
142 }
Arun Lal K Mb0caca02021-09-05 22:09:33 +0000143
144 return AttributesType::unknown;
145}
146
147bool fillPayloadData(std::string& payloadData,
148 const std::variant<int64_t, std::string>& attributes,
149 const std::string_view key, AttributesType& attrType)
150{
151 payloadData += key;
152 payloadData += '=';
153
Arun Lal K Md2d60ab2021-12-29 19:42:03 +0000154 if (attrType == AttributesType::string ||
155 attrType == AttributesType::enumeration)
Arun Lal K Mb0caca02021-09-05 22:09:33 +0000156 {
157 if (!std::holds_alternative<std::string>(attributes))
158 {
159 phosphor::logging::log<phosphor::logging::level::ERR>(
160 "fillPayloadData: No string data in attributes");
161 return false;
162 }
163 payloadData += std::get<std::string>(attributes);
164 }
165 else if (attrType == AttributesType::integer)
166 {
167 if (!std::holds_alternative<int64_t>(attributes))
168 {
169 phosphor::logging::log<phosphor::logging::level::ERR>(
170 "fillPayloadData: No int64_t data in attributes");
171 return false;
172 }
173 payloadData += std::to_string(std::get<int64_t>(attributes));
174 }
175 else
176 {
177 phosphor::logging::log<phosphor::logging::level::ERR>(
178 "fillPayloadData: Unsupported attribute type");
179 return false;
180 }
181
182 payloadData += '\n';
183
184 return true;
185}
186
187bool getPendingList(ipmi::Context::ptr ctx, std::string& payloadData)
188{
189 std::variant<PendingAttributesType> pendingAttributesData;
190 boost::system::error_code ec;
191
192 payloadData.clear();
193
194 auto dbus = getSdBus();
195 if (!dbus)
196 {
197 phosphor::logging::log<phosphor::logging::level::ERR>(
198 "getPendingList: getSdBus() failed");
199 return false;
200 }
201
202 std::string service =
203 getService(*dbus, biosConfigIntf, biosConfigBaseMgrPath);
204
205 try
206 {
207 pendingAttributesData =
208 dbus->yield_method_call<std::variant<PendingAttributesType>>(
209 ctx->yield, ec, service,
210 "/xyz/openbmc_project/bios_config/manager",
211 "org.freedesktop.DBus.Properties", "Get",
212 "xyz.openbmc_project.BIOSConfig.Manager", "PendingAttributes");
213 }
Patrick Williamsbd51e6a2021-10-06 13:09:44 -0500214 catch (const std::exception& ex)
Arun Lal K Mb0caca02021-09-05 22:09:33 +0000215 {
216 phosphor::logging::log<phosphor::logging::level::ERR>(ex.what());
217 return false;
218 }
219
220 if (ec)
221 {
222 std::string err = "getPendingList: error while trying to get "
223 "PendingAttributes, error = ";
224 err += ec.message();
225
226 phosphor::logging::log<phosphor::logging::level::ERR>(err.c_str());
227
228 return false;
229 }
230
231 const PendingAttributesType* pendingAttributes =
232 std::get_if<PendingAttributesType>(&pendingAttributesData);
233 if (!pendingAttributes)
234 {
235 phosphor::logging::log<phosphor::logging::level::ERR>(
236 "getPendingList: pendingAttributes is null");
237 return false;
238 }
239
240 for (const auto& [key, attributes] : *pendingAttributes)
241 {
242 const std::string& itemType = std::get<0>(attributes);
243 AttributesType attrType = getAttrType(itemType);
244
245 if (!fillPayloadData(payloadData, std::get<1>(attributes), key,
246 attrType))
247 {
248 return false;
249 }
250 }
251
252 if (payloadData.empty())
253 {
254 phosphor::logging::log<phosphor::logging::level::ERR>(
255 "getPendingList: payloadData is empty");
256 return false;
257 }
258
259 return true;
260}
261bool updatePayloadFile(std::string& payloadFilePath, std::string payloadData)
262{
263 std::ofstream payloadFile(payloadFilePath,
264 std::ios::out | std::ios::binary);
265
266 payloadFile << payloadData;
267
268 if (!payloadFile.good())
269 {
270 return false;
271 }
272
273 return true;
274}
275
276bool computeCheckSum(std::string& payloadFilePath,
277 boost::crc_32_type& calcChecksum)
278{
279 std::ifstream payloadFile(payloadFilePath.c_str(),
280 std::ios::in | std::ios::binary | std::ios::ate);
281
282 if (!payloadFile.good())
283 {
284 phosphor::logging::log<phosphor::logging::level::ERR>(
285 "computeCheckSum: Cannot open Payload1 file");
286 return false;
287 }
288
289 payloadFile.seekg(0, payloadFile.end);
290 int length = payloadFile.tellg();
291 payloadFile.seekg(0, payloadFile.beg);
292
293 if (maxGetPayloadDataSize < length)
294 {
295 phosphor::logging::log<phosphor::logging::level::ERR>(
296 "computeCheckSum: length > maxGetPayloadDataSize");
297 return false;
298 }
299
300 std::unique_ptr<char[]> payloadBuffer(new char[length]);
301
302 payloadFile.read(payloadBuffer.get(), length);
303 uint32_t readCount = payloadFile.gcount();
304
305 calcChecksum.process_bytes(payloadBuffer.get(), readCount);
306
307 return true;
308}
309
310bool updatePayloadInfo(std::string& payloadFilePath)
311{
312 boost::crc_32_type calcChecksum;
313
314 uint8_t payloadType = static_cast<uint8_t>(ipmi::PType::IntelXMLType1);
315 auto& payloadInfo = gNVOOBdata.payloadInfo[payloadType];
316
317 if (!computeCheckSum(payloadFilePath, calcChecksum))
318 {
319 phosphor::logging::log<phosphor::logging::level::ERR>(
320 "updatePayloadInfo: Cannot compute checksum for Payload1 file");
321 return false;
322 }
323
324 payloadInfo.payloadVersion = 0;
325 payloadInfo.payloadflag = 0;
326 payloadInfo.payloadReservationID = rand();
327
328 payloadInfo.payloadType = payloadType;
329
330 payloadInfo.payloadTotalChecksum = calcChecksum.checksum();
331 payloadInfo.payloadCurrentChecksum = payloadInfo.payloadTotalChecksum;
332
333 payloadInfo.payloadStatus = (static_cast<uint8_t>(ipmi::PStatus::Valid));
334
335 struct stat filestat;
336 /* Get entry's information. */
337 if (!stat(payloadFilePath.c_str(), &filestat))
338 {
339 payloadInfo.payloadTimeStamp = filestat.st_mtime;
340 payloadInfo.payloadTotalSize = filestat.st_size;
341 payloadInfo.payloadCurrentSize = filestat.st_size;
342 payloadInfo.actualTotalPayloadWritten = filestat.st_size;
343 }
344 else
345 {
346 phosphor::logging::log<phosphor::logging::level::ERR>(
347 "updatePayloadInfo: Cannot get file status for Payload1 file");
348 return false;
349 }
350
351 if (!flushNVOOBdata())
352 {
353 phosphor::logging::log<phosphor::logging::level::ERR>(
354 "updatePayloadInfo: flushNVOOBdata failed");
355 return false;
356 }
357
358 return true;
359}
360
361bool update(ipmi::Context::ptr ctx)
362{
363 std::string payloadFilePath =
364 "/var/oob/Payload" +
365 std::to_string(static_cast<uint8_t>(ipmi::PType::IntelXMLType1));
366
367 std::string payloadData;
368
369 if (!getPendingList(ctx, payloadData))
370 {
371 phosphor::logging::log<phosphor::logging::level::ERR>(
372 "payload1::update : getPendingList() failed");
373 return false;
374 }
375
376 if (!updatePayloadFile(payloadFilePath, payloadData))
377 {
378 phosphor::logging::log<phosphor::logging::level::ERR>(
379 "payload1::update : updatePayloadFile() failed");
380 return false;
381 }
382
383 if (!updatePayloadInfo(payloadFilePath))
384 {
385 phosphor::logging::log<phosphor::logging::level::ERR>(
386 "payload1::update : updatePayloadInfo() failed");
387 return false;
388 }
389
390 return true;
391}
392} // namespace payload1
393
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800394/** @brief implement to set the BaseBIOSTable property
395 * @returns status
396 */
Arun Lal K Me7725612021-07-15 18:20:58 +0000397static bool sendAllAttributes(std::string service)
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800398{
Arun Lal K Me7725612021-07-15 18:20:58 +0000399 std::shared_ptr<sdbusplus::asio::connection> pSdBusPlus = getSdBus();
400
401 if (pSdBusPlus)
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800402 {
Arun Lal K Me7725612021-07-15 18:20:58 +0000403 try
404 {
405 pSdBusPlus->async_method_call(
406 [](const boost::system::error_code ec) {
407 /* No more need to keep attributes data in memory */
408 attributesData.clear();
409
410 if (ec)
411 {
412 phosphor::logging::log<phosphor::logging::level::ERR>(
413 "sendAllAttributes error: send all attributes - "
414 "failed");
415 return;
416 }
417
418 phosphor::logging::log<phosphor::logging::level::INFO>(
419 "sendAllAttributes: send all attributes - done");
420 },
421 service, biosConfigBaseMgrPath,
422 "org.freedesktop.DBus.Properties", "Set", biosConfigIntf,
423 "BaseBIOSTable",
424 std::variant<bios::BiosBaseTableType>(attributesData));
425
426 return true;
427 }
Patrick Williamsbd51e6a2021-10-06 13:09:44 -0500428 catch (const std::exception& ex)
Arun Lal K Me7725612021-07-15 18:20:58 +0000429 {
430 phosphor::logging::log<phosphor::logging::level::ERR>(ex.what());
431 }
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800432 }
Arun Lal K Me7725612021-07-15 18:20:58 +0000433
434 return false;
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800435}
436
437/** @brief implement to flush the updated data in nv space
438 * @returns status
439 */
Arun Lal K Mb0caca02021-09-05 22:09:33 +0000440static bool flushNVOOBdata()
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800441{
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000442 std::ofstream outFile(biosConfigNVPath, std::ios::binary);
Arun Lal K Mb0caca02021-09-05 22:09:33 +0000443
444 outFile.seekp(std::ios_base::beg);
445 const char* writedata = reinterpret_cast<const char*>(&gNVOOBdata);
446 outFile.write(writedata, sizeof(struct NVOOBdata));
447
448 if (!outFile.good())
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800449 {
Arun Lal K Mb0caca02021-09-05 22:09:33 +0000450 return false;
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800451 }
Arun Lal K Mb0caca02021-09-05 22:09:33 +0000452
453 return true;
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800454}
455
456/** @brief implement to get the System State
457 * @returns status
458 */
Arun Lal K M382dc972022-01-20 22:18:23 +0000459static bool getPostCompleted()
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800460{
Arun Lal K M382dc972022-01-20 22:18:23 +0000461 /*
462 * In case of failure we treat postCompleted as true.
463 * So that BIOS config commands is not accepted by BMC by mistake.
464 */
465 bool postCompleted = true;
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800466
467 try
468 {
469 std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
470 Value variant =
471 getDbusProperty(*dbus, "xyz.openbmc_project.State.OperatingSystem",
472 "/xyz/openbmc_project/state/os",
473 "xyz.openbmc_project.State.OperatingSystem.Status",
474 "OperatingSystemState");
Arun Lal K M382dc972022-01-20 22:18:23 +0000475 auto& value = std::get<std::string>(variant);
476
477 // The short strings "Standby" is deprecated in favor of the
478 // full enum strings. Support for the short strings will be
479 // removed in the future.
480 postCompleted = (value == "Standby") ||
481 (value == "xyz.openbmc_project.State.OperatingSystem."
482 "Status.OSStatus.Standby");
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800483 }
484 catch (const std::exception& e)
485 {
Arun Lal K M382dc972022-01-20 22:18:23 +0000486 phosphor::logging::log<phosphor::logging::level::ERR>(
487 "'getDbusProperty' failed to read "
488 "xyz.openbmc_project.State.OperatingSystem");
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800489 }
Arun Lal K M382dc972022-01-20 22:18:23 +0000490
491 return postCompleted;
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800492}
493
494/** @brief implement to get the Rest BIOS property
495 * @returns status
496 */
497static int getResetBIOSSettings(uint8_t& ResetFlag)
498{
499
500 try
501 {
502 std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
503 std::string service =
504 getService(*dbus, biosConfigIntf, biosConfigBaseMgrPath);
505 Value variant = getDbusProperty(*dbus, service, biosConfigBaseMgrPath,
506 biosConfigIntf, resetBIOSSettingsProp);
Suryakanth Sekarcc402592021-04-01 15:02:10 +0530507
508 std::string_view ResetStr = std::get<std::string>(variant);
509 if (ResetStr ==
510 "xyz.openbmc_project.BIOSConfig.Manager.ResetFlag.NoAction")
511 {
512 ResetFlag = 0;
513 }
514 else if (ResetStr == "xyz.openbmc_project.BIOSConfig.Manager.ResetFlag."
515 "FactoryDefaults")
516 {
517 ResetFlag = 1;
518 }
519 else if (ResetStr == "xyz.openbmc_project.BIOSConfig.Manager.ResetFlag."
520 "FailSafeDefaults")
521 {
522 ResetFlag = 2;
523 }
524 else
525 {
526 return ipmi::ccUnspecifiedError;
527 }
528
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800529 return ipmi::ccSuccess;
530 }
531 catch (const std::exception& e)
532 {
533 return ipmi::ccUnspecifiedError;
534 }
535}
536
Arun Lal K Me7725612021-07-15 18:20:58 +0000537/** @brief Get attributes data (bios base table) from bios.xml
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800538 */
Arun Lal K Me7725612021-07-15 18:20:58 +0000539static bool generateAttributesData()
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800540{
Arun Lal K Me7725612021-07-15 18:20:58 +0000541 try
542 {
543 bios::Xml biosxml(biosXMLFilePath);
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800544
Arun Lal K Me7725612021-07-15 18:20:58 +0000545 if (!biosxml.doDepexCompute())
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800546 {
Arun Lal K Me7725612021-07-15 18:20:58 +0000547 phosphor::logging::log<phosphor::logging::level::ERR>(
548 "'depex' compute failed");
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800549 }
Arun Lal K Me7725612021-07-15 18:20:58 +0000550
551 if (!biosxml.getBaseTable(attributesData))
552 {
553 phosphor::logging::log<phosphor::logging::level::ERR>(
554 "Failed to get bios base table");
555 }
556 }
Patrick Williamsbd51e6a2021-10-06 13:09:44 -0500557 catch (const std::exception& ex)
Arun Lal K Me7725612021-07-15 18:20:58 +0000558 {
559 phosphor::logging::log<phosphor::logging::level::ERR>(ex.what());
560 return false;
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800561 }
562
Arun Lal K Me7725612021-07-15 18:20:58 +0000563 return true;
564}
565
566/** @brief Generate attributes data from bios.xml
567 * and send attributes data (bios base table) to dbus using set method.
568 */
569static void generateAndSendAttributesData(std::string service,
570 uint8_t payloadType)
571{
572 if (!generateAttributesData())
573 {
574 phosphor::logging::log<phosphor::logging::level::ERR>(
575 "generateAndSendAttributesData: generateAttributesData - failed");
576 gNVOOBdata.payloadInfo[payloadType].payloadStatus =
577 static_cast<uint8_t>(ipmi::PStatus::Corrupted);
578 return;
579 }
580
581 phosphor::logging::log<phosphor::logging::level::INFO>(
582 "generateAndSendAttributesData : generateAttributesData is done");
583
584 if (!sendAllAttributes(service))
585 {
586 phosphor::logging::log<phosphor::logging::level::ERR>(
587 "generateAndSendAttributesData: sendAllAttributes - failed");
588 gNVOOBdata.payloadInfo[payloadType].payloadStatus =
589 static_cast<uint8_t>(ipmi::PStatus::Corrupted);
590 return;
591 }
592
593 phosphor::logging::log<phosphor::logging::level::INFO>(
594 "generateAndSendAttributesData : sendAllAttributes is done");
595 gNVOOBdata.payloadInfo[payloadType].payloadStatus =
596 static_cast<uint8_t>(ipmi::PStatus::Valid);
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800597}
598
599/** @brief implement executing the linux command to uncompress and generate the
600 * xmlfile
601 * @param[in] linux command
602 * @returns status
603 */
604template <typename... ArgTypes>
605static int generateBIOSXMLFile(const char* path, ArgTypes&&... tArgs)
606{
607
608 boost::process::child execProg(path, const_cast<char*>(tArgs)...,
609 boost::process::std_out > biosXMLFilePath);
610 execProg.wait();
611 return execProg.exit_code();
612}
613
614/** @brief implements to clean up the temp/ existing payload file
615 **/
616static void cleanUpPayloadFile(uint8_t& payloadType)
617{
618 // Clear the payload Information
619 std::string FilePath = "/var/oob/temp" + std::to_string(payloadType);
620 unlink(FilePath.c_str());
621 FilePath = "/var/oob/Payload" + std::to_string(payloadType);
622 unlink(FilePath.c_str());
623 if (payloadType == static_cast<uint8_t>(ipmi::PType::IntelXMLType0))
624 {
625 unlink("/var/oob/Payload1");
626 gNVOOBdata.payloadInfo[static_cast<uint8_t>(ipmi::PType::IntelXMLType1)]
627 .payloadStatus = static_cast<uint8_t>(ipmi::PStatus::Unknown);
628 }
629}
630
631/** @brief implements to create the oob folders and nv space
632 **/
633static Cc InitNVOOBdata()
634{
635 FILE* fptr;
636 uint16_t size;
637
638 if (!(std::filesystem::exists(biosConfigFolder)))
639 {
640 std::filesystem::create_directory(biosConfigFolder);
641 }
642
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000643 std::ifstream ifs(biosConfigNVPath, std::ios::in | std::ios::binary);
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800644
645 if (ifs.good())
646 {
647
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000648 ifs.seekg(std::ios_base::beg);
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800649 ifs.read(reinterpret_cast<char*>(&gNVOOBdata),
650 sizeof(struct NVOOBdata));
651 ifs.close();
652 return ipmi::ccSuccess;
653 }
654 return ipmi::ccResponseError;
655}
656
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800657ipmi::RspType<> ipmiOEMSetBIOSCap(ipmi::Context::ptr ctx,
658 uint8_t BIOSCapabilties, uint8_t reserved1,
659 uint8_t reserved2, uint8_t reserved3)
660{
Arun Lal K M3a1be322022-02-08 21:37:30 +0000661 if (getPostCompleted())
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800662 {
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800663 return ipmi::response(ipmiCCNotSupportedInCurrentState);
664 }
Arun Lal K M3a1be322022-02-08 21:37:30 +0000665
666 if (reserved1 != 0 || reserved2 != 0 || reserved3 != 0)
667 {
668 return ipmi::responseInvalidFieldRequest();
669 }
670
671 gNVOOBdata.mBIOSCapabilities.OOBCapability = BIOSCapabilties;
672 gNVOOBdata.mIsBIOSCapInitDone = true;
673
674 flushNVOOBdata();
675 return ipmi::responseSuccess();
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800676}
677
678ipmi::RspType<uint8_t, uint8_t, uint8_t, uint8_t>
679 ipmiOEMGetBIOSCap(ipmi::Context::ptr ctx)
680{
681 if (gNVOOBdata.mIsBIOSCapInitDone)
682 {
683 return ipmi::responseSuccess(gNVOOBdata.mBIOSCapabilities.OOBCapability,
684 0, 0, 0);
685 }
686 else
687 {
688 return ipmi::response(ipmiCCBIOSCapabilityInitNotDone);
689 }
690}
691
692ipmi::RspType<uint32_t> ipmiOEMSetPayload(ipmi::Context::ptr ctx,
693 uint8_t paramSel, uint8_t payloadType,
694 std::vector<uint8_t> payload)
695{
696 uint8_t biosCapOffsetBit = 2; // BIT:1 0-OOB BIOS config not supported
697 // 1-OOB BIOS config is supported
698
699 if (!(gNVOOBdata.mBIOSCapabilities.OOBCapability & (biosCapOffsetBit)))
700 {
701 return ipmi::response(ipmiCCBIOSCapabilityInitNotDone);
702 }
Arun Lal K M382dc972022-01-20 22:18:23 +0000703
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800704 // Validate the Payload Type
705 if (payloadType > maxPayloadSupported)
706 {
707 return ipmi::responseInvalidFieldRequest();
708 }
709
710 // We should support this Payload type 0 command only in KCS Interface
711 if (payloadType == static_cast<uint8_t>(ipmi::PType::IntelXMLType0))
712 {
Arun Lal K M3a1be322022-02-08 21:37:30 +0000713 if (getPostCompleted())
714 {
715 return ipmi::response(ipmiCCNotSupportedInCurrentState);
716 }
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800717 }
718
719 switch (static_cast<PTState>(paramSel))
720 {
721 case ipmi::PTState::StartTransfer:
722 {
723 PayloadStartTransfer* pPayloadStartTransfer =
724 reinterpret_cast<PayloadStartTransfer*>(payload.data());
725 if (payload.size() < sizeof(PayloadStartTransfer))
726 {
727 phosphor::logging::log<phosphor::logging::level::ERR>(
728 "ipmiOEMSetPayload: BIOS Config Payload size is not "
729 "correct");
730 return ipmi::responseReqDataLenInvalid();
731 }
732 cleanUpPayloadFile(payloadType);
733
734 gNVOOBdata.payloadInfo[payloadType].payloadReservationID = rand();
735 gNVOOBdata.payloadInfo[payloadType].payloadTotalChecksum =
736 pPayloadStartTransfer->payloadTotalChecksum;
737 gNVOOBdata.payloadInfo[payloadType].payloadTotalSize =
738 pPayloadStartTransfer->payloadTotalSize;
739 gNVOOBdata.payloadInfo[payloadType].payloadVersion =
740 pPayloadStartTransfer->payloadVersion;
741 gNVOOBdata.payloadInfo[payloadType].actualTotalPayloadWritten = 0;
742 gNVOOBdata.payloadInfo[payloadType].payloadStatus =
743 static_cast<uint8_t>(ipmi::PStatus::Unknown);
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000744 gNVOOBdata.payloadInfo[payloadType].payloadType = payloadType;
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800745
746 return ipmi::responseSuccess(
747 gNVOOBdata.payloadInfo[payloadType].payloadReservationID);
748 }
749 break;
750
751 case ipmi::PTState::InProgress:
752 {
753 PayloadInProgress* pPayloadInProgress =
754 reinterpret_cast<PayloadInProgress*>(payload.data());
755 PayloadInfo payloadInfo = gNVOOBdata.payloadInfo[payloadType];
756
757 if (payload.size() < sizeof(PayloadInProgress))
758 {
759 phosphor::logging::log<phosphor::logging::level::ERR>(
760 "BIOS Config Payload size is not correct");
761 return ipmi::responseReqDataLenInvalid();
762 }
763
764 if (pPayloadInProgress->payloadReservationID !=
765 payloadInfo.payloadReservationID)
766 {
Arun Lal K Mb0caca02021-09-05 22:09:33 +0000767 phosphor::logging::log<phosphor::logging::level::ERR>(
768 "BIOS Config Payload reservation ID is not correct");
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800769 return ipmi::responseInvalidReservationId();
770 }
771 payloadInfo.payloadCurrentSize =
772 pPayloadInProgress->payloadCurrentSize;
773 // Need to verify the current Payload Checksum
774 const uint8_t* data =
775 reinterpret_cast<const uint8_t*>(payload.data());
776 // we have to remove the current size, current offset, current
777 // length,checksum bytes , reservation bytes
778 boost::crc_32_type calcChecksum;
779 calcChecksum.process_bytes(data + 16, payload.size() - 16);
780 if (calcChecksum.checksum() !=
781 pPayloadInProgress->payloadCurrentChecksum)
782 {
783 phosphor::logging::log<phosphor::logging::level::ERR>(
784 "ipmiOEMSetPayload: Payload Checksum Failed");
785 return ipmi::response(ipmiCCPayloadChecksumFailed);
786 }
787 // store the data in temp file
788 std::string FilePath =
789 "/var/oob/temp" + std::to_string(payloadType);
790
791 std::ofstream outFile(FilePath, std::ios::binary | std::ios::app);
792 outFile.seekp(pPayloadInProgress->payloadOffset);
793 // we have to remove the current size, current offset, current
794 // length,checksum bytes , reservation bytes
795
796 const char* writedata =
797 reinterpret_cast<const char*>(payload.data());
798 outFile.write(writedata + 16, payload.size() - 16);
799 outFile.close();
800
801 gNVOOBdata.payloadInfo[payloadType].payloadStatus =
802 static_cast<uint8_t>(ipmi::PStatus::Unknown);
803 gNVOOBdata.payloadInfo[payloadType].actualTotalPayloadWritten +=
804 payloadInfo.payloadCurrentSize;
805 return ipmi::responseSuccess(payloadInfo.payloadCurrentSize);
806 }
807 break;
808 case ipmi::PTState::EndTransfer:
809 {
810 PayloadEndTransfer* pPayloadEndTransfer =
811 reinterpret_cast<PayloadEndTransfer*>(payload.data());
812 PayloadInfo payloadInfo = gNVOOBdata.payloadInfo[payloadType];
813 if (pPayloadEndTransfer->payloadReservationID !=
814 payloadInfo.payloadReservationID)
815 {
816 return ipmi::responseInvalidReservationId();
817 }
818 gNVOOBdata.payloadInfo[payloadType].payloadStatus =
819 static_cast<uint8_t>(ipmi::PStatus::Unknown);
820
821 if (gNVOOBdata.payloadInfo[payloadType].actualTotalPayloadWritten !=
822 gNVOOBdata.payloadInfo[payloadType].payloadTotalSize)
823 {
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800824 return ipmi::response(ipmiCCPayloadPayloadInComplete);
825 }
826 std::string tempFilePath =
827 "/var/oob/temp" + std::to_string(payloadType);
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000828 std::string payloadFilePath =
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800829 "/var/oob/Payload" + std::to_string(payloadType);
830 auto renamestatus =
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000831 std::rename(tempFilePath.c_str(), payloadFilePath.c_str());
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800832 if (renamestatus)
833 {
834 phosphor::logging::log<phosphor::logging::level::ERR>(
835 "ipmiOEMSetPayload: Renaming Payload file - failed");
836 }
837
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800838 if (payloadType == static_cast<uint8_t>(ipmi::PType::IntelXMLType0))
839 {
840 // Unzip the Intel format XML file type 0
841 auto response = generateBIOSXMLFile("/usr/bin/lzcat", "-d",
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000842 payloadFilePath.c_str());
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800843 if (response)
844 {
845
846 phosphor::logging::log<phosphor::logging::level::ERR>(
847 "ipmiOEMSetPayload: generateBIOSXMLFile - failed");
848 gNVOOBdata.payloadInfo[payloadType].payloadStatus =
849 static_cast<uint8_t>(ipmi::PStatus::Corrupted);
850 return ipmi::response(ipmiCCPayloadPayloadPacketMissed);
851 }
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000852 phosphor::logging::log<phosphor::logging::level::INFO>(
853 " ipmiOEMSetPayload : Convert XML into native-dbus DONE");
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000854
Arun Lal K Me7725612021-07-15 18:20:58 +0000855 /* So that we don't block the call */
856 auto io = getIoContext();
857 auto dbus = getSdBus();
858 if (io && dbus)
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000859 {
Arun Lal K Me7725612021-07-15 18:20:58 +0000860 std::string service = getService(*dbus, biosConfigIntf,
861 biosConfigBaseMgrPath);
862
863 boost::asio::post(*io, [service, payloadType] {
864 generateAndSendAttributesData(service, payloadType);
865 });
866 }
867 else
868 {
869 phosphor::logging::log<phosphor::logging::level::INFO>(
870 "ipmiOEMSetPayload: Unable to get io context or sdbus");
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000871 return ipmi::responseResponseError();
872 }
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800873 }
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800874
875 struct stat filestat;
876
877 /* Get entry's information. */
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000878 if (!stat(payloadFilePath.c_str(), &filestat))
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800879 {
880 gNVOOBdata.payloadInfo[payloadType].payloadTimeStamp =
881 filestat.st_mtime;
882 gNVOOBdata.payloadInfo[payloadType].payloadTotalSize =
883 filestat.st_size;
Snehalatha Venkatesh0d0dc342022-01-20 11:36:56 +0000884 gNVOOBdata.payloadInfo[payloadType].payloadStatus =
885 static_cast<uint8_t>(ipmi::PStatus::Valid);
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800886 }
887 else
888 {
889 return ipmi::responseResponseError();
890 }
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800891 flushNVOOBdata();
892 return ipmi::responseSuccess(
893 gNVOOBdata.payloadInfo[payloadType].actualTotalPayloadWritten);
894 }
895 break;
896 case ipmi::PTState::UserAbort:
897 {
898 PayloadEndTransfer* pPayloadEndTransfer =
899 reinterpret_cast<PayloadEndTransfer*>(payload.data());
900 PayloadInfo payloadInfo = gNVOOBdata.payloadInfo[payloadType];
901 if (pPayloadEndTransfer->payloadReservationID !=
902 payloadInfo.payloadReservationID)
903 {
904 return ipmi::responseInvalidReservationId();
905 }
906 gNVOOBdata.payloadInfo[payloadType].payloadReservationID = 0;
907 gNVOOBdata.payloadInfo[payloadType].payloadType = 0;
908 gNVOOBdata.payloadInfo[payloadType].payloadTotalSize = 0;
909 // Delete the temp file
910 std::string tempFilePath =
911 "/var/oob/temp" + std::to_string(payloadType);
912 unlink(tempFilePath.c_str());
913 flushNVOOBdata();
914 return ipmi::responseSuccess();
915 }
916 break;
917 default:
918 return ipmi::responseInvalidFieldRequest();
919 }
920 return ipmi::responseResponseError();
921}
922
923ipmi::RspType<message::Payload>
924 ipmiOEMGetPayload(ipmi::Context::ptr ctx, uint8_t paramSel,
925 uint8_t payloadType, ipmi::message::Payload& payload)
926{
927 // 1-OOB BIOS config is supported
928 message::Payload retValue;
929
930 if (!(gNVOOBdata.mBIOSCapabilities.OOBCapability & (biosCapOffsetBit)))
931 {
932 return ipmi::response(ipmiCCBIOSCapabilityInitNotDone);
933 }
934 // Validate the Payload Type
935 if (payloadType > maxPayloadSupported)
936 {
937 return ipmi::responseInvalidFieldRequest();
938 }
939
Arun Lal K Mb0caca02021-09-05 22:09:33 +0000940 if (payloadType == static_cast<uint8_t>(ipmi::PType::IntelXMLType1))
941 {
942 if (!payload1::update(ctx))
943 {
944 phosphor::logging::log<phosphor::logging::level::ERR>(
945 "ipmiOEMGetPayload: unable to update NVOOBdata for payloadType "
946 "= IntelXMLType1");
947 return ipmi::response(ipmi::ccUnspecifiedError);
948 }
949 }
950
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800951 struct PayloadInfo res = gNVOOBdata.payloadInfo[payloadType];
952
953 switch (static_cast<GetPayloadParameter>(paramSel))
954 {
955 case ipmi::GetPayloadParameter::GetPayloadInfo:
956 {
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000957 std::string payloadFilePath =
958 "/var/oob/Payload" + std::to_string(payloadType);
959
960 std::ifstream ifs(payloadFilePath,
961 std::ios::in | std::ios::binary | std::ios::ate);
962
963 if (!ifs.good())
964 {
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000965 phosphor::logging::log<phosphor::logging::level::ERR>(
966 "ipmiOEMGetPayload: Payload File Error");
967 // File does not exist code here
968 return ipmi::response(ipmi::ccUnspecifiedError);
969 }
Arun Lal K Mb0caca02021-09-05 22:09:33 +0000970
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000971 ifs.close();
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800972 retValue.pack(res.payloadVersion);
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000973 retValue.pack(payloadType);
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800974 retValue.pack(res.payloadTotalSize);
975 retValue.pack(res.payloadTotalChecksum);
976 retValue.pack(res.payloadflag);
977 retValue.pack(res.payloadStatus);
978 retValue.pack(res.payloadTimeStamp);
979
980 return ipmi::responseSuccess(std::move(retValue));
981 }
982
983 break;
984 case ipmi::GetPayloadParameter::GetPayloadData:
985 {
986 if (res.payloadStatus ==
987 (static_cast<uint8_t>(ipmi::PStatus::Valid)))
988 {
989 std::vector<uint32_t> reqData;
990 if (payload.unpack(reqData) || !payload.fullyUnpacked())
991 {
992 return ipmi::responseReqDataLenInvalid();
993 }
994 uint32_t offset = reqData.at(0);
995 uint32_t length = reqData.at(1);
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000996 std::string payloadFilePath =
997 "/var/oob/Payload" + std::to_string(payloadType);
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800998
Snehalatha Venkatesh0d0dc342022-01-20 11:36:56 +0000999 if (length > static_cast<uint32_t>(maxGetPayloadDataSize))
Snehalatha Venkatesh2ff15bf2021-12-30 11:51:14 +00001000 {
1001 phosphor::logging::log<phosphor::logging::level::ERR>(
1002 "ipmiOEMGetPayload: length > maxGetPayloadDataSize",
1003 phosphor::logging::entry("LENGTH=%d", length),
1004 phosphor::logging::entry("maxGetPayloadDataSize=%d",
1005 maxGetPayloadDataSize));
1006 return ipmi::responseInvalidFieldRequest();
1007 }
1008
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +00001009 std::ifstream ifs(payloadFilePath, std::ios::in |
1010 std::ios::binary |
1011 std::ios::ate);
1012
1013 if (!ifs.good())
1014 {
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +00001015 phosphor::logging::log<phosphor::logging::level::ERR>(
1016 "ipmiOEMGetPayload: Payload File Error");
1017 // File does not exist code here
1018 return ipmi::response(ipmi::ccUnspecifiedError);
1019 }
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001020 std::ifstream::pos_type fileSize = ifs.tellg();
1021 // Total file data within given offset
1022 if (fileSize < static_cast<uint64_t>(offset))
1023 {
Snehalatha Venkatesh2ff15bf2021-12-30 11:51:14 +00001024 phosphor::logging::log<phosphor::logging::level::ERR>(
1025 "ipmiOEMGetPayload: filesize < offset");
1026 return ipmi::responseInvalidFieldRequest();
1027 }
1028
1029 if ((static_cast<uint64_t>(fileSize) - offset) < length)
1030 {
1031 phosphor::logging::log<phosphor::logging::level::ERR>(
1032 "ipmiOEMGetPayload: (filesize - offset) < length ");
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001033 return ipmi::responseInvalidFieldRequest();
1034 }
1035
1036 ifs.seekg(offset, std::ios::beg);
1037 std::array<uint8_t, maxGetPayloadDataSize> Buffer;
1038 ifs.read(reinterpret_cast<char*>(Buffer.data()), length);
1039 uint32_t readCount = ifs.gcount();
1040 ifs.close();
1041
1042 boost::crc_32_type calcChecksum;
1043 calcChecksum.process_bytes(
1044 reinterpret_cast<char*>(Buffer.data()), readCount);
1045 uint32_t chkSum = calcChecksum.checksum();
1046 retValue.pack(payloadType);
1047 retValue.pack(readCount);
1048 retValue.pack(chkSum);
1049
1050 for (int i = 0; i < readCount; i++)
1051 {
1052 retValue.pack(Buffer.at(i));
1053 }
Arun Lal K Mb0caca02021-09-05 22:09:33 +00001054
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001055 return ipmi::responseSuccess(std::move(retValue));
1056 }
1057 else
1058 {
1059 return ipmi::responseResponseError();
1060 }
1061 }
1062 break;
1063 case ipmi::GetPayloadParameter::GetPayloadStatus:
1064 {
1065 retValue.pack(gNVOOBdata.payloadInfo[payloadType].payloadStatus);
1066 return ipmi::responseSuccess(std::move(retValue));
1067 }
1068 break;
1069 default:
1070 return ipmi::responseInvalidFieldRequest();
1071 }
1072 return ipmi::responseInvalidFieldRequest();
1073}
1074
1075ipmi::RspType<> ipmiOEMSetBIOSHashInfo(
1076 ipmi::Context::ptr ctx, std::array<uint8_t, maxSeedSize>& pwdSeed,
Ayushi Smriti32381872021-06-23 11:05:48 +05301077 uint8_t algoInfo, std::array<uint8_t, maxHashSize>& adminPwdHash)
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001078{
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001079 // We should not support this command after System Booted - After Exit Boot
1080 // service called
Arun Lal K M382dc972022-01-20 22:18:23 +00001081 if (getPostCompleted())
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001082 {
Ayushi Smriti32381872021-06-23 11:05:48 +05301083 return ipmi::response(ipmiCCNotSupportedInCurrentState);
1084 }
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001085
Ayushi Smriti32381872021-06-23 11:05:48 +05301086 nlohmann::json json;
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001087
Ayushi Smriti32381872021-06-23 11:05:48 +05301088 if ((algoInfo & 0xF) == algoSHA384)
1089 {
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001090 json["HashAlgo"] = "SHA384";
Ayushi Smriti32381872021-06-23 11:05:48 +05301091 }
1092 else if ((algoInfo & 0xF) == algoSHA256)
1093 {
1094 json["HashAlgo"] = "SHA256";
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001095 }
1096 else
1097 {
Ayushi Smriti32381872021-06-23 11:05:48 +05301098 return ipmi::responseInvalidFieldRequest();
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001099 }
Ayushi Smriti32381872021-06-23 11:05:48 +05301100
1101 json["Seed"] = pwdSeed;
1102 json["IsAdminPwdChanged"] = false;
1103 json["AdminPwdHash"] = adminPwdHash;
1104 json["IsUserPwdChanged"] = false;
1105
1106 std::array<uint8_t, maxHashSize> userPwdHash;
1107 userPwdHash.fill({}); // initializing with 0 as user password hash field
1108 // is not used presently
1109 json["UserPwdHash"] = userPwdHash;
1110 json["StatusFlag"] = algoInfo;
1111
1112 std::string hashFilePath = "/var/lib/bios-settings-manager/seedData";
1113 std::ofstream ofs(hashFilePath, std::ios::out);
1114 const auto& writeData = json.dump();
1115 ofs << writeData;
1116 ofs.close();
1117 return ipmi::responseSuccess();
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001118}
1119
Ayushi Smriti32381872021-06-23 11:05:48 +05301120ipmi::RspType<std::array<uint8_t, maxSeedSize>, uint8_t,
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001121 std::array<uint8_t, maxHashSize>>
1122 ipmiOEMGetBIOSHash(ipmi::Context::ptr ctx)
1123{
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001124 nlohmann::json data = nullptr;
1125
Arun Lal K M1d0bac92022-02-11 00:23:13 +00001126 // We should not support this command after System Booted - After Exit Boot
1127 // service called
Arun Lal K M3a1be322022-02-08 21:37:30 +00001128 if (getPostCompleted())
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001129 {
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001130 return ipmi::response(ipmiCCNotSupportedInCurrentState);
1131 }
Arun Lal K M3a1be322022-02-08 21:37:30 +00001132
1133 std::string HashFilePath = "/var/lib/bios-settings-manager/seedData";
1134
1135 std::ifstream devIdFile(HashFilePath);
1136 if (!devIdFile.is_open())
1137 {
1138 return ipmi::responseResponseError();
1139 }
1140
1141 try
1142 {
1143 data = nlohmann::json::parse(devIdFile, nullptr, false);
1144 }
1145 catch (const nlohmann::json::parse_error& e)
1146 {
1147 return ipmi::responseResponseError();
1148 }
1149
1150 if (data.is_discarded())
1151 {
1152 return ipmi::responseResponseError();
1153 }
1154
1155 std::array<uint8_t, maxHashSize> newAdminHash;
1156 std::array<uint8_t, maxSeedSize> seed;
1157
1158 uint8_t flag = 0;
1159 uint8_t adminPwdChangedFlag = 0;
1160 if (!data.is_discarded())
1161 {
1162
1163 adminPwdChangedFlag = data["IsAdminPwdChanged"];
1164 newAdminHash = data["AdminPwdHash"];
1165 seed = data["Seed"];
1166 }
1167
1168 auto status = getResetBIOSSettings(flag);
1169 if (status)
1170 {
1171 return ipmi::responseResponseError();
1172 }
Snehalatha Venkatesh6346e982022-03-09 06:49:18 +00001173 if (flag)
1174 {
1175 flag |= restoreDefaultValues;
1176 }
Arun Lal K M3a1be322022-02-08 21:37:30 +00001177 if (adminPwdChangedFlag)
1178 {
1179 flag |= adminPasswordChanged;
1180 }
1181
1182 std::copy(std::begin(newAdminHash), std::end(newAdminHash),
1183 std::begin(newAdminHash));
1184
1185 return ipmi::responseSuccess(seed, flag, newAdminHash);
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001186}
1187
1188static void registerBIOSConfigFunctions(void)
1189{
1190 phosphor::logging::log<phosphor::logging::level::INFO>(
1191 "BIOSConfig module initialization");
1192 InitNVOOBdata();
1193
1194 registerHandler(prioOemBase, intel::netFnGeneral,
1195 intel::general::cmdSetBIOSCap, Privilege::Admin,
1196 ipmiOEMSetBIOSCap);
1197
1198 registerHandler(prioOemBase, intel::netFnGeneral,
1199 intel::general::cmdGetBIOSCap, Privilege::User,
1200 ipmiOEMGetBIOSCap);
1201 registerHandler(prioOemBase, intel::netFnGeneral,
1202 intel::general::cmdSetBIOSPwdHashInfo, Privilege::Admin,
1203 ipmiOEMSetBIOSHashInfo);
1204
1205 registerHandler(prioOemBase, intel::netFnGeneral,
1206 intel::general::cmdGetBIOSPwdHash, Privilege::User,
1207 ipmiOEMGetBIOSHash);
1208
1209 registerHandler(prioOemBase, intel::netFnGeneral,
1210 intel::general::cmdGetPayload, Privilege::User,
1211 ipmiOEMGetPayload);
1212 registerHandler(prioOemBase, intel::netFnGeneral,
1213 intel::general::cmdSetPayload, Privilege::Admin,
1214 ipmiOEMSetPayload);
1215
1216 return;
1217}
1218
1219} // namespace ipmi