blob: 0fae09c2ebf5c5fab7512d544da22e7e33d2426a [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 */
Arun Lal K M382dc972022-01-20 22:18:23 +0000458static bool getPostCompleted()
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800459{
Arun Lal K M382dc972022-01-20 22:18:23 +0000460 /*
461 * In case of failure we treat postCompleted as true.
462 * So that BIOS config commands is not accepted by BMC by mistake.
463 */
464 bool postCompleted = true;
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800465
466 try
467 {
468 std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
469 Value variant =
470 getDbusProperty(*dbus, "xyz.openbmc_project.State.OperatingSystem",
471 "/xyz/openbmc_project/state/os",
472 "xyz.openbmc_project.State.OperatingSystem.Status",
473 "OperatingSystemState");
Arun Lal K M382dc972022-01-20 22:18:23 +0000474 auto& value = std::get<std::string>(variant);
475
476 // The short strings "Standby" is deprecated in favor of the
477 // full enum strings. Support for the short strings will be
478 // removed in the future.
479 postCompleted = (value == "Standby") ||
480 (value == "xyz.openbmc_project.State.OperatingSystem."
481 "Status.OSStatus.Standby");
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800482 }
483 catch (const std::exception& e)
484 {
Arun Lal K M382dc972022-01-20 22:18:23 +0000485 phosphor::logging::log<phosphor::logging::level::ERR>(
486 "'getDbusProperty' failed to read "
487 "xyz.openbmc_project.State.OperatingSystem");
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800488 }
Arun Lal K M382dc972022-01-20 22:18:23 +0000489
490 return postCompleted;
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800491}
492
493/** @brief implement to get the Rest BIOS property
494 * @returns status
495 */
496static int getResetBIOSSettings(uint8_t& ResetFlag)
497{
498
499 try
500 {
501 std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
502 std::string service =
503 getService(*dbus, biosConfigIntf, biosConfigBaseMgrPath);
504 Value variant = getDbusProperty(*dbus, service, biosConfigBaseMgrPath,
505 biosConfigIntf, resetBIOSSettingsProp);
Suryakanth Sekarcc402592021-04-01 15:02:10 +0530506
507 std::string_view ResetStr = std::get<std::string>(variant);
508 if (ResetStr ==
509 "xyz.openbmc_project.BIOSConfig.Manager.ResetFlag.NoAction")
510 {
511 ResetFlag = 0;
512 }
513 else if (ResetStr == "xyz.openbmc_project.BIOSConfig.Manager.ResetFlag."
514 "FactoryDefaults")
515 {
516 ResetFlag = 1;
517 }
518 else if (ResetStr == "xyz.openbmc_project.BIOSConfig.Manager.ResetFlag."
519 "FailSafeDefaults")
520 {
521 ResetFlag = 2;
522 }
523 else
524 {
525 return ipmi::ccUnspecifiedError;
526 }
527
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800528 return ipmi::ccSuccess;
529 }
530 catch (const std::exception& e)
531 {
532 return ipmi::ccUnspecifiedError;
533 }
534}
535
Arun Lal K Me7725612021-07-15 18:20:58 +0000536/** @brief Get attributes data (bios base table) from bios.xml
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800537 */
Arun Lal K Me7725612021-07-15 18:20:58 +0000538static bool generateAttributesData()
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800539{
Arun Lal K Me7725612021-07-15 18:20:58 +0000540 try
541 {
542 bios::Xml biosxml(biosXMLFilePath);
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800543
Arun Lal K Me7725612021-07-15 18:20:58 +0000544 if (!biosxml.doDepexCompute())
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800545 {
Arun Lal K Me7725612021-07-15 18:20:58 +0000546 phosphor::logging::log<phosphor::logging::level::ERR>(
547 "'depex' compute failed");
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800548 }
Arun Lal K Me7725612021-07-15 18:20:58 +0000549
550 if (!biosxml.getBaseTable(attributesData))
551 {
552 phosphor::logging::log<phosphor::logging::level::ERR>(
553 "Failed to get bios base table");
554 }
555 }
Patrick Williamsbd51e6a2021-10-06 13:09:44 -0500556 catch (const std::exception& ex)
Arun Lal K Me7725612021-07-15 18:20:58 +0000557 {
558 phosphor::logging::log<phosphor::logging::level::ERR>(ex.what());
559 return false;
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800560 }
561
Arun Lal K Me7725612021-07-15 18:20:58 +0000562 return true;
563}
564
565/** @brief Generate attributes data from bios.xml
566 * and send attributes data (bios base table) to dbus using set method.
567 */
568static void generateAndSendAttributesData(std::string service,
569 uint8_t payloadType)
570{
571 if (!generateAttributesData())
572 {
573 phosphor::logging::log<phosphor::logging::level::ERR>(
574 "generateAndSendAttributesData: generateAttributesData - failed");
575 gNVOOBdata.payloadInfo[payloadType].payloadStatus =
576 static_cast<uint8_t>(ipmi::PStatus::Corrupted);
577 return;
578 }
579
580 phosphor::logging::log<phosphor::logging::level::INFO>(
581 "generateAndSendAttributesData : generateAttributesData is done");
582
583 if (!sendAllAttributes(service))
584 {
585 phosphor::logging::log<phosphor::logging::level::ERR>(
586 "generateAndSendAttributesData: sendAllAttributes - failed");
587 gNVOOBdata.payloadInfo[payloadType].payloadStatus =
588 static_cast<uint8_t>(ipmi::PStatus::Corrupted);
589 return;
590 }
591
592 phosphor::logging::log<phosphor::logging::level::INFO>(
593 "generateAndSendAttributesData : sendAllAttributes is done");
594 gNVOOBdata.payloadInfo[payloadType].payloadStatus =
595 static_cast<uint8_t>(ipmi::PStatus::Valid);
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800596}
597
598/** @brief implement executing the linux command to uncompress and generate the
599 * xmlfile
600 * @param[in] linux command
601 * @returns status
602 */
603template <typename... ArgTypes>
604static int generateBIOSXMLFile(const char* path, ArgTypes&&... tArgs)
605{
606
607 boost::process::child execProg(path, const_cast<char*>(tArgs)...,
608 boost::process::std_out > biosXMLFilePath);
609 execProg.wait();
610 return execProg.exit_code();
611}
612
613/** @brief implements to clean up the temp/ existing payload file
614 **/
615static void cleanUpPayloadFile(uint8_t& payloadType)
616{
617 // Clear the payload Information
618 std::string FilePath = "/var/oob/temp" + std::to_string(payloadType);
619 unlink(FilePath.c_str());
620 FilePath = "/var/oob/Payload" + std::to_string(payloadType);
621 unlink(FilePath.c_str());
622 if (payloadType == static_cast<uint8_t>(ipmi::PType::IntelXMLType0))
623 {
624 unlink("/var/oob/Payload1");
625 gNVOOBdata.payloadInfo[static_cast<uint8_t>(ipmi::PType::IntelXMLType1)]
626 .payloadStatus = static_cast<uint8_t>(ipmi::PStatus::Unknown);
627 }
628}
629
630/** @brief implements to create the oob folders and nv space
631 **/
632static Cc InitNVOOBdata()
633{
634 FILE* fptr;
635 uint16_t size;
636
637 if (!(std::filesystem::exists(biosConfigFolder)))
638 {
639 std::filesystem::create_directory(biosConfigFolder);
640 }
641
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000642 std::ifstream ifs(biosConfigNVPath, std::ios::in | std::ios::binary);
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800643
644 if (ifs.good())
645 {
646
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000647 ifs.seekg(std::ios_base::beg);
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800648 ifs.read(reinterpret_cast<char*>(&gNVOOBdata),
649 sizeof(struct NVOOBdata));
650 ifs.close();
651 return ipmi::ccSuccess;
652 }
653 return ipmi::ccResponseError;
654}
655
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800656ipmi::RspType<> ipmiOEMSetBIOSCap(ipmi::Context::ptr ctx,
657 uint8_t BIOSCapabilties, uint8_t reserved1,
658 uint8_t reserved2, uint8_t reserved3)
659{
Arun Lal K M3a1be322022-02-08 21:37:30 +0000660 if (getPostCompleted())
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800661 {
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800662 return ipmi::response(ipmiCCNotSupportedInCurrentState);
663 }
Arun Lal K M3a1be322022-02-08 21:37:30 +0000664
665 if (reserved1 != 0 || reserved2 != 0 || reserved3 != 0)
666 {
667 return ipmi::responseInvalidFieldRequest();
668 }
669
670 gNVOOBdata.mBIOSCapabilities.OOBCapability = BIOSCapabilties;
671 gNVOOBdata.mIsBIOSCapInitDone = true;
672
673 flushNVOOBdata();
674 return ipmi::responseSuccess();
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800675}
676
677ipmi::RspType<uint8_t, uint8_t, uint8_t, uint8_t>
678 ipmiOEMGetBIOSCap(ipmi::Context::ptr ctx)
679{
680 if (gNVOOBdata.mIsBIOSCapInitDone)
681 {
682 return ipmi::responseSuccess(gNVOOBdata.mBIOSCapabilities.OOBCapability,
683 0, 0, 0);
684 }
685 else
686 {
687 return ipmi::response(ipmiCCBIOSCapabilityInitNotDone);
688 }
689}
690
691ipmi::RspType<uint32_t> ipmiOEMSetPayload(ipmi::Context::ptr ctx,
692 uint8_t paramSel, uint8_t payloadType,
693 std::vector<uint8_t> payload)
694{
695 uint8_t biosCapOffsetBit = 2; // BIT:1 0-OOB BIOS config not supported
696 // 1-OOB BIOS config is supported
697
698 if (!(gNVOOBdata.mBIOSCapabilities.OOBCapability & (biosCapOffsetBit)))
699 {
700 return ipmi::response(ipmiCCBIOSCapabilityInitNotDone);
701 }
Arun Lal K M382dc972022-01-20 22:18:23 +0000702
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800703 // Validate the Payload Type
704 if (payloadType > maxPayloadSupported)
705 {
706 return ipmi::responseInvalidFieldRequest();
707 }
708
709 // We should support this Payload type 0 command only in KCS Interface
710 if (payloadType == static_cast<uint8_t>(ipmi::PType::IntelXMLType0))
711 {
Arun Lal K M3a1be322022-02-08 21:37:30 +0000712 if (getPostCompleted())
713 {
714 return ipmi::response(ipmiCCNotSupportedInCurrentState);
715 }
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800716 }
717
718 switch (static_cast<PTState>(paramSel))
719 {
720 case ipmi::PTState::StartTransfer:
721 {
722 PayloadStartTransfer* pPayloadStartTransfer =
723 reinterpret_cast<PayloadStartTransfer*>(payload.data());
724 if (payload.size() < sizeof(PayloadStartTransfer))
725 {
726 phosphor::logging::log<phosphor::logging::level::ERR>(
727 "ipmiOEMSetPayload: BIOS Config Payload size is not "
728 "correct");
729 return ipmi::responseReqDataLenInvalid();
730 }
731 cleanUpPayloadFile(payloadType);
732
733 gNVOOBdata.payloadInfo[payloadType].payloadReservationID = rand();
734 gNVOOBdata.payloadInfo[payloadType].payloadTotalChecksum =
735 pPayloadStartTransfer->payloadTotalChecksum;
736 gNVOOBdata.payloadInfo[payloadType].payloadTotalSize =
737 pPayloadStartTransfer->payloadTotalSize;
738 gNVOOBdata.payloadInfo[payloadType].payloadVersion =
739 pPayloadStartTransfer->payloadVersion;
740 gNVOOBdata.payloadInfo[payloadType].actualTotalPayloadWritten = 0;
741 gNVOOBdata.payloadInfo[payloadType].payloadStatus =
742 static_cast<uint8_t>(ipmi::PStatus::Unknown);
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000743 gNVOOBdata.payloadInfo[payloadType].payloadType = payloadType;
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800744
745 return ipmi::responseSuccess(
746 gNVOOBdata.payloadInfo[payloadType].payloadReservationID);
747 }
748 break;
749
750 case ipmi::PTState::InProgress:
751 {
752 PayloadInProgress* pPayloadInProgress =
753 reinterpret_cast<PayloadInProgress*>(payload.data());
754 PayloadInfo payloadInfo = gNVOOBdata.payloadInfo[payloadType];
755
756 if (payload.size() < sizeof(PayloadInProgress))
757 {
758 phosphor::logging::log<phosphor::logging::level::ERR>(
759 "BIOS Config Payload size is not correct");
760 return ipmi::responseReqDataLenInvalid();
761 }
762
763 if (pPayloadInProgress->payloadReservationID !=
764 payloadInfo.payloadReservationID)
765 {
Arun Lal K Mb0caca02021-09-05 22:09:33 +0000766 phosphor::logging::log<phosphor::logging::level::ERR>(
767 "BIOS Config Payload reservation ID is not correct");
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800768 return ipmi::responseInvalidReservationId();
769 }
770 payloadInfo.payloadCurrentSize =
771 pPayloadInProgress->payloadCurrentSize;
772 // Need to verify the current Payload Checksum
773 const uint8_t* data =
774 reinterpret_cast<const uint8_t*>(payload.data());
775 // we have to remove the current size, current offset, current
776 // length,checksum bytes , reservation bytes
777 boost::crc_32_type calcChecksum;
778 calcChecksum.process_bytes(data + 16, payload.size() - 16);
779 if (calcChecksum.checksum() !=
780 pPayloadInProgress->payloadCurrentChecksum)
781 {
782 phosphor::logging::log<phosphor::logging::level::ERR>(
783 "ipmiOEMSetPayload: Payload Checksum Failed");
784 return ipmi::response(ipmiCCPayloadChecksumFailed);
785 }
786 // store the data in temp file
787 std::string FilePath =
788 "/var/oob/temp" + std::to_string(payloadType);
789
790 std::ofstream outFile(FilePath, std::ios::binary | std::ios::app);
791 outFile.seekp(pPayloadInProgress->payloadOffset);
792 // we have to remove the current size, current offset, current
793 // length,checksum bytes , reservation bytes
794
795 const char* writedata =
796 reinterpret_cast<const char*>(payload.data());
797 outFile.write(writedata + 16, payload.size() - 16);
798 outFile.close();
799
800 gNVOOBdata.payloadInfo[payloadType].payloadStatus =
801 static_cast<uint8_t>(ipmi::PStatus::Unknown);
802 gNVOOBdata.payloadInfo[payloadType].actualTotalPayloadWritten +=
803 payloadInfo.payloadCurrentSize;
804 return ipmi::responseSuccess(payloadInfo.payloadCurrentSize);
805 }
806 break;
807 case ipmi::PTState::EndTransfer:
808 {
809 PayloadEndTransfer* pPayloadEndTransfer =
810 reinterpret_cast<PayloadEndTransfer*>(payload.data());
811 PayloadInfo payloadInfo = gNVOOBdata.payloadInfo[payloadType];
812 if (pPayloadEndTransfer->payloadReservationID !=
813 payloadInfo.payloadReservationID)
814 {
815 return ipmi::responseInvalidReservationId();
816 }
817 gNVOOBdata.payloadInfo[payloadType].payloadStatus =
818 static_cast<uint8_t>(ipmi::PStatus::Unknown);
819
820 if (gNVOOBdata.payloadInfo[payloadType].actualTotalPayloadWritten !=
821 gNVOOBdata.payloadInfo[payloadType].payloadTotalSize)
822 {
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800823 return ipmi::response(ipmiCCPayloadPayloadInComplete);
824 }
825 std::string tempFilePath =
826 "/var/oob/temp" + std::to_string(payloadType);
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000827 std::string payloadFilePath =
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800828 "/var/oob/Payload" + std::to_string(payloadType);
829 auto renamestatus =
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000830 std::rename(tempFilePath.c_str(), payloadFilePath.c_str());
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800831 if (renamestatus)
832 {
833 phosphor::logging::log<phosphor::logging::level::ERR>(
834 "ipmiOEMSetPayload: Renaming Payload file - failed");
835 }
836
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800837 if (payloadType == static_cast<uint8_t>(ipmi::PType::IntelXMLType0))
838 {
839 // Unzip the Intel format XML file type 0
840 auto response = generateBIOSXMLFile("/usr/bin/lzcat", "-d",
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000841 payloadFilePath.c_str());
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800842 if (response)
843 {
844
845 phosphor::logging::log<phosphor::logging::level::ERR>(
846 "ipmiOEMSetPayload: generateBIOSXMLFile - failed");
847 gNVOOBdata.payloadInfo[payloadType].payloadStatus =
848 static_cast<uint8_t>(ipmi::PStatus::Corrupted);
849 return ipmi::response(ipmiCCPayloadPayloadPacketMissed);
850 }
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000851 phosphor::logging::log<phosphor::logging::level::INFO>(
852 " ipmiOEMSetPayload : Convert XML into native-dbus DONE");
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000853
Arun Lal K Me7725612021-07-15 18:20:58 +0000854 /* So that we don't block the call */
855 auto io = getIoContext();
856 auto dbus = getSdBus();
857 if (io && dbus)
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000858 {
Arun Lal K Me7725612021-07-15 18:20:58 +0000859 std::string service = getService(*dbus, biosConfigIntf,
860 biosConfigBaseMgrPath);
861
862 boost::asio::post(*io, [service, payloadType] {
863 generateAndSendAttributesData(service, payloadType);
864 });
865 }
866 else
867 {
868 phosphor::logging::log<phosphor::logging::level::INFO>(
869 "ipmiOEMSetPayload: Unable to get io context or sdbus");
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000870 return ipmi::responseResponseError();
871 }
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800872 }
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800873
874 struct stat filestat;
875
876 /* Get entry's information. */
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000877 if (!stat(payloadFilePath.c_str(), &filestat))
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800878 {
879 gNVOOBdata.payloadInfo[payloadType].payloadTimeStamp =
880 filestat.st_mtime;
881 gNVOOBdata.payloadInfo[payloadType].payloadTotalSize =
882 filestat.st_size;
Snehalatha Venkatesh0d0dc342022-01-20 11:36:56 +0000883 gNVOOBdata.payloadInfo[payloadType].payloadStatus =
884 static_cast<uint8_t>(ipmi::PStatus::Valid);
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800885 }
886 else
887 {
888 return ipmi::responseResponseError();
889 }
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800890 flushNVOOBdata();
891 return ipmi::responseSuccess(
892 gNVOOBdata.payloadInfo[payloadType].actualTotalPayloadWritten);
893 }
894 break;
895 case ipmi::PTState::UserAbort:
896 {
897 PayloadEndTransfer* pPayloadEndTransfer =
898 reinterpret_cast<PayloadEndTransfer*>(payload.data());
899 PayloadInfo payloadInfo = gNVOOBdata.payloadInfo[payloadType];
900 if (pPayloadEndTransfer->payloadReservationID !=
901 payloadInfo.payloadReservationID)
902 {
903 return ipmi::responseInvalidReservationId();
904 }
905 gNVOOBdata.payloadInfo[payloadType].payloadReservationID = 0;
906 gNVOOBdata.payloadInfo[payloadType].payloadType = 0;
907 gNVOOBdata.payloadInfo[payloadType].payloadTotalSize = 0;
908 // Delete the temp file
909 std::string tempFilePath =
910 "/var/oob/temp" + std::to_string(payloadType);
911 unlink(tempFilePath.c_str());
912 flushNVOOBdata();
913 return ipmi::responseSuccess();
914 }
915 break;
916 default:
917 return ipmi::responseInvalidFieldRequest();
918 }
919 return ipmi::responseResponseError();
920}
921
922ipmi::RspType<message::Payload>
923 ipmiOEMGetPayload(ipmi::Context::ptr ctx, uint8_t paramSel,
924 uint8_t payloadType, ipmi::message::Payload& payload)
925{
926 // 1-OOB BIOS config is supported
927 message::Payload retValue;
928
929 if (!(gNVOOBdata.mBIOSCapabilities.OOBCapability & (biosCapOffsetBit)))
930 {
931 return ipmi::response(ipmiCCBIOSCapabilityInitNotDone);
932 }
933 // Validate the Payload Type
934 if (payloadType > maxPayloadSupported)
935 {
936 return ipmi::responseInvalidFieldRequest();
937 }
938
Arun Lal K Mb0caca02021-09-05 22:09:33 +0000939 if (payloadType == static_cast<uint8_t>(ipmi::PType::IntelXMLType1))
940 {
941 if (!payload1::update(ctx))
942 {
943 phosphor::logging::log<phosphor::logging::level::ERR>(
944 "ipmiOEMGetPayload: unable to update NVOOBdata for payloadType "
945 "= IntelXMLType1");
946 return ipmi::response(ipmi::ccUnspecifiedError);
947 }
948 }
949
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800950 struct PayloadInfo res = gNVOOBdata.payloadInfo[payloadType];
951
952 switch (static_cast<GetPayloadParameter>(paramSel))
953 {
954 case ipmi::GetPayloadParameter::GetPayloadInfo:
955 {
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000956 std::string payloadFilePath =
957 "/var/oob/Payload" + std::to_string(payloadType);
958
959 std::ifstream ifs(payloadFilePath,
960 std::ios::in | std::ios::binary | std::ios::ate);
961
962 if (!ifs.good())
963 {
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000964 phosphor::logging::log<phosphor::logging::level::ERR>(
965 "ipmiOEMGetPayload: Payload File Error");
966 // File does not exist code here
967 return ipmi::response(ipmi::ccUnspecifiedError);
968 }
Arun Lal K Mb0caca02021-09-05 22:09:33 +0000969
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000970 ifs.close();
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800971 retValue.pack(res.payloadVersion);
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000972 retValue.pack(payloadType);
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800973 retValue.pack(res.payloadTotalSize);
974 retValue.pack(res.payloadTotalChecksum);
975 retValue.pack(res.payloadflag);
976 retValue.pack(res.payloadStatus);
977 retValue.pack(res.payloadTimeStamp);
978
979 return ipmi::responseSuccess(std::move(retValue));
980 }
981
982 break;
983 case ipmi::GetPayloadParameter::GetPayloadData:
984 {
985 if (res.payloadStatus ==
986 (static_cast<uint8_t>(ipmi::PStatus::Valid)))
987 {
988 std::vector<uint32_t> reqData;
989 if (payload.unpack(reqData) || !payload.fullyUnpacked())
990 {
991 return ipmi::responseReqDataLenInvalid();
992 }
993 uint32_t offset = reqData.at(0);
994 uint32_t length = reqData.at(1);
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000995 std::string payloadFilePath =
996 "/var/oob/Payload" + std::to_string(payloadType);
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800997
Snehalatha Venkatesh0d0dc342022-01-20 11:36:56 +0000998 if (length > static_cast<uint32_t>(maxGetPayloadDataSize))
Snehalatha Venkatesh2ff15bf2021-12-30 11:51:14 +0000999 {
1000 phosphor::logging::log<phosphor::logging::level::ERR>(
1001 "ipmiOEMGetPayload: length > maxGetPayloadDataSize",
1002 phosphor::logging::entry("LENGTH=%d", length),
1003 phosphor::logging::entry("maxGetPayloadDataSize=%d",
1004 maxGetPayloadDataSize));
1005 return ipmi::responseInvalidFieldRequest();
1006 }
1007
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +00001008 std::ifstream ifs(payloadFilePath, std::ios::in |
1009 std::ios::binary |
1010 std::ios::ate);
1011
1012 if (!ifs.good())
1013 {
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +00001014 phosphor::logging::log<phosphor::logging::level::ERR>(
1015 "ipmiOEMGetPayload: Payload File Error");
1016 // File does not exist code here
1017 return ipmi::response(ipmi::ccUnspecifiedError);
1018 }
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001019 std::ifstream::pos_type fileSize = ifs.tellg();
1020 // Total file data within given offset
1021 if (fileSize < static_cast<uint64_t>(offset))
1022 {
Snehalatha Venkatesh2ff15bf2021-12-30 11:51:14 +00001023 phosphor::logging::log<phosphor::logging::level::ERR>(
1024 "ipmiOEMGetPayload: filesize < offset");
1025 return ipmi::responseInvalidFieldRequest();
1026 }
1027
1028 if ((static_cast<uint64_t>(fileSize) - offset) < length)
1029 {
1030 phosphor::logging::log<phosphor::logging::level::ERR>(
1031 "ipmiOEMGetPayload: (filesize - offset) < length ");
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001032 return ipmi::responseInvalidFieldRequest();
1033 }
1034
1035 ifs.seekg(offset, std::ios::beg);
1036 std::array<uint8_t, maxGetPayloadDataSize> Buffer;
1037 ifs.read(reinterpret_cast<char*>(Buffer.data()), length);
1038 uint32_t readCount = ifs.gcount();
1039 ifs.close();
1040
1041 boost::crc_32_type calcChecksum;
1042 calcChecksum.process_bytes(
1043 reinterpret_cast<char*>(Buffer.data()), readCount);
1044 uint32_t chkSum = calcChecksum.checksum();
1045 retValue.pack(payloadType);
1046 retValue.pack(readCount);
1047 retValue.pack(chkSum);
1048
1049 for (int i = 0; i < readCount; i++)
1050 {
1051 retValue.pack(Buffer.at(i));
1052 }
Arun Lal K Mb0caca02021-09-05 22:09:33 +00001053
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001054 return ipmi::responseSuccess(std::move(retValue));
1055 }
1056 else
1057 {
1058 return ipmi::responseResponseError();
1059 }
1060 }
1061 break;
1062 case ipmi::GetPayloadParameter::GetPayloadStatus:
1063 {
1064 retValue.pack(gNVOOBdata.payloadInfo[payloadType].payloadStatus);
1065 return ipmi::responseSuccess(std::move(retValue));
1066 }
1067 break;
1068 default:
1069 return ipmi::responseInvalidFieldRequest();
1070 }
1071 return ipmi::responseInvalidFieldRequest();
1072}
1073
1074ipmi::RspType<> ipmiOEMSetBIOSHashInfo(
1075 ipmi::Context::ptr ctx, std::array<uint8_t, maxSeedSize>& pwdSeed,
Ayushi Smriti32381872021-06-23 11:05:48 +05301076 uint8_t algoInfo, std::array<uint8_t, maxHashSize>& adminPwdHash)
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001077{
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001078 // We should not support this command after System Booted - After Exit Boot
1079 // service called
Arun Lal K M382dc972022-01-20 22:18:23 +00001080 if (getPostCompleted())
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001081 {
Ayushi Smriti32381872021-06-23 11:05:48 +05301082 return ipmi::response(ipmiCCNotSupportedInCurrentState);
1083 }
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001084
Ayushi Smriti32381872021-06-23 11:05:48 +05301085 nlohmann::json json;
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001086
Ayushi Smriti32381872021-06-23 11:05:48 +05301087 if ((algoInfo & 0xF) == algoSHA384)
1088 {
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001089 json["HashAlgo"] = "SHA384";
Ayushi Smriti32381872021-06-23 11:05:48 +05301090 }
1091 else if ((algoInfo & 0xF) == algoSHA256)
1092 {
1093 json["HashAlgo"] = "SHA256";
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001094 }
1095 else
1096 {
Ayushi Smriti32381872021-06-23 11:05:48 +05301097 return ipmi::responseInvalidFieldRequest();
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001098 }
Ayushi Smriti32381872021-06-23 11:05:48 +05301099
1100 json["Seed"] = pwdSeed;
1101 json["IsAdminPwdChanged"] = false;
1102 json["AdminPwdHash"] = adminPwdHash;
1103 json["IsUserPwdChanged"] = false;
1104
1105 std::array<uint8_t, maxHashSize> userPwdHash;
1106 userPwdHash.fill({}); // initializing with 0 as user password hash field
1107 // is not used presently
1108 json["UserPwdHash"] = userPwdHash;
1109 json["StatusFlag"] = algoInfo;
1110
1111 std::string hashFilePath = "/var/lib/bios-settings-manager/seedData";
1112 std::ofstream ofs(hashFilePath, std::ios::out);
1113 const auto& writeData = json.dump();
1114 ofs << writeData;
1115 ofs.close();
1116 return ipmi::responseSuccess();
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001117}
1118
Ayushi Smriti32381872021-06-23 11:05:48 +05301119ipmi::RspType<std::array<uint8_t, maxSeedSize>, uint8_t,
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001120 std::array<uint8_t, maxHashSize>>
1121 ipmiOEMGetBIOSHash(ipmi::Context::ptr ctx)
1122{
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001123 nlohmann::json data = nullptr;
1124
Arun Lal K M1d0bac92022-02-11 00:23:13 +00001125 // We should not support this command after System Booted - After Exit Boot
1126 // service called
Arun Lal K M3a1be322022-02-08 21:37:30 +00001127 if (getPostCompleted())
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001128 {
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001129 return ipmi::response(ipmiCCNotSupportedInCurrentState);
1130 }
Arun Lal K M3a1be322022-02-08 21:37:30 +00001131
1132 std::string HashFilePath = "/var/lib/bios-settings-manager/seedData";
1133
1134 std::ifstream devIdFile(HashFilePath);
1135 if (!devIdFile.is_open())
1136 {
1137 return ipmi::responseResponseError();
1138 }
1139
1140 try
1141 {
1142 data = nlohmann::json::parse(devIdFile, nullptr, false);
1143 }
1144 catch (const nlohmann::json::parse_error& e)
1145 {
1146 return ipmi::responseResponseError();
1147 }
1148
1149 if (data.is_discarded())
1150 {
1151 return ipmi::responseResponseError();
1152 }
1153
1154 std::array<uint8_t, maxHashSize> newAdminHash;
1155 std::array<uint8_t, maxSeedSize> seed;
1156
1157 uint8_t flag = 0;
1158 uint8_t adminPwdChangedFlag = 0;
1159 if (!data.is_discarded())
1160 {
1161
1162 adminPwdChangedFlag = data["IsAdminPwdChanged"];
1163 newAdminHash = data["AdminPwdHash"];
1164 seed = data["Seed"];
1165 }
1166
1167 auto status = getResetBIOSSettings(flag);
1168 if (status)
1169 {
1170 return ipmi::responseResponseError();
1171 }
1172 if (adminPwdChangedFlag)
1173 {
1174 flag |= adminPasswordChanged;
1175 }
1176
1177 std::copy(std::begin(newAdminHash), std::end(newAdminHash),
1178 std::begin(newAdminHash));
1179
1180 return ipmi::responseSuccess(seed, flag, newAdminHash);
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001181}
1182
1183static void registerBIOSConfigFunctions(void)
1184{
1185 phosphor::logging::log<phosphor::logging::level::INFO>(
1186 "BIOSConfig module initialization");
1187 InitNVOOBdata();
1188
1189 registerHandler(prioOemBase, intel::netFnGeneral,
1190 intel::general::cmdSetBIOSCap, Privilege::Admin,
1191 ipmiOEMSetBIOSCap);
1192
1193 registerHandler(prioOemBase, intel::netFnGeneral,
1194 intel::general::cmdGetBIOSCap, Privilege::User,
1195 ipmiOEMGetBIOSCap);
1196 registerHandler(prioOemBase, intel::netFnGeneral,
1197 intel::general::cmdSetBIOSPwdHashInfo, Privilege::Admin,
1198 ipmiOEMSetBIOSHashInfo);
1199
1200 registerHandler(prioOemBase, intel::netFnGeneral,
1201 intel::general::cmdGetBIOSPwdHash, Privilege::User,
1202 ipmiOEMGetBIOSHash);
1203
1204 registerHandler(prioOemBase, intel::netFnGeneral,
1205 intel::general::cmdGetPayload, Privilege::User,
1206 ipmiOEMGetPayload);
1207 registerHandler(prioOemBase, intel::netFnGeneral,
1208 intel::general::cmdSetPayload, Privilege::Admin,
1209 ipmiOEMSetPayload);
1210
1211 return;
1212}
1213
1214} // namespace ipmi