blob: 3ae45825a33c4e02478ce871444db5a235f4619b [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);
55
56static constexpr const char* biosConfigFolder = "/var/oob";
57static constexpr const char* biosConfigNVPath = "/var/oob/nvoobdata.dat";
58static constexpr const uint8_t algoSHA384 = 2;
Ayushi Smriti32381872021-06-23 11:05:48 +053059static constexpr const uint8_t algoSHA256 = 1;
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +080060static constexpr const uint8_t biosCapOffsetBit = 0x3;
61static constexpr uint16_t maxGetPayloadDataSize = 4096;
62static constexpr const char* biosXMLFilePath = "/var/oob/bios.xml";
63static constexpr const char* biosXMLFilePath1 = "/var/oob/tempbios.xml";
64
65static constexpr const char* biosConfigBaseMgrPath =
66 "/xyz/openbmc_project/bios_config/manager";
67static constexpr const char* biosConfigIntf =
68 "xyz.openbmc_project.BIOSConfig.Manager";
69static constexpr const char* resetBIOSSettingsProp = "ResetBIOSSettings";
70/*baseBIOSTable
71map{attributeName,struct{attributeType,readonlyStatus,displayname,
72 description,menuPath,current,default,
73 array{struct{optionstring,optionvalue}}}}
74*/
Arun Lal K Me7725612021-07-15 18:20:58 +000075
76bios::BiosBaseTableType attributesData;
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +080077
78NVOOBdata gNVOOBdata;
79
80enum class PTState : uint8_t
81{
82 StartTransfer = 0,
83 InProgress = 1,
84 EndTransfer = 2,
85 UserAbort = 3
86};
87enum class PStatus : uint8_t
88{
89 Unknown = 0,
90 Valid = 1,
91 Corrupted = 2
92};
93enum class PType : uint8_t
94{
95 IntelXMLType0 = 0,
96 IntelXMLType1 = 1,
97 OTAPayload = 5,
98};
99
100//
101// GetPayload Payload status enumeration
102//
103enum class GetPayloadParameter : uint8_t
104{
105 GetPayloadInfo = 0, // 0
106 GetPayloadData = 1, // 1
107 GetPayloadStatus = 2
108};
109
Arun Lal K Mb0caca02021-09-05 22:09:33 +0000110namespace payload1
111{
112
113enum class AttributesType : uint8_t
114{
115 unknown = 0,
116 string,
Arun Lal K Md2d60ab2021-12-29 19:42:03 +0000117 integer,
118 enumeration
Arun Lal K Mb0caca02021-09-05 22:09:33 +0000119};
120
121using PendingAttributesType =
122 std::map<std::string,
123 std::tuple<std::string, std::variant<int64_t, std::string>>>;
124
125AttributesType getAttrType(const std::string_view typeDbus)
126{
127 if (typeDbus == "xyz.openbmc_project.BIOSConfig.Manager."
128 "AttributeType.String")
129 {
130 return AttributesType::string;
131 }
132 else if (typeDbus == "xyz.openbmc_project.BIOSConfig."
133 "Manager.AttributeType.Integer")
134 {
135 return AttributesType::integer;
136 }
Arun Lal K Md2d60ab2021-12-29 19:42:03 +0000137 else if (typeDbus == "xyz.openbmc_project.BIOSConfig."
138 "Manager.AttributeType.Enumeration")
139 {
140 return AttributesType::enumeration;
141 }
Arun Lal K Mb0caca02021-09-05 22:09:33 +0000142
143 return AttributesType::unknown;
144}
145
146bool fillPayloadData(std::string& payloadData,
147 const std::variant<int64_t, std::string>& attributes,
148 const std::string_view key, AttributesType& attrType)
149{
150 payloadData += key;
151 payloadData += '=';
152
Arun Lal K Md2d60ab2021-12-29 19:42:03 +0000153 if (attrType == AttributesType::string ||
154 attrType == AttributesType::enumeration)
Arun Lal K Mb0caca02021-09-05 22:09:33 +0000155 {
156 if (!std::holds_alternative<std::string>(attributes))
157 {
158 phosphor::logging::log<phosphor::logging::level::ERR>(
159 "fillPayloadData: No string data in attributes");
160 return false;
161 }
162 payloadData += std::get<std::string>(attributes);
163 }
164 else if (attrType == AttributesType::integer)
165 {
166 if (!std::holds_alternative<int64_t>(attributes))
167 {
168 phosphor::logging::log<phosphor::logging::level::ERR>(
169 "fillPayloadData: No int64_t data in attributes");
170 return false;
171 }
172 payloadData += std::to_string(std::get<int64_t>(attributes));
173 }
174 else
175 {
176 phosphor::logging::log<phosphor::logging::level::ERR>(
177 "fillPayloadData: Unsupported attribute type");
178 return false;
179 }
180
181 payloadData += '\n';
182
183 return true;
184}
185
186bool getPendingList(ipmi::Context::ptr ctx, std::string& payloadData)
187{
188 std::variant<PendingAttributesType> pendingAttributesData;
189 boost::system::error_code ec;
190
191 payloadData.clear();
192
193 auto dbus = getSdBus();
194 if (!dbus)
195 {
196 phosphor::logging::log<phosphor::logging::level::ERR>(
197 "getPendingList: getSdBus() failed");
198 return false;
199 }
200
201 std::string service =
202 getService(*dbus, biosConfigIntf, biosConfigBaseMgrPath);
203
204 try
205 {
206 pendingAttributesData =
207 dbus->yield_method_call<std::variant<PendingAttributesType>>(
208 ctx->yield, ec, service,
209 "/xyz/openbmc_project/bios_config/manager",
210 "org.freedesktop.DBus.Properties", "Get",
211 "xyz.openbmc_project.BIOSConfig.Manager", "PendingAttributes");
212 }
Patrick Williamsbd51e6a2021-10-06 13:09:44 -0500213 catch (const std::exception& ex)
Arun Lal K Mb0caca02021-09-05 22:09:33 +0000214 {
215 phosphor::logging::log<phosphor::logging::level::ERR>(ex.what());
216 return false;
217 }
218
219 if (ec)
220 {
221 std::string err = "getPendingList: error while trying to get "
222 "PendingAttributes, error = ";
223 err += ec.message();
224
225 phosphor::logging::log<phosphor::logging::level::ERR>(err.c_str());
226
227 return false;
228 }
229
230 const PendingAttributesType* pendingAttributes =
231 std::get_if<PendingAttributesType>(&pendingAttributesData);
232 if (!pendingAttributes)
233 {
234 phosphor::logging::log<phosphor::logging::level::ERR>(
235 "getPendingList: pendingAttributes is null");
236 return false;
237 }
238
239 for (const auto& [key, attributes] : *pendingAttributes)
240 {
241 const std::string& itemType = std::get<0>(attributes);
242 AttributesType attrType = getAttrType(itemType);
243
244 if (!fillPayloadData(payloadData, std::get<1>(attributes), key,
245 attrType))
246 {
247 return false;
248 }
249 }
250
251 if (payloadData.empty())
252 {
253 phosphor::logging::log<phosphor::logging::level::ERR>(
254 "getPendingList: payloadData is empty");
255 return false;
256 }
257
258 return true;
259}
260bool updatePayloadFile(std::string& payloadFilePath, std::string payloadData)
261{
262 std::ofstream payloadFile(payloadFilePath,
263 std::ios::out | std::ios::binary);
264
265 payloadFile << payloadData;
266
267 if (!payloadFile.good())
268 {
269 return false;
270 }
271
272 return true;
273}
274
275bool computeCheckSum(std::string& payloadFilePath,
276 boost::crc_32_type& calcChecksum)
277{
278 std::ifstream payloadFile(payloadFilePath.c_str(),
279 std::ios::in | std::ios::binary | std::ios::ate);
280
281 if (!payloadFile.good())
282 {
283 phosphor::logging::log<phosphor::logging::level::ERR>(
284 "computeCheckSum: Cannot open Payload1 file");
285 return false;
286 }
287
288 payloadFile.seekg(0, payloadFile.end);
289 int length = payloadFile.tellg();
290 payloadFile.seekg(0, payloadFile.beg);
291
292 if (maxGetPayloadDataSize < length)
293 {
294 phosphor::logging::log<phosphor::logging::level::ERR>(
295 "computeCheckSum: length > maxGetPayloadDataSize");
296 return false;
297 }
298
299 std::unique_ptr<char[]> payloadBuffer(new char[length]);
300
301 payloadFile.read(payloadBuffer.get(), length);
302 uint32_t readCount = payloadFile.gcount();
303
304 calcChecksum.process_bytes(payloadBuffer.get(), readCount);
305
306 return true;
307}
308
309bool updatePayloadInfo(std::string& payloadFilePath)
310{
311 boost::crc_32_type calcChecksum;
312
313 uint8_t payloadType = static_cast<uint8_t>(ipmi::PType::IntelXMLType1);
314 auto& payloadInfo = gNVOOBdata.payloadInfo[payloadType];
315
316 if (!computeCheckSum(payloadFilePath, calcChecksum))
317 {
318 phosphor::logging::log<phosphor::logging::level::ERR>(
319 "updatePayloadInfo: Cannot compute checksum for Payload1 file");
320 return false;
321 }
322
323 payloadInfo.payloadVersion = 0;
324 payloadInfo.payloadflag = 0;
325 payloadInfo.payloadReservationID = rand();
326
327 payloadInfo.payloadType = payloadType;
328
329 payloadInfo.payloadTotalChecksum = calcChecksum.checksum();
330 payloadInfo.payloadCurrentChecksum = payloadInfo.payloadTotalChecksum;
331
332 payloadInfo.payloadStatus = (static_cast<uint8_t>(ipmi::PStatus::Valid));
333
334 struct stat filestat;
335 /* Get entry's information. */
336 if (!stat(payloadFilePath.c_str(), &filestat))
337 {
338 payloadInfo.payloadTimeStamp = filestat.st_mtime;
339 payloadInfo.payloadTotalSize = filestat.st_size;
340 payloadInfo.payloadCurrentSize = filestat.st_size;
341 payloadInfo.actualTotalPayloadWritten = filestat.st_size;
342 }
343 else
344 {
345 phosphor::logging::log<phosphor::logging::level::ERR>(
346 "updatePayloadInfo: Cannot get file status for Payload1 file");
347 return false;
348 }
349
350 if (!flushNVOOBdata())
351 {
352 phosphor::logging::log<phosphor::logging::level::ERR>(
353 "updatePayloadInfo: flushNVOOBdata failed");
354 return false;
355 }
356
357 return true;
358}
359
360bool update(ipmi::Context::ptr ctx)
361{
362 std::string payloadFilePath =
363 "/var/oob/Payload" +
364 std::to_string(static_cast<uint8_t>(ipmi::PType::IntelXMLType1));
365
366 std::string payloadData;
367
368 if (!getPendingList(ctx, payloadData))
369 {
370 phosphor::logging::log<phosphor::logging::level::ERR>(
371 "payload1::update : getPendingList() failed");
372 return false;
373 }
374
375 if (!updatePayloadFile(payloadFilePath, payloadData))
376 {
377 phosphor::logging::log<phosphor::logging::level::ERR>(
378 "payload1::update : updatePayloadFile() failed");
379 return false;
380 }
381
382 if (!updatePayloadInfo(payloadFilePath))
383 {
384 phosphor::logging::log<phosphor::logging::level::ERR>(
385 "payload1::update : updatePayloadInfo() failed");
386 return false;
387 }
388
389 return true;
390}
391} // namespace payload1
392
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800393/** @brief implement to set the BaseBIOSTable property
394 * @returns status
395 */
Arun Lal K Me7725612021-07-15 18:20:58 +0000396static bool sendAllAttributes(std::string service)
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800397{
Arun Lal K Me7725612021-07-15 18:20:58 +0000398 std::shared_ptr<sdbusplus::asio::connection> pSdBusPlus = getSdBus();
399
400 if (pSdBusPlus)
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800401 {
Arun Lal K Me7725612021-07-15 18:20:58 +0000402 try
403 {
404 pSdBusPlus->async_method_call(
405 [](const boost::system::error_code ec) {
406 /* No more need to keep attributes data in memory */
407 attributesData.clear();
408
409 if (ec)
410 {
411 phosphor::logging::log<phosphor::logging::level::ERR>(
412 "sendAllAttributes error: send all attributes - "
413 "failed");
414 return;
415 }
416
417 phosphor::logging::log<phosphor::logging::level::INFO>(
418 "sendAllAttributes: send all attributes - done");
419 },
420 service, biosConfigBaseMgrPath,
421 "org.freedesktop.DBus.Properties", "Set", biosConfigIntf,
422 "BaseBIOSTable",
423 std::variant<bios::BiosBaseTableType>(attributesData));
424
425 return true;
426 }
Patrick Williamsbd51e6a2021-10-06 13:09:44 -0500427 catch (const std::exception& ex)
Arun Lal K Me7725612021-07-15 18:20:58 +0000428 {
429 phosphor::logging::log<phosphor::logging::level::ERR>(ex.what());
430 }
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800431 }
Arun Lal K Me7725612021-07-15 18:20:58 +0000432
433 return false;
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800434}
435
436/** @brief implement to flush the updated data in nv space
437 * @returns status
438 */
Arun Lal K Mb0caca02021-09-05 22:09:33 +0000439static bool flushNVOOBdata()
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800440{
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000441 std::ofstream outFile(biosConfigNVPath, std::ios::binary);
Arun Lal K Mb0caca02021-09-05 22:09:33 +0000442
443 outFile.seekp(std::ios_base::beg);
444 const char* writedata = reinterpret_cast<const char*>(&gNVOOBdata);
445 outFile.write(writedata, sizeof(struct NVOOBdata));
446
447 if (!outFile.good())
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800448 {
Arun Lal K Mb0caca02021-09-05 22:09:33 +0000449 return false;
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800450 }
Arun Lal K Mb0caca02021-09-05 22:09:33 +0000451
452 return true;
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800453}
454
455/** @brief implement to get the System State
456 * @returns status
457 */
458
459static int getSystemOSState(std::string& OsStatus)
460{
461
462 try
463 {
464 std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
465 Value variant =
466 getDbusProperty(*dbus, "xyz.openbmc_project.State.OperatingSystem",
467 "/xyz/openbmc_project/state/os",
468 "xyz.openbmc_project.State.OperatingSystem.Status",
469 "OperatingSystemState");
470 OsStatus = std::get<std::string>(variant);
471 return ipmi::ccSuccess;
472 }
473 catch (const std::exception& e)
474 {
475 return ipmi::ccUnspecifiedError;
476 }
477}
478
479/** @brief implement to get the Rest BIOS property
480 * @returns status
481 */
482static int getResetBIOSSettings(uint8_t& ResetFlag)
483{
484
485 try
486 {
487 std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
488 std::string service =
489 getService(*dbus, biosConfigIntf, biosConfigBaseMgrPath);
490 Value variant = getDbusProperty(*dbus, service, biosConfigBaseMgrPath,
491 biosConfigIntf, resetBIOSSettingsProp);
Suryakanth Sekarcc402592021-04-01 15:02:10 +0530492
493 std::string_view ResetStr = std::get<std::string>(variant);
494 if (ResetStr ==
495 "xyz.openbmc_project.BIOSConfig.Manager.ResetFlag.NoAction")
496 {
497 ResetFlag = 0;
498 }
499 else if (ResetStr == "xyz.openbmc_project.BIOSConfig.Manager.ResetFlag."
500 "FactoryDefaults")
501 {
502 ResetFlag = 1;
503 }
504 else if (ResetStr == "xyz.openbmc_project.BIOSConfig.Manager.ResetFlag."
505 "FailSafeDefaults")
506 {
507 ResetFlag = 2;
508 }
509 else
510 {
511 return ipmi::ccUnspecifiedError;
512 }
513
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800514 return ipmi::ccSuccess;
515 }
516 catch (const std::exception& e)
517 {
518 return ipmi::ccUnspecifiedError;
519 }
520}
521
Arun Lal K Me7725612021-07-15 18:20:58 +0000522/** @brief Get attributes data (bios base table) from bios.xml
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800523 */
Arun Lal K Me7725612021-07-15 18:20:58 +0000524static bool generateAttributesData()
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800525{
Arun Lal K Me7725612021-07-15 18:20:58 +0000526 try
527 {
528 bios::Xml biosxml(biosXMLFilePath);
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800529
Arun Lal K Me7725612021-07-15 18:20:58 +0000530 if (!biosxml.doDepexCompute())
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800531 {
Arun Lal K Me7725612021-07-15 18:20:58 +0000532 phosphor::logging::log<phosphor::logging::level::ERR>(
533 "'depex' compute failed");
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800534 }
Arun Lal K Me7725612021-07-15 18:20:58 +0000535
536 if (!biosxml.getBaseTable(attributesData))
537 {
538 phosphor::logging::log<phosphor::logging::level::ERR>(
539 "Failed to get bios base table");
540 }
541 }
Patrick Williamsbd51e6a2021-10-06 13:09:44 -0500542 catch (const std::exception& ex)
Arun Lal K Me7725612021-07-15 18:20:58 +0000543 {
544 phosphor::logging::log<phosphor::logging::level::ERR>(ex.what());
545 return false;
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800546 }
547
Arun Lal K Me7725612021-07-15 18:20:58 +0000548 return true;
549}
550
551/** @brief Generate attributes data from bios.xml
552 * and send attributes data (bios base table) to dbus using set method.
553 */
554static void generateAndSendAttributesData(std::string service,
555 uint8_t payloadType)
556{
557 if (!generateAttributesData())
558 {
559 phosphor::logging::log<phosphor::logging::level::ERR>(
560 "generateAndSendAttributesData: generateAttributesData - failed");
561 gNVOOBdata.payloadInfo[payloadType].payloadStatus =
562 static_cast<uint8_t>(ipmi::PStatus::Corrupted);
563 return;
564 }
565
566 phosphor::logging::log<phosphor::logging::level::INFO>(
567 "generateAndSendAttributesData : generateAttributesData is done");
568
569 if (!sendAllAttributes(service))
570 {
571 phosphor::logging::log<phosphor::logging::level::ERR>(
572 "generateAndSendAttributesData: sendAllAttributes - failed");
573 gNVOOBdata.payloadInfo[payloadType].payloadStatus =
574 static_cast<uint8_t>(ipmi::PStatus::Corrupted);
575 return;
576 }
577
578 phosphor::logging::log<phosphor::logging::level::INFO>(
579 "generateAndSendAttributesData : sendAllAttributes is done");
580 gNVOOBdata.payloadInfo[payloadType].payloadStatus =
581 static_cast<uint8_t>(ipmi::PStatus::Valid);
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800582}
583
584/** @brief implement executing the linux command to uncompress and generate the
585 * xmlfile
586 * @param[in] linux command
587 * @returns status
588 */
589template <typename... ArgTypes>
590static int generateBIOSXMLFile(const char* path, ArgTypes&&... tArgs)
591{
592
593 boost::process::child execProg(path, const_cast<char*>(tArgs)...,
594 boost::process::std_out > biosXMLFilePath);
595 execProg.wait();
596 return execProg.exit_code();
597}
598
599/** @brief implements to clean up the temp/ existing payload file
600 **/
601static void cleanUpPayloadFile(uint8_t& payloadType)
602{
603 // Clear the payload Information
604 std::string FilePath = "/var/oob/temp" + std::to_string(payloadType);
605 unlink(FilePath.c_str());
606 FilePath = "/var/oob/Payload" + std::to_string(payloadType);
607 unlink(FilePath.c_str());
608 if (payloadType == static_cast<uint8_t>(ipmi::PType::IntelXMLType0))
609 {
610 unlink("/var/oob/Payload1");
611 gNVOOBdata.payloadInfo[static_cast<uint8_t>(ipmi::PType::IntelXMLType1)]
612 .payloadStatus = static_cast<uint8_t>(ipmi::PStatus::Unknown);
613 }
614}
615
616/** @brief implements to create the oob folders and nv space
617 **/
618static Cc InitNVOOBdata()
619{
620 FILE* fptr;
621 uint16_t size;
622
623 if (!(std::filesystem::exists(biosConfigFolder)))
624 {
625 std::filesystem::create_directory(biosConfigFolder);
626 }
627
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000628 std::ifstream ifs(biosConfigNVPath, std::ios::in | std::ios::binary);
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800629
630 if (ifs.good())
631 {
632
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000633 ifs.seekg(std::ios_base::beg);
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800634 ifs.read(reinterpret_cast<char*>(&gNVOOBdata),
635 sizeof(struct NVOOBdata));
636 ifs.close();
637 return ipmi::ccSuccess;
638 }
639 return ipmi::ccResponseError;
640}
641
642/** @brief implements check the command interface is
643 ** system interface or not
644 ** true mean System interface and false mean LAN or IPMB
645 **/
646static bool IsSystemInterface(ipmi::Context::ptr ctx)
647{
648 ChannelInfo chInfo;
649 Cc status = false;
650
651 try
652 {
653 getChannelInfo(ctx->channel, chInfo);
654 }
Patrick Williamsbd51e6a2021-10-06 13:09:44 -0500655 catch (const sdbusplus::exception_t& e)
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800656 {
657 return false;
658 }
659 if (chInfo.mediumType !=
660 static_cast<uint8_t>(EChannelMediumType::systemInterface))
661 {
662 return false;
663 }
664 return true;
665}
666
667ipmi::RspType<> ipmiOEMSetBIOSCap(ipmi::Context::ptr ctx,
668 uint8_t BIOSCapabilties, uint8_t reserved1,
669 uint8_t reserved2, uint8_t reserved3)
670{
671 std::string OSState;
672 getSystemOSState(OSState);
673
674 if (OSState != "OperatingState" && IsSystemInterface(ctx))
675 {
676 if (reserved1 != 0 || reserved2 != 0 || reserved3 != 0)
677 {
678 return ipmi::responseInvalidFieldRequest();
679 }
680
681 gNVOOBdata.mBIOSCapabilities.OOBCapability = BIOSCapabilties;
682 gNVOOBdata.mIsBIOSCapInitDone = true;
683
684 flushNVOOBdata();
685 return ipmi::responseSuccess();
686 }
687 else
688 {
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800689 return ipmi::response(ipmiCCNotSupportedInCurrentState);
690 }
691}
692
693ipmi::RspType<uint8_t, uint8_t, uint8_t, uint8_t>
694 ipmiOEMGetBIOSCap(ipmi::Context::ptr ctx)
695{
696 if (gNVOOBdata.mIsBIOSCapInitDone)
697 {
698 return ipmi::responseSuccess(gNVOOBdata.mBIOSCapabilities.OOBCapability,
699 0, 0, 0);
700 }
701 else
702 {
703 return ipmi::response(ipmiCCBIOSCapabilityInitNotDone);
704 }
705}
706
707ipmi::RspType<uint32_t> ipmiOEMSetPayload(ipmi::Context::ptr ctx,
708 uint8_t paramSel, uint8_t payloadType,
709 std::vector<uint8_t> payload)
710{
711 uint8_t biosCapOffsetBit = 2; // BIT:1 0-OOB BIOS config not supported
712 // 1-OOB BIOS config is supported
713
714 if (!(gNVOOBdata.mBIOSCapabilities.OOBCapability & (biosCapOffsetBit)))
715 {
716 return ipmi::response(ipmiCCBIOSCapabilityInitNotDone);
717 }
718 // Validate the Payload Type
719 if (payloadType > maxPayloadSupported)
720 {
721 return ipmi::responseInvalidFieldRequest();
722 }
723
724 // We should support this Payload type 0 command only in KCS Interface
725 if (payloadType == static_cast<uint8_t>(ipmi::PType::IntelXMLType0))
726 {
727 std::string OSState;
728
729 getSystemOSState(OSState);
730 if (!IsSystemInterface(ctx) || OSState == "OperatingState")
731 {
732 return ipmi::responseCommandNotAvailable();
733 }
734 }
735
736 switch (static_cast<PTState>(paramSel))
737 {
738 case ipmi::PTState::StartTransfer:
739 {
740 PayloadStartTransfer* pPayloadStartTransfer =
741 reinterpret_cast<PayloadStartTransfer*>(payload.data());
742 if (payload.size() < sizeof(PayloadStartTransfer))
743 {
744 phosphor::logging::log<phosphor::logging::level::ERR>(
745 "ipmiOEMSetPayload: BIOS Config Payload size is not "
746 "correct");
747 return ipmi::responseReqDataLenInvalid();
748 }
749 cleanUpPayloadFile(payloadType);
750
751 gNVOOBdata.payloadInfo[payloadType].payloadReservationID = rand();
752 gNVOOBdata.payloadInfo[payloadType].payloadTotalChecksum =
753 pPayloadStartTransfer->payloadTotalChecksum;
754 gNVOOBdata.payloadInfo[payloadType].payloadTotalSize =
755 pPayloadStartTransfer->payloadTotalSize;
756 gNVOOBdata.payloadInfo[payloadType].payloadVersion =
757 pPayloadStartTransfer->payloadVersion;
758 gNVOOBdata.payloadInfo[payloadType].actualTotalPayloadWritten = 0;
759 gNVOOBdata.payloadInfo[payloadType].payloadStatus =
760 static_cast<uint8_t>(ipmi::PStatus::Unknown);
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000761 gNVOOBdata.payloadInfo[payloadType].payloadType = payloadType;
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800762
763 return ipmi::responseSuccess(
764 gNVOOBdata.payloadInfo[payloadType].payloadReservationID);
765 }
766 break;
767
768 case ipmi::PTState::InProgress:
769 {
770 PayloadInProgress* pPayloadInProgress =
771 reinterpret_cast<PayloadInProgress*>(payload.data());
772 PayloadInfo payloadInfo = gNVOOBdata.payloadInfo[payloadType];
773
774 if (payload.size() < sizeof(PayloadInProgress))
775 {
776 phosphor::logging::log<phosphor::logging::level::ERR>(
777 "BIOS Config Payload size is not correct");
778 return ipmi::responseReqDataLenInvalid();
779 }
780
781 if (pPayloadInProgress->payloadReservationID !=
782 payloadInfo.payloadReservationID)
783 {
Arun Lal K Mb0caca02021-09-05 22:09:33 +0000784 phosphor::logging::log<phosphor::logging::level::ERR>(
785 "BIOS Config Payload reservation ID is not correct");
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800786 return ipmi::responseInvalidReservationId();
787 }
788 payloadInfo.payloadCurrentSize =
789 pPayloadInProgress->payloadCurrentSize;
790 // Need to verify the current Payload Checksum
791 const uint8_t* data =
792 reinterpret_cast<const uint8_t*>(payload.data());
793 // we have to remove the current size, current offset, current
794 // length,checksum bytes , reservation bytes
795 boost::crc_32_type calcChecksum;
796 calcChecksum.process_bytes(data + 16, payload.size() - 16);
797 if (calcChecksum.checksum() !=
798 pPayloadInProgress->payloadCurrentChecksum)
799 {
800 phosphor::logging::log<phosphor::logging::level::ERR>(
801 "ipmiOEMSetPayload: Payload Checksum Failed");
802 return ipmi::response(ipmiCCPayloadChecksumFailed);
803 }
804 // store the data in temp file
805 std::string FilePath =
806 "/var/oob/temp" + std::to_string(payloadType);
807
808 std::ofstream outFile(FilePath, std::ios::binary | std::ios::app);
809 outFile.seekp(pPayloadInProgress->payloadOffset);
810 // we have to remove the current size, current offset, current
811 // length,checksum bytes , reservation bytes
812
813 const char* writedata =
814 reinterpret_cast<const char*>(payload.data());
815 outFile.write(writedata + 16, payload.size() - 16);
816 outFile.close();
817
818 gNVOOBdata.payloadInfo[payloadType].payloadStatus =
819 static_cast<uint8_t>(ipmi::PStatus::Unknown);
820 gNVOOBdata.payloadInfo[payloadType].actualTotalPayloadWritten +=
821 payloadInfo.payloadCurrentSize;
822 return ipmi::responseSuccess(payloadInfo.payloadCurrentSize);
823 }
824 break;
825 case ipmi::PTState::EndTransfer:
826 {
827 PayloadEndTransfer* pPayloadEndTransfer =
828 reinterpret_cast<PayloadEndTransfer*>(payload.data());
829 PayloadInfo payloadInfo = gNVOOBdata.payloadInfo[payloadType];
830 if (pPayloadEndTransfer->payloadReservationID !=
831 payloadInfo.payloadReservationID)
832 {
833 return ipmi::responseInvalidReservationId();
834 }
835 gNVOOBdata.payloadInfo[payloadType].payloadStatus =
836 static_cast<uint8_t>(ipmi::PStatus::Unknown);
837
838 if (gNVOOBdata.payloadInfo[payloadType].actualTotalPayloadWritten !=
839 gNVOOBdata.payloadInfo[payloadType].payloadTotalSize)
840 {
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800841 return ipmi::response(ipmiCCPayloadPayloadInComplete);
842 }
843 std::string tempFilePath =
844 "/var/oob/temp" + std::to_string(payloadType);
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000845 std::string payloadFilePath =
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800846 "/var/oob/Payload" + std::to_string(payloadType);
847 auto renamestatus =
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000848 std::rename(tempFilePath.c_str(), payloadFilePath.c_str());
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800849 if (renamestatus)
850 {
851 phosphor::logging::log<phosphor::logging::level::ERR>(
852 "ipmiOEMSetPayload: Renaming Payload file - failed");
853 }
854
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800855 if (payloadType == static_cast<uint8_t>(ipmi::PType::IntelXMLType0))
856 {
857 // Unzip the Intel format XML file type 0
858 auto response = generateBIOSXMLFile("/usr/bin/lzcat", "-d",
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000859 payloadFilePath.c_str());
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800860 if (response)
861 {
862
863 phosphor::logging::log<phosphor::logging::level::ERR>(
864 "ipmiOEMSetPayload: generateBIOSXMLFile - failed");
865 gNVOOBdata.payloadInfo[payloadType].payloadStatus =
866 static_cast<uint8_t>(ipmi::PStatus::Corrupted);
867 return ipmi::response(ipmiCCPayloadPayloadPacketMissed);
868 }
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000869 phosphor::logging::log<phosphor::logging::level::INFO>(
870 " ipmiOEMSetPayload : Convert XML into native-dbus DONE");
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000871
Arun Lal K Me7725612021-07-15 18:20:58 +0000872 /* So that we don't block the call */
873 auto io = getIoContext();
874 auto dbus = getSdBus();
875 if (io && dbus)
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000876 {
Arun Lal K Me7725612021-07-15 18:20:58 +0000877 std::string service = getService(*dbus, biosConfigIntf,
878 biosConfigBaseMgrPath);
879
880 boost::asio::post(*io, [service, payloadType] {
881 generateAndSendAttributesData(service, payloadType);
882 });
883 }
884 else
885 {
886 phosphor::logging::log<phosphor::logging::level::INFO>(
887 "ipmiOEMSetPayload: Unable to get io context or sdbus");
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000888 return ipmi::responseResponseError();
889 }
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800890 }
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800891
892 struct stat filestat;
893
894 /* Get entry's information. */
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000895 if (!stat(payloadFilePath.c_str(), &filestat))
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800896 {
897 gNVOOBdata.payloadInfo[payloadType].payloadTimeStamp =
898 filestat.st_mtime;
899 gNVOOBdata.payloadInfo[payloadType].payloadTotalSize =
900 filestat.st_size;
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800901 }
902 else
903 {
904 return ipmi::responseResponseError();
905 }
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800906 flushNVOOBdata();
907 return ipmi::responseSuccess(
908 gNVOOBdata.payloadInfo[payloadType].actualTotalPayloadWritten);
909 }
910 break;
911 case ipmi::PTState::UserAbort:
912 {
913 PayloadEndTransfer* pPayloadEndTransfer =
914 reinterpret_cast<PayloadEndTransfer*>(payload.data());
915 PayloadInfo payloadInfo = gNVOOBdata.payloadInfo[payloadType];
916 if (pPayloadEndTransfer->payloadReservationID !=
917 payloadInfo.payloadReservationID)
918 {
919 return ipmi::responseInvalidReservationId();
920 }
921 gNVOOBdata.payloadInfo[payloadType].payloadReservationID = 0;
922 gNVOOBdata.payloadInfo[payloadType].payloadType = 0;
923 gNVOOBdata.payloadInfo[payloadType].payloadTotalSize = 0;
924 // Delete the temp file
925 std::string tempFilePath =
926 "/var/oob/temp" + std::to_string(payloadType);
927 unlink(tempFilePath.c_str());
928 flushNVOOBdata();
929 return ipmi::responseSuccess();
930 }
931 break;
932 default:
933 return ipmi::responseInvalidFieldRequest();
934 }
935 return ipmi::responseResponseError();
936}
937
938ipmi::RspType<message::Payload>
939 ipmiOEMGetPayload(ipmi::Context::ptr ctx, uint8_t paramSel,
940 uint8_t payloadType, ipmi::message::Payload& payload)
941{
942 // 1-OOB BIOS config is supported
943 message::Payload retValue;
944
945 if (!(gNVOOBdata.mBIOSCapabilities.OOBCapability & (biosCapOffsetBit)))
946 {
947 return ipmi::response(ipmiCCBIOSCapabilityInitNotDone);
948 }
949 // Validate the Payload Type
950 if (payloadType > maxPayloadSupported)
951 {
952 return ipmi::responseInvalidFieldRequest();
953 }
954
Arun Lal K Mb0caca02021-09-05 22:09:33 +0000955 if (payloadType == static_cast<uint8_t>(ipmi::PType::IntelXMLType1))
956 {
957 if (!payload1::update(ctx))
958 {
959 phosphor::logging::log<phosphor::logging::level::ERR>(
960 "ipmiOEMGetPayload: unable to update NVOOBdata for payloadType "
961 "= IntelXMLType1");
962 return ipmi::response(ipmi::ccUnspecifiedError);
963 }
964 }
965
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800966 struct PayloadInfo res = gNVOOBdata.payloadInfo[payloadType];
967
968 switch (static_cast<GetPayloadParameter>(paramSel))
969 {
970 case ipmi::GetPayloadParameter::GetPayloadInfo:
971 {
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000972 std::string payloadFilePath =
973 "/var/oob/Payload" + std::to_string(payloadType);
974
975 std::ifstream ifs(payloadFilePath,
976 std::ios::in | std::ios::binary | std::ios::ate);
977
978 if (!ifs.good())
979 {
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000980 phosphor::logging::log<phosphor::logging::level::ERR>(
981 "ipmiOEMGetPayload: Payload File Error");
982 // File does not exist code here
983 return ipmi::response(ipmi::ccUnspecifiedError);
984 }
Arun Lal K Mb0caca02021-09-05 22:09:33 +0000985
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000986 ifs.close();
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800987 retValue.pack(res.payloadVersion);
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000988 retValue.pack(payloadType);
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800989 retValue.pack(res.payloadTotalSize);
990 retValue.pack(res.payloadTotalChecksum);
991 retValue.pack(res.payloadflag);
992 retValue.pack(res.payloadStatus);
993 retValue.pack(res.payloadTimeStamp);
994
995 return ipmi::responseSuccess(std::move(retValue));
996 }
997
998 break;
999 case ipmi::GetPayloadParameter::GetPayloadData:
1000 {
1001 if (res.payloadStatus ==
1002 (static_cast<uint8_t>(ipmi::PStatus::Valid)))
1003 {
1004 std::vector<uint32_t> reqData;
1005 if (payload.unpack(reqData) || !payload.fullyUnpacked())
1006 {
1007 return ipmi::responseReqDataLenInvalid();
1008 }
1009 uint32_t offset = reqData.at(0);
1010 uint32_t length = reqData.at(1);
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +00001011 std::string payloadFilePath =
1012 "/var/oob/Payload" + std::to_string(payloadType);
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001013
Snehalatha Venkatesh2ff15bf2021-12-30 11:51:14 +00001014 if (length < static_cast<uint32_t>(maxGetPayloadDataSize))
1015 {
1016 phosphor::logging::log<phosphor::logging::level::ERR>(
1017 "ipmiOEMGetPayload: length > maxGetPayloadDataSize",
1018 phosphor::logging::entry("LENGTH=%d", length),
1019 phosphor::logging::entry("maxGetPayloadDataSize=%d",
1020 maxGetPayloadDataSize));
1021 return ipmi::responseInvalidFieldRequest();
1022 }
1023
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +00001024 std::ifstream ifs(payloadFilePath, std::ios::in |
1025 std::ios::binary |
1026 std::ios::ate);
1027
1028 if (!ifs.good())
1029 {
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +00001030 phosphor::logging::log<phosphor::logging::level::ERR>(
1031 "ipmiOEMGetPayload: Payload File Error");
1032 // File does not exist code here
1033 return ipmi::response(ipmi::ccUnspecifiedError);
1034 }
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001035 std::ifstream::pos_type fileSize = ifs.tellg();
1036 // Total file data within given offset
1037 if (fileSize < static_cast<uint64_t>(offset))
1038 {
Snehalatha Venkatesh2ff15bf2021-12-30 11:51:14 +00001039 phosphor::logging::log<phosphor::logging::level::ERR>(
1040 "ipmiOEMGetPayload: filesize < offset");
1041 return ipmi::responseInvalidFieldRequest();
1042 }
1043
1044 if ((static_cast<uint64_t>(fileSize) - offset) < length)
1045 {
1046 phosphor::logging::log<phosphor::logging::level::ERR>(
1047 "ipmiOEMGetPayload: (filesize - offset) < length ");
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001048 return ipmi::responseInvalidFieldRequest();
1049 }
1050
1051 ifs.seekg(offset, std::ios::beg);
1052 std::array<uint8_t, maxGetPayloadDataSize> Buffer;
1053 ifs.read(reinterpret_cast<char*>(Buffer.data()), length);
1054 uint32_t readCount = ifs.gcount();
1055 ifs.close();
1056
1057 boost::crc_32_type calcChecksum;
1058 calcChecksum.process_bytes(
1059 reinterpret_cast<char*>(Buffer.data()), readCount);
1060 uint32_t chkSum = calcChecksum.checksum();
1061 retValue.pack(payloadType);
1062 retValue.pack(readCount);
1063 retValue.pack(chkSum);
1064
1065 for (int i = 0; i < readCount; i++)
1066 {
1067 retValue.pack(Buffer.at(i));
1068 }
Arun Lal K Mb0caca02021-09-05 22:09:33 +00001069
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001070 return ipmi::responseSuccess(std::move(retValue));
1071 }
1072 else
1073 {
1074 return ipmi::responseResponseError();
1075 }
1076 }
1077 break;
1078 case ipmi::GetPayloadParameter::GetPayloadStatus:
1079 {
1080 retValue.pack(gNVOOBdata.payloadInfo[payloadType].payloadStatus);
1081 return ipmi::responseSuccess(std::move(retValue));
1082 }
1083 break;
1084 default:
1085 return ipmi::responseInvalidFieldRequest();
1086 }
1087 return ipmi::responseInvalidFieldRequest();
1088}
1089
1090ipmi::RspType<> ipmiOEMSetBIOSHashInfo(
1091 ipmi::Context::ptr ctx, std::array<uint8_t, maxSeedSize>& pwdSeed,
Ayushi Smriti32381872021-06-23 11:05:48 +05301092 uint8_t algoInfo, std::array<uint8_t, maxHashSize>& adminPwdHash)
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001093{
1094
1095 std::string OSState;
1096
1097 // We should support this command only in KCS Interface
1098 if (!IsSystemInterface(ctx))
1099 {
1100 return ipmi::responseCommandNotAvailable();
1101 }
1102 getSystemOSState(OSState);
1103 // We should not support this command after System Booted - After Exit Boot
1104 // service called
1105
Ayushi Smriti32381872021-06-23 11:05:48 +05301106 if (OSState == "OperatingState")
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001107 {
Ayushi Smriti32381872021-06-23 11:05:48 +05301108 return ipmi::response(ipmiCCNotSupportedInCurrentState);
1109 }
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001110
Ayushi Smriti32381872021-06-23 11:05:48 +05301111 nlohmann::json json;
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001112
Ayushi Smriti32381872021-06-23 11:05:48 +05301113 if ((algoInfo & 0xF) == algoSHA384)
1114 {
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001115 json["HashAlgo"] = "SHA384";
Ayushi Smriti32381872021-06-23 11:05:48 +05301116 }
1117 else if ((algoInfo & 0xF) == algoSHA256)
1118 {
1119 json["HashAlgo"] = "SHA256";
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001120 }
1121 else
1122 {
Ayushi Smriti32381872021-06-23 11:05:48 +05301123 return ipmi::responseInvalidFieldRequest();
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001124 }
Ayushi Smriti32381872021-06-23 11:05:48 +05301125
1126 json["Seed"] = pwdSeed;
1127 json["IsAdminPwdChanged"] = false;
1128 json["AdminPwdHash"] = adminPwdHash;
1129 json["IsUserPwdChanged"] = false;
1130
1131 std::array<uint8_t, maxHashSize> userPwdHash;
1132 userPwdHash.fill({}); // initializing with 0 as user password hash field
1133 // is not used presently
1134 json["UserPwdHash"] = userPwdHash;
1135 json["StatusFlag"] = algoInfo;
1136
1137 std::string hashFilePath = "/var/lib/bios-settings-manager/seedData";
1138 std::ofstream ofs(hashFilePath, std::ios::out);
1139 const auto& writeData = json.dump();
1140 ofs << writeData;
1141 ofs.close();
1142 return ipmi::responseSuccess();
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001143}
1144
Ayushi Smriti32381872021-06-23 11:05:48 +05301145ipmi::RspType<std::array<uint8_t, maxSeedSize>, uint8_t,
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001146 std::array<uint8_t, maxHashSize>>
1147 ipmiOEMGetBIOSHash(ipmi::Context::ptr ctx)
1148{
1149
1150 std::string OSState;
1151 nlohmann::json data = nullptr;
1152
1153 // We should support this command only in KCS Interface
1154 if (!IsSystemInterface(ctx))
1155 {
1156 return ipmi::responseCommandNotAvailable();
1157 }
1158
1159 getSystemOSState(OSState);
1160 // We should not support this command after System Booted - After Exit Boot
1161 // service called
1162
1163 if (OSState != "OperatingState")
1164 {
Suryakanth Sekarcc402592021-04-01 15:02:10 +05301165 std::string HashFilePath = "/var/lib/bios-settings-manager/seedData";
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001166
1167 std::ifstream devIdFile(HashFilePath);
1168 if (devIdFile.is_open())
1169 {
1170
1171 try
1172 {
1173 data = nlohmann::json::parse(devIdFile, nullptr, false);
1174 }
1175 catch (const nlohmann::json::parse_error& e)
1176 {
1177 return ipmi::responseResponseError();
1178 }
1179
1180 if (data.is_discarded())
1181 {
1182 return ipmi::responseResponseError();
1183 }
1184
1185 std::array<uint8_t, maxHashSize> newAdminHash;
Ayushi Smriti32381872021-06-23 11:05:48 +05301186 std::array<uint8_t, maxSeedSize> seed;
1187
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001188 uint8_t flag = 0;
1189 uint8_t adminPwdChangedFlag = 0;
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001190 if (!data.is_discarded())
1191 {
1192
1193 adminPwdChangedFlag = data["IsAdminPwdChanged"];
1194 newAdminHash = data["AdminPwdHash"];
Ayushi Smriti32381872021-06-23 11:05:48 +05301195 seed = data["Seed"];
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001196 }
1197
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001198 auto status = getResetBIOSSettings(flag);
1199 if (status)
1200 {
1201 return ipmi::responseResponseError();
1202 }
1203 if (adminPwdChangedFlag)
1204 {
1205 flag |= adminPasswordChanged;
1206 }
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001207
1208 std::copy(std::begin(newAdminHash), std::end(newAdminHash),
1209 std::begin(newAdminHash));
Ayushi Smriti32381872021-06-23 11:05:48 +05301210
1211 return ipmi::responseSuccess(seed, flag, newAdminHash);
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001212 }
1213 else
1214 {
1215 return ipmi::responseResponseError();
1216 }
1217 }
1218 else
1219 {
1220
1221 return ipmi::response(ipmiCCNotSupportedInCurrentState);
1222 }
1223}
1224
1225static void registerBIOSConfigFunctions(void)
1226{
1227 phosphor::logging::log<phosphor::logging::level::INFO>(
1228 "BIOSConfig module initialization");
1229 InitNVOOBdata();
1230
1231 registerHandler(prioOemBase, intel::netFnGeneral,
1232 intel::general::cmdSetBIOSCap, Privilege::Admin,
1233 ipmiOEMSetBIOSCap);
1234
1235 registerHandler(prioOemBase, intel::netFnGeneral,
1236 intel::general::cmdGetBIOSCap, Privilege::User,
1237 ipmiOEMGetBIOSCap);
1238 registerHandler(prioOemBase, intel::netFnGeneral,
1239 intel::general::cmdSetBIOSPwdHashInfo, Privilege::Admin,
1240 ipmiOEMSetBIOSHashInfo);
1241
1242 registerHandler(prioOemBase, intel::netFnGeneral,
1243 intel::general::cmdGetBIOSPwdHash, Privilege::User,
1244 ipmiOEMGetBIOSHash);
1245
1246 registerHandler(prioOemBase, intel::netFnGeneral,
1247 intel::general::cmdGetPayload, Privilege::User,
1248 ipmiOEMGetPayload);
1249 registerHandler(prioOemBase, intel::netFnGeneral,
1250 intel::general::cmdSetPayload, Privilege::Admin,
1251 ipmiOEMSetPayload);
1252
1253 return;
1254}
1255
1256} // namespace ipmi