blob: 9d40f5d35534a9bf2120a3f1eb26ef2d7601de9e [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
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +00001014 std::ifstream ifs(payloadFilePath, std::ios::in |
1015 std::ios::binary |
1016 std::ios::ate);
1017
1018 if (!ifs.good())
1019 {
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +00001020 phosphor::logging::log<phosphor::logging::level::ERR>(
1021 "ipmiOEMGetPayload: Payload File Error");
1022 // File does not exist code here
1023 return ipmi::response(ipmi::ccUnspecifiedError);
1024 }
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001025 std::ifstream::pos_type fileSize = ifs.tellg();
1026 // Total file data within given offset
1027 if (fileSize < static_cast<uint64_t>(offset))
1028 {
1029 ifs.close();
1030 return ipmi::responseInvalidFieldRequest();
1031 }
1032
1033 ifs.seekg(offset, std::ios::beg);
1034 std::array<uint8_t, maxGetPayloadDataSize> Buffer;
1035 ifs.read(reinterpret_cast<char*>(Buffer.data()), length);
1036 uint32_t readCount = ifs.gcount();
1037 ifs.close();
1038
1039 boost::crc_32_type calcChecksum;
1040 calcChecksum.process_bytes(
1041 reinterpret_cast<char*>(Buffer.data()), readCount);
1042 uint32_t chkSum = calcChecksum.checksum();
1043 retValue.pack(payloadType);
1044 retValue.pack(readCount);
1045 retValue.pack(chkSum);
1046
1047 for (int i = 0; i < readCount; i++)
1048 {
1049 retValue.pack(Buffer.at(i));
1050 }
Arun Lal K Mb0caca02021-09-05 22:09:33 +00001051
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001052 return ipmi::responseSuccess(std::move(retValue));
1053 }
1054 else
1055 {
1056 return ipmi::responseResponseError();
1057 }
1058 }
1059 break;
1060 case ipmi::GetPayloadParameter::GetPayloadStatus:
1061 {
1062 retValue.pack(gNVOOBdata.payloadInfo[payloadType].payloadStatus);
1063 return ipmi::responseSuccess(std::move(retValue));
1064 }
1065 break;
1066 default:
1067 return ipmi::responseInvalidFieldRequest();
1068 }
1069 return ipmi::responseInvalidFieldRequest();
1070}
1071
1072ipmi::RspType<> ipmiOEMSetBIOSHashInfo(
1073 ipmi::Context::ptr ctx, std::array<uint8_t, maxSeedSize>& pwdSeed,
Ayushi Smriti32381872021-06-23 11:05:48 +05301074 uint8_t algoInfo, std::array<uint8_t, maxHashSize>& adminPwdHash)
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001075{
1076
1077 std::string OSState;
1078
1079 // We should support this command only in KCS Interface
1080 if (!IsSystemInterface(ctx))
1081 {
1082 return ipmi::responseCommandNotAvailable();
1083 }
1084 getSystemOSState(OSState);
1085 // We should not support this command after System Booted - After Exit Boot
1086 // service called
1087
Ayushi Smriti32381872021-06-23 11:05:48 +05301088 if (OSState == "OperatingState")
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001089 {
Ayushi Smriti32381872021-06-23 11:05:48 +05301090 return ipmi::response(ipmiCCNotSupportedInCurrentState);
1091 }
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001092
Ayushi Smriti32381872021-06-23 11:05:48 +05301093 nlohmann::json json;
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001094
Ayushi Smriti32381872021-06-23 11:05:48 +05301095 if ((algoInfo & 0xF) == algoSHA384)
1096 {
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001097 json["HashAlgo"] = "SHA384";
Ayushi Smriti32381872021-06-23 11:05:48 +05301098 }
1099 else if ((algoInfo & 0xF) == algoSHA256)
1100 {
1101 json["HashAlgo"] = "SHA256";
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001102 }
1103 else
1104 {
Ayushi Smriti32381872021-06-23 11:05:48 +05301105 return ipmi::responseInvalidFieldRequest();
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001106 }
Ayushi Smriti32381872021-06-23 11:05:48 +05301107
1108 json["Seed"] = pwdSeed;
1109 json["IsAdminPwdChanged"] = false;
1110 json["AdminPwdHash"] = adminPwdHash;
1111 json["IsUserPwdChanged"] = false;
1112
1113 std::array<uint8_t, maxHashSize> userPwdHash;
1114 userPwdHash.fill({}); // initializing with 0 as user password hash field
1115 // is not used presently
1116 json["UserPwdHash"] = userPwdHash;
1117 json["StatusFlag"] = algoInfo;
1118
1119 std::string hashFilePath = "/var/lib/bios-settings-manager/seedData";
1120 std::ofstream ofs(hashFilePath, std::ios::out);
1121 const auto& writeData = json.dump();
1122 ofs << writeData;
1123 ofs.close();
1124 return ipmi::responseSuccess();
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001125}
1126
Ayushi Smriti32381872021-06-23 11:05:48 +05301127ipmi::RspType<std::array<uint8_t, maxSeedSize>, uint8_t,
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001128 std::array<uint8_t, maxHashSize>>
1129 ipmiOEMGetBIOSHash(ipmi::Context::ptr ctx)
1130{
1131
1132 std::string OSState;
1133 nlohmann::json data = nullptr;
1134
1135 // We should support this command only in KCS Interface
1136 if (!IsSystemInterface(ctx))
1137 {
1138 return ipmi::responseCommandNotAvailable();
1139 }
1140
1141 getSystemOSState(OSState);
1142 // We should not support this command after System Booted - After Exit Boot
1143 // service called
1144
1145 if (OSState != "OperatingState")
1146 {
Suryakanth Sekarcc402592021-04-01 15:02:10 +05301147 std::string HashFilePath = "/var/lib/bios-settings-manager/seedData";
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001148
1149 std::ifstream devIdFile(HashFilePath);
1150 if (devIdFile.is_open())
1151 {
1152
1153 try
1154 {
1155 data = nlohmann::json::parse(devIdFile, nullptr, false);
1156 }
1157 catch (const nlohmann::json::parse_error& e)
1158 {
1159 return ipmi::responseResponseError();
1160 }
1161
1162 if (data.is_discarded())
1163 {
1164 return ipmi::responseResponseError();
1165 }
1166
1167 std::array<uint8_t, maxHashSize> newAdminHash;
Ayushi Smriti32381872021-06-23 11:05:48 +05301168 std::array<uint8_t, maxSeedSize> seed;
1169
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001170 uint8_t flag = 0;
1171 uint8_t adminPwdChangedFlag = 0;
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001172 if (!data.is_discarded())
1173 {
1174
1175 adminPwdChangedFlag = data["IsAdminPwdChanged"];
1176 newAdminHash = data["AdminPwdHash"];
Ayushi Smriti32381872021-06-23 11:05:48 +05301177 seed = data["Seed"];
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001178 }
1179
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001180 auto status = getResetBIOSSettings(flag);
1181 if (status)
1182 {
1183 return ipmi::responseResponseError();
1184 }
1185 if (adminPwdChangedFlag)
1186 {
1187 flag |= adminPasswordChanged;
1188 }
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001189
1190 std::copy(std::begin(newAdminHash), std::end(newAdminHash),
1191 std::begin(newAdminHash));
Ayushi Smriti32381872021-06-23 11:05:48 +05301192
1193 return ipmi::responseSuccess(seed, flag, newAdminHash);
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001194 }
1195 else
1196 {
1197 return ipmi::responseResponseError();
1198 }
1199 }
1200 else
1201 {
1202
1203 return ipmi::response(ipmiCCNotSupportedInCurrentState);
1204 }
1205}
1206
1207static void registerBIOSConfigFunctions(void)
1208{
1209 phosphor::logging::log<phosphor::logging::level::INFO>(
1210 "BIOSConfig module initialization");
1211 InitNVOOBdata();
1212
1213 registerHandler(prioOemBase, intel::netFnGeneral,
1214 intel::general::cmdSetBIOSCap, Privilege::Admin,
1215 ipmiOEMSetBIOSCap);
1216
1217 registerHandler(prioOemBase, intel::netFnGeneral,
1218 intel::general::cmdGetBIOSCap, Privilege::User,
1219 ipmiOEMGetBIOSCap);
1220 registerHandler(prioOemBase, intel::netFnGeneral,
1221 intel::general::cmdSetBIOSPwdHashInfo, Privilege::Admin,
1222 ipmiOEMSetBIOSHashInfo);
1223
1224 registerHandler(prioOemBase, intel::netFnGeneral,
1225 intel::general::cmdGetBIOSPwdHash, Privilege::User,
1226 ipmiOEMGetBIOSHash);
1227
1228 registerHandler(prioOemBase, intel::netFnGeneral,
1229 intel::general::cmdGetPayload, Privilege::User,
1230 ipmiOEMGetPayload);
1231 registerHandler(prioOemBase, intel::netFnGeneral,
1232 intel::general::cmdSetPayload, Privilege::Admin,
1233 ipmiOEMSetPayload);
1234
1235 return;
1236}
1237
1238} // namespace ipmi