blob: 83b895927834d926ed2850094af054d090ef5149 [file] [log] [blame]
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001/*
2// Copyright (c) 2020 Intel Corporation
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
16
Arun Lal K Me7725612021-07-15 18:20:58 +000017#include "biosxml.hpp"
18
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +080019#include <openssl/sha.h>
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +080020
21#include <biosconfigcommands.hpp>
22#include <boost/crc.hpp>
23#include <boost/process/child.hpp>
24#include <boost/process/io.hpp>
25#include <ipmid/api.hpp>
26#include <ipmid/message.hpp>
27#include <ipmid/message/types.hpp>
28#include <ipmid/types.hpp>
29#include <ipmid/utils.hpp>
30#include <nlohmann/json.hpp>
31#include <oemcommands.hpp>
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +080032#include <sdbusplus/bus.hpp>
33#include <sdbusplus/message/types.hpp>
34
35#include <filesystem>
Suryakanth Sekarcc402592021-04-01 15:02:10 +053036#include <string_view>
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +080037
38namespace ipmi
39{
Arun Lal K Mb0caca02021-09-05 22:09:33 +000040static bool flushNVOOBdata();
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +080041static void registerBIOSConfigFunctions() __attribute__((constructor));
42
43// Define BIOS config related Completion Code
44using Cc = uint8_t;
45static constexpr Cc ipmiCCPayloadPayloadPacketMissed = 0x80;
46static constexpr Cc ipmiCCBIOSPasswordInitNotDone = 0x80;
47static constexpr Cc ipmiCCPayloadChecksumFailed = 0x81;
48static constexpr Cc ipmiCCNotSupportedInCurrentState = 0x82;
49static constexpr Cc ipmiCCPayloadPayloadInComplete = 0x83;
50static constexpr Cc ipmiCCBIOSCapabilityInitNotDone = 0x85;
51static constexpr Cc ipmiCCPayloadLengthIllegal = 0x85;
52
53static constexpr uint8_t userPasswordChanged = (1 << 5);
54static constexpr uint8_t adminPasswordChanged = (1 << 4);
Snehalatha Venkatesh6346e982022-03-09 06:49:18 +000055static constexpr uint8_t restoreDefaultValues = (1 << 7);
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +080056
57static constexpr const char* biosConfigFolder = "/var/oob";
58static constexpr const char* biosConfigNVPath = "/var/oob/nvoobdata.dat";
59static constexpr const uint8_t algoSHA384 = 2;
Ayushi Smriti32381872021-06-23 11:05:48 +053060static constexpr const uint8_t algoSHA256 = 1;
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +080061static constexpr const uint8_t biosCapOffsetBit = 0x3;
62static constexpr uint16_t maxGetPayloadDataSize = 4096;
63static constexpr const char* biosXMLFilePath = "/var/oob/bios.xml";
64static constexpr const char* biosXMLFilePath1 = "/var/oob/tempbios.xml";
65
66static constexpr const char* biosConfigBaseMgrPath =
67 "/xyz/openbmc_project/bios_config/manager";
68static constexpr const char* biosConfigIntf =
69 "xyz.openbmc_project.BIOSConfig.Manager";
70static constexpr const char* resetBIOSSettingsProp = "ResetBIOSSettings";
71/*baseBIOSTable
72map{attributeName,struct{attributeType,readonlyStatus,displayname,
73 description,menuPath,current,default,
74 array{struct{optionstring,optionvalue}}}}
75*/
Arun Lal K Me7725612021-07-15 18:20:58 +000076
77bios::BiosBaseTableType attributesData;
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +080078
79NVOOBdata gNVOOBdata;
80
81enum class PTState : uint8_t
82{
83 StartTransfer = 0,
84 InProgress = 1,
85 EndTransfer = 2,
86 UserAbort = 3
87};
88enum class PStatus : uint8_t
89{
90 Unknown = 0,
91 Valid = 1,
92 Corrupted = 2
93};
94enum class PType : uint8_t
95{
96 IntelXMLType0 = 0,
97 IntelXMLType1 = 1,
98 OTAPayload = 5,
99};
100
101//
102// GetPayload Payload status enumeration
103//
104enum class GetPayloadParameter : uint8_t
105{
106 GetPayloadInfo = 0, // 0
107 GetPayloadData = 1, // 1
Matt Simmering2daecd62022-05-19 12:50:53 -0700108 GetPayloadStatus = 2,
109 MaxPayloadParameters
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800110};
111
Arun Lal K Mb0caca02021-09-05 22:09:33 +0000112namespace payload1
113{
114
115enum class AttributesType : uint8_t
116{
117 unknown = 0,
118 string,
Arun Lal K Md2d60ab2021-12-29 19:42:03 +0000119 integer,
120 enumeration
Arun Lal K Mb0caca02021-09-05 22:09:33 +0000121};
122
123using PendingAttributesType =
124 std::map<std::string,
125 std::tuple<std::string, std::variant<int64_t, std::string>>>;
126
127AttributesType getAttrType(const std::string_view typeDbus)
128{
129 if (typeDbus == "xyz.openbmc_project.BIOSConfig.Manager."
130 "AttributeType.String")
131 {
132 return AttributesType::string;
133 }
134 else if (typeDbus == "xyz.openbmc_project.BIOSConfig."
135 "Manager.AttributeType.Integer")
136 {
137 return AttributesType::integer;
138 }
Arun Lal K Md2d60ab2021-12-29 19:42:03 +0000139 else if (typeDbus == "xyz.openbmc_project.BIOSConfig."
140 "Manager.AttributeType.Enumeration")
141 {
142 return AttributesType::enumeration;
143 }
Arun Lal K Mb0caca02021-09-05 22:09:33 +0000144
145 return AttributesType::unknown;
146}
147
148bool fillPayloadData(std::string& payloadData,
149 const std::variant<int64_t, std::string>& attributes,
150 const std::string_view key, AttributesType& attrType)
151{
152 payloadData += key;
153 payloadData += '=';
154
Arun Lal K Md2d60ab2021-12-29 19:42:03 +0000155 if (attrType == AttributesType::string ||
156 attrType == AttributesType::enumeration)
Arun Lal K Mb0caca02021-09-05 22:09:33 +0000157 {
158 if (!std::holds_alternative<std::string>(attributes))
159 {
160 phosphor::logging::log<phosphor::logging::level::ERR>(
161 "fillPayloadData: No string data in attributes");
162 return false;
163 }
164 payloadData += std::get<std::string>(attributes);
165 }
166 else if (attrType == AttributesType::integer)
167 {
168 if (!std::holds_alternative<int64_t>(attributes))
169 {
170 phosphor::logging::log<phosphor::logging::level::ERR>(
171 "fillPayloadData: No int64_t data in attributes");
172 return false;
173 }
174 payloadData += std::to_string(std::get<int64_t>(attributes));
175 }
176 else
177 {
178 phosphor::logging::log<phosphor::logging::level::ERR>(
179 "fillPayloadData: Unsupported attribute type");
180 return false;
181 }
182
183 payloadData += '\n';
184
185 return true;
186}
187
188bool getPendingList(ipmi::Context::ptr ctx, std::string& payloadData)
189{
190 std::variant<PendingAttributesType> pendingAttributesData;
191 boost::system::error_code ec;
192
193 payloadData.clear();
194
195 auto dbus = getSdBus();
196 if (!dbus)
197 {
198 phosphor::logging::log<phosphor::logging::level::ERR>(
199 "getPendingList: getSdBus() failed");
200 return false;
201 }
202
203 std::string service =
204 getService(*dbus, biosConfigIntf, biosConfigBaseMgrPath);
205
206 try
207 {
208 pendingAttributesData =
209 dbus->yield_method_call<std::variant<PendingAttributesType>>(
210 ctx->yield, ec, service,
211 "/xyz/openbmc_project/bios_config/manager",
212 "org.freedesktop.DBus.Properties", "Get",
213 "xyz.openbmc_project.BIOSConfig.Manager", "PendingAttributes");
214 }
Patrick Williamsbd51e6a2021-10-06 13:09:44 -0500215 catch (const std::exception& ex)
Arun Lal K Mb0caca02021-09-05 22:09:33 +0000216 {
217 phosphor::logging::log<phosphor::logging::level::ERR>(ex.what());
218 return false;
219 }
220
221 if (ec)
222 {
223 std::string err = "getPendingList: error while trying to get "
224 "PendingAttributes, error = ";
225 err += ec.message();
226
227 phosphor::logging::log<phosphor::logging::level::ERR>(err.c_str());
228
229 return false;
230 }
231
232 const PendingAttributesType* pendingAttributes =
233 std::get_if<PendingAttributesType>(&pendingAttributesData);
234 if (!pendingAttributes)
235 {
236 phosphor::logging::log<phosphor::logging::level::ERR>(
237 "getPendingList: pendingAttributes is null");
238 return false;
239 }
240
241 for (const auto& [key, attributes] : *pendingAttributes)
242 {
243 const std::string& itemType = std::get<0>(attributes);
244 AttributesType attrType = getAttrType(itemType);
245
246 if (!fillPayloadData(payloadData, std::get<1>(attributes), key,
247 attrType))
248 {
249 return false;
250 }
251 }
252
253 if (payloadData.empty())
254 {
255 phosphor::logging::log<phosphor::logging::level::ERR>(
256 "getPendingList: payloadData is empty");
257 return false;
258 }
259
260 return true;
261}
262bool updatePayloadFile(std::string& payloadFilePath, std::string payloadData)
263{
264 std::ofstream payloadFile(payloadFilePath,
265 std::ios::out | std::ios::binary);
266
267 payloadFile << payloadData;
268
269 if (!payloadFile.good())
270 {
271 return false;
272 }
273
274 return true;
275}
276
277bool computeCheckSum(std::string& payloadFilePath,
278 boost::crc_32_type& calcChecksum)
279{
280 std::ifstream payloadFile(payloadFilePath.c_str(),
281 std::ios::in | std::ios::binary | std::ios::ate);
282
283 if (!payloadFile.good())
284 {
285 phosphor::logging::log<phosphor::logging::level::ERR>(
286 "computeCheckSum: Cannot open Payload1 file");
287 return false;
288 }
289
290 payloadFile.seekg(0, payloadFile.end);
291 int length = payloadFile.tellg();
292 payloadFile.seekg(0, payloadFile.beg);
293
294 if (maxGetPayloadDataSize < length)
295 {
296 phosphor::logging::log<phosphor::logging::level::ERR>(
297 "computeCheckSum: length > maxGetPayloadDataSize");
298 return false;
299 }
300
301 std::unique_ptr<char[]> payloadBuffer(new char[length]);
302
303 payloadFile.read(payloadBuffer.get(), length);
304 uint32_t readCount = payloadFile.gcount();
305
306 calcChecksum.process_bytes(payloadBuffer.get(), readCount);
307
308 return true;
309}
310
311bool updatePayloadInfo(std::string& payloadFilePath)
312{
313 boost::crc_32_type calcChecksum;
314
315 uint8_t payloadType = static_cast<uint8_t>(ipmi::PType::IntelXMLType1);
316 auto& payloadInfo = gNVOOBdata.payloadInfo[payloadType];
317
318 if (!computeCheckSum(payloadFilePath, calcChecksum))
319 {
320 phosphor::logging::log<phosphor::logging::level::ERR>(
321 "updatePayloadInfo: Cannot compute checksum for Payload1 file");
322 return false;
323 }
324
325 payloadInfo.payloadVersion = 0;
326 payloadInfo.payloadflag = 0;
327 payloadInfo.payloadReservationID = rand();
328
329 payloadInfo.payloadType = payloadType;
330
331 payloadInfo.payloadTotalChecksum = calcChecksum.checksum();
332 payloadInfo.payloadCurrentChecksum = payloadInfo.payloadTotalChecksum;
333
334 payloadInfo.payloadStatus = (static_cast<uint8_t>(ipmi::PStatus::Valid));
335
336 struct stat filestat;
337 /* Get entry's information. */
338 if (!stat(payloadFilePath.c_str(), &filestat))
339 {
340 payloadInfo.payloadTimeStamp = filestat.st_mtime;
341 payloadInfo.payloadTotalSize = filestat.st_size;
342 payloadInfo.payloadCurrentSize = filestat.st_size;
343 payloadInfo.actualTotalPayloadWritten = filestat.st_size;
344 }
345 else
346 {
347 phosphor::logging::log<phosphor::logging::level::ERR>(
348 "updatePayloadInfo: Cannot get file status for Payload1 file");
349 return false;
350 }
351
352 if (!flushNVOOBdata())
353 {
354 phosphor::logging::log<phosphor::logging::level::ERR>(
355 "updatePayloadInfo: flushNVOOBdata failed");
356 return false;
357 }
358
359 return true;
360}
361
362bool update(ipmi::Context::ptr ctx)
363{
364 std::string payloadFilePath =
365 "/var/oob/Payload" +
366 std::to_string(static_cast<uint8_t>(ipmi::PType::IntelXMLType1));
367
368 std::string payloadData;
369
370 if (!getPendingList(ctx, payloadData))
371 {
372 phosphor::logging::log<phosphor::logging::level::ERR>(
373 "payload1::update : getPendingList() failed");
374 return false;
375 }
376
377 if (!updatePayloadFile(payloadFilePath, payloadData))
378 {
379 phosphor::logging::log<phosphor::logging::level::ERR>(
380 "payload1::update : updatePayloadFile() failed");
381 return false;
382 }
383
384 if (!updatePayloadInfo(payloadFilePath))
385 {
386 phosphor::logging::log<phosphor::logging::level::ERR>(
387 "payload1::update : updatePayloadInfo() failed");
388 return false;
389 }
390
391 return true;
392}
393} // namespace payload1
394
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800395/** @brief implement to set the BaseBIOSTable property
396 * @returns status
397 */
Arun Lal K Me7725612021-07-15 18:20:58 +0000398static bool sendAllAttributes(std::string service)
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800399{
Arun Lal K Me7725612021-07-15 18:20:58 +0000400 std::shared_ptr<sdbusplus::asio::connection> pSdBusPlus = getSdBus();
401
402 if (pSdBusPlus)
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800403 {
Arun Lal K Me7725612021-07-15 18:20:58 +0000404 try
405 {
406 pSdBusPlus->async_method_call(
407 [](const boost::system::error_code ec) {
408 /* No more need to keep attributes data in memory */
409 attributesData.clear();
410
411 if (ec)
412 {
413 phosphor::logging::log<phosphor::logging::level::ERR>(
414 "sendAllAttributes error: send all attributes - "
415 "failed");
416 return;
417 }
418
419 phosphor::logging::log<phosphor::logging::level::INFO>(
420 "sendAllAttributes: send all attributes - done");
421 },
422 service, biosConfigBaseMgrPath,
423 "org.freedesktop.DBus.Properties", "Set", biosConfigIntf,
424 "BaseBIOSTable",
425 std::variant<bios::BiosBaseTableType>(attributesData));
426
427 return true;
428 }
Patrick Williamsbd51e6a2021-10-06 13:09:44 -0500429 catch (const std::exception& ex)
Arun Lal K Me7725612021-07-15 18:20:58 +0000430 {
431 phosphor::logging::log<phosphor::logging::level::ERR>(ex.what());
432 }
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800433 }
Arun Lal K Me7725612021-07-15 18:20:58 +0000434
435 return false;
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800436}
437
438/** @brief implement to flush the updated data in nv space
439 * @returns status
440 */
Arun Lal K Mb0caca02021-09-05 22:09:33 +0000441static bool flushNVOOBdata()
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800442{
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000443 std::ofstream outFile(biosConfigNVPath, std::ios::binary);
Arun Lal K Mb0caca02021-09-05 22:09:33 +0000444
445 outFile.seekp(std::ios_base::beg);
446 const char* writedata = reinterpret_cast<const char*>(&gNVOOBdata);
447 outFile.write(writedata, sizeof(struct NVOOBdata));
448
449 if (!outFile.good())
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800450 {
Arun Lal K Mb0caca02021-09-05 22:09:33 +0000451 return false;
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800452 }
Arun Lal K Mb0caca02021-09-05 22:09:33 +0000453
454 return true;
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800455}
456
457/** @brief implement to get the System State
458 * @returns status
459 */
Arun Lal K M382dc972022-01-20 22:18:23 +0000460static bool getPostCompleted()
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800461{
Arun Lal K M382dc972022-01-20 22:18:23 +0000462 /*
463 * In case of failure we treat postCompleted as true.
464 * So that BIOS config commands is not accepted by BMC by mistake.
465 */
466 bool postCompleted = true;
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800467
468 try
469 {
470 std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
471 Value variant =
472 getDbusProperty(*dbus, "xyz.openbmc_project.State.OperatingSystem",
473 "/xyz/openbmc_project/state/os",
474 "xyz.openbmc_project.State.OperatingSystem.Status",
475 "OperatingSystemState");
Arun Lal K M382dc972022-01-20 22:18:23 +0000476 auto& value = std::get<std::string>(variant);
477
478 // The short strings "Standby" is deprecated in favor of the
479 // full enum strings. Support for the short strings will be
480 // removed in the future.
481 postCompleted = (value == "Standby") ||
482 (value == "xyz.openbmc_project.State.OperatingSystem."
483 "Status.OSStatus.Standby");
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800484 }
485 catch (const std::exception& e)
486 {
Arun Lal K M382dc972022-01-20 22:18:23 +0000487 phosphor::logging::log<phosphor::logging::level::ERR>(
488 "'getDbusProperty' failed to read "
489 "xyz.openbmc_project.State.OperatingSystem");
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800490 }
Arun Lal K M382dc972022-01-20 22:18:23 +0000491
492 return postCompleted;
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800493}
494
495/** @brief implement to get the Rest BIOS property
496 * @returns status
497 */
498static int getResetBIOSSettings(uint8_t& ResetFlag)
499{
500
501 try
502 {
503 std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
504 std::string service =
505 getService(*dbus, biosConfigIntf, biosConfigBaseMgrPath);
506 Value variant = getDbusProperty(*dbus, service, biosConfigBaseMgrPath,
507 biosConfigIntf, resetBIOSSettingsProp);
Suryakanth Sekarcc402592021-04-01 15:02:10 +0530508
509 std::string_view ResetStr = std::get<std::string>(variant);
510 if (ResetStr ==
511 "xyz.openbmc_project.BIOSConfig.Manager.ResetFlag.NoAction")
512 {
513 ResetFlag = 0;
514 }
515 else if (ResetStr == "xyz.openbmc_project.BIOSConfig.Manager.ResetFlag."
516 "FactoryDefaults")
517 {
518 ResetFlag = 1;
519 }
520 else if (ResetStr == "xyz.openbmc_project.BIOSConfig.Manager.ResetFlag."
521 "FailSafeDefaults")
522 {
523 ResetFlag = 2;
524 }
525 else
526 {
527 return ipmi::ccUnspecifiedError;
528 }
529
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800530 return ipmi::ccSuccess;
531 }
532 catch (const std::exception& e)
533 {
534 return ipmi::ccUnspecifiedError;
535 }
536}
537
Arun Lal K Me7725612021-07-15 18:20:58 +0000538/** @brief Get attributes data (bios base table) from bios.xml
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800539 */
Arun Lal K Me7725612021-07-15 18:20:58 +0000540static bool generateAttributesData()
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800541{
Arun Lal K Me7725612021-07-15 18:20:58 +0000542 try
543 {
544 bios::Xml biosxml(biosXMLFilePath);
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800545
Arun Lal K Me7725612021-07-15 18:20:58 +0000546 if (!biosxml.doDepexCompute())
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800547 {
Arun Lal K Me7725612021-07-15 18:20:58 +0000548 phosphor::logging::log<phosphor::logging::level::ERR>(
549 "'depex' compute failed");
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800550 }
Arun Lal K Me7725612021-07-15 18:20:58 +0000551
552 if (!biosxml.getBaseTable(attributesData))
553 {
554 phosphor::logging::log<phosphor::logging::level::ERR>(
555 "Failed to get bios base table");
556 }
557 }
Patrick Williamsbd51e6a2021-10-06 13:09:44 -0500558 catch (const std::exception& ex)
Arun Lal K Me7725612021-07-15 18:20:58 +0000559 {
560 phosphor::logging::log<phosphor::logging::level::ERR>(ex.what());
561 return false;
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800562 }
563
Arun Lal K Me7725612021-07-15 18:20:58 +0000564 return true;
565}
566
567/** @brief Generate attributes data from bios.xml
568 * and send attributes data (bios base table) to dbus using set method.
569 */
570static void generateAndSendAttributesData(std::string service,
571 uint8_t payloadType)
572{
573 if (!generateAttributesData())
574 {
575 phosphor::logging::log<phosphor::logging::level::ERR>(
576 "generateAndSendAttributesData: generateAttributesData - failed");
577 gNVOOBdata.payloadInfo[payloadType].payloadStatus =
578 static_cast<uint8_t>(ipmi::PStatus::Corrupted);
579 return;
580 }
581
582 phosphor::logging::log<phosphor::logging::level::INFO>(
583 "generateAndSendAttributesData : generateAttributesData is done");
584
585 if (!sendAllAttributes(service))
586 {
587 phosphor::logging::log<phosphor::logging::level::ERR>(
588 "generateAndSendAttributesData: sendAllAttributes - failed");
589 gNVOOBdata.payloadInfo[payloadType].payloadStatus =
590 static_cast<uint8_t>(ipmi::PStatus::Corrupted);
591 return;
592 }
593
594 phosphor::logging::log<phosphor::logging::level::INFO>(
595 "generateAndSendAttributesData : sendAllAttributes is done");
596 gNVOOBdata.payloadInfo[payloadType].payloadStatus =
597 static_cast<uint8_t>(ipmi::PStatus::Valid);
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800598}
599
600/** @brief implement executing the linux command to uncompress and generate the
601 * xmlfile
602 * @param[in] linux command
603 * @returns status
604 */
605template <typename... ArgTypes>
606static int generateBIOSXMLFile(const char* path, ArgTypes&&... tArgs)
607{
608
609 boost::process::child execProg(path, const_cast<char*>(tArgs)...,
610 boost::process::std_out > biosXMLFilePath);
611 execProg.wait();
612 return execProg.exit_code();
613}
614
615/** @brief implements to clean up the temp/ existing payload file
616 **/
617static void cleanUpPayloadFile(uint8_t& payloadType)
618{
619 // Clear the payload Information
620 std::string FilePath = "/var/oob/temp" + std::to_string(payloadType);
621 unlink(FilePath.c_str());
622 FilePath = "/var/oob/Payload" + std::to_string(payloadType);
623 unlink(FilePath.c_str());
624 if (payloadType == static_cast<uint8_t>(ipmi::PType::IntelXMLType0))
625 {
626 unlink("/var/oob/Payload1");
627 gNVOOBdata.payloadInfo[static_cast<uint8_t>(ipmi::PType::IntelXMLType1)]
628 .payloadStatus = static_cast<uint8_t>(ipmi::PStatus::Unknown);
629 }
630}
631
632/** @brief implements to create the oob folders and nv space
633 **/
634static Cc InitNVOOBdata()
635{
636 FILE* fptr;
637 uint16_t size;
638
639 if (!(std::filesystem::exists(biosConfigFolder)))
640 {
641 std::filesystem::create_directory(biosConfigFolder);
642 }
643
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000644 std::ifstream ifs(biosConfigNVPath, std::ios::in | std::ios::binary);
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800645
646 if (ifs.good())
647 {
648
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000649 ifs.seekg(std::ios_base::beg);
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800650 ifs.read(reinterpret_cast<char*>(&gNVOOBdata),
651 sizeof(struct NVOOBdata));
652 ifs.close();
653 return ipmi::ccSuccess;
654 }
655 return ipmi::ccResponseError;
656}
657
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800658ipmi::RspType<> ipmiOEMSetBIOSCap(ipmi::Context::ptr ctx,
659 uint8_t BIOSCapabilties, uint8_t reserved1,
660 uint8_t reserved2, uint8_t reserved3)
661{
Arun Lal K M3a1be322022-02-08 21:37:30 +0000662 if (getPostCompleted())
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800663 {
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800664 return ipmi::response(ipmiCCNotSupportedInCurrentState);
665 }
Arun Lal K M3a1be322022-02-08 21:37:30 +0000666
667 if (reserved1 != 0 || reserved2 != 0 || reserved3 != 0)
668 {
669 return ipmi::responseInvalidFieldRequest();
670 }
671
672 gNVOOBdata.mBIOSCapabilities.OOBCapability = BIOSCapabilties;
673 gNVOOBdata.mIsBIOSCapInitDone = true;
674
675 flushNVOOBdata();
676 return ipmi::responseSuccess();
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800677}
678
679ipmi::RspType<uint8_t, uint8_t, uint8_t, uint8_t>
680 ipmiOEMGetBIOSCap(ipmi::Context::ptr ctx)
681{
682 if (gNVOOBdata.mIsBIOSCapInitDone)
683 {
684 return ipmi::responseSuccess(gNVOOBdata.mBIOSCapabilities.OOBCapability,
685 0, 0, 0);
686 }
687 else
688 {
689 return ipmi::response(ipmiCCBIOSCapabilityInitNotDone);
690 }
691}
692
693ipmi::RspType<uint32_t> ipmiOEMSetPayload(ipmi::Context::ptr ctx,
694 uint8_t paramSel, uint8_t payloadType,
695 std::vector<uint8_t> payload)
696{
697 uint8_t biosCapOffsetBit = 2; // BIT:1 0-OOB BIOS config not supported
698 // 1-OOB BIOS config is supported
699
700 if (!(gNVOOBdata.mBIOSCapabilities.OOBCapability & (biosCapOffsetBit)))
701 {
702 return ipmi::response(ipmiCCBIOSCapabilityInitNotDone);
703 }
Arun Lal K M382dc972022-01-20 22:18:23 +0000704
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800705 // Validate the Payload Type
706 if (payloadType > maxPayloadSupported)
707 {
708 return ipmi::responseInvalidFieldRequest();
709 }
710
711 // We should support this Payload type 0 command only in KCS Interface
712 if (payloadType == static_cast<uint8_t>(ipmi::PType::IntelXMLType0))
713 {
Arun Lal K M3a1be322022-02-08 21:37:30 +0000714 if (getPostCompleted())
715 {
716 return ipmi::response(ipmiCCNotSupportedInCurrentState);
717 }
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800718 }
719
720 switch (static_cast<PTState>(paramSel))
721 {
722 case ipmi::PTState::StartTransfer:
723 {
724 PayloadStartTransfer* pPayloadStartTransfer =
725 reinterpret_cast<PayloadStartTransfer*>(payload.data());
726 if (payload.size() < sizeof(PayloadStartTransfer))
727 {
728 phosphor::logging::log<phosphor::logging::level::ERR>(
729 "ipmiOEMSetPayload: BIOS Config Payload size is not "
730 "correct");
731 return ipmi::responseReqDataLenInvalid();
732 }
733 cleanUpPayloadFile(payloadType);
734
735 gNVOOBdata.payloadInfo[payloadType].payloadReservationID = rand();
736 gNVOOBdata.payloadInfo[payloadType].payloadTotalChecksum =
737 pPayloadStartTransfer->payloadTotalChecksum;
738 gNVOOBdata.payloadInfo[payloadType].payloadTotalSize =
739 pPayloadStartTransfer->payloadTotalSize;
740 gNVOOBdata.payloadInfo[payloadType].payloadVersion =
741 pPayloadStartTransfer->payloadVersion;
742 gNVOOBdata.payloadInfo[payloadType].actualTotalPayloadWritten = 0;
743 gNVOOBdata.payloadInfo[payloadType].payloadStatus =
744 static_cast<uint8_t>(ipmi::PStatus::Unknown);
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000745 gNVOOBdata.payloadInfo[payloadType].payloadType = payloadType;
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800746
747 return ipmi::responseSuccess(
748 gNVOOBdata.payloadInfo[payloadType].payloadReservationID);
749 }
750 break;
751
752 case ipmi::PTState::InProgress:
753 {
754 PayloadInProgress* pPayloadInProgress =
755 reinterpret_cast<PayloadInProgress*>(payload.data());
756 PayloadInfo payloadInfo = gNVOOBdata.payloadInfo[payloadType];
757
758 if (payload.size() < sizeof(PayloadInProgress))
759 {
760 phosphor::logging::log<phosphor::logging::level::ERR>(
761 "BIOS Config Payload size is not correct");
762 return ipmi::responseReqDataLenInvalid();
763 }
764
765 if (pPayloadInProgress->payloadReservationID !=
766 payloadInfo.payloadReservationID)
767 {
Arun Lal K Mb0caca02021-09-05 22:09:33 +0000768 phosphor::logging::log<phosphor::logging::level::ERR>(
769 "BIOS Config Payload reservation ID is not correct");
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800770 return ipmi::responseInvalidReservationId();
771 }
772 payloadInfo.payloadCurrentSize =
773 pPayloadInProgress->payloadCurrentSize;
774 // Need to verify the current Payload Checksum
775 const uint8_t* data =
776 reinterpret_cast<const uint8_t*>(payload.data());
777 // we have to remove the current size, current offset, current
778 // length,checksum bytes , reservation bytes
779 boost::crc_32_type calcChecksum;
780 calcChecksum.process_bytes(data + 16, payload.size() - 16);
781 if (calcChecksum.checksum() !=
782 pPayloadInProgress->payloadCurrentChecksum)
783 {
784 phosphor::logging::log<phosphor::logging::level::ERR>(
785 "ipmiOEMSetPayload: Payload Checksum Failed");
786 return ipmi::response(ipmiCCPayloadChecksumFailed);
787 }
788 // store the data in temp file
789 std::string FilePath =
790 "/var/oob/temp" + std::to_string(payloadType);
791
792 std::ofstream outFile(FilePath, std::ios::binary | std::ios::app);
793 outFile.seekp(pPayloadInProgress->payloadOffset);
794 // we have to remove the current size, current offset, current
795 // length,checksum bytes , reservation bytes
796
797 const char* writedata =
798 reinterpret_cast<const char*>(payload.data());
799 outFile.write(writedata + 16, payload.size() - 16);
800 outFile.close();
801
802 gNVOOBdata.payloadInfo[payloadType].payloadStatus =
803 static_cast<uint8_t>(ipmi::PStatus::Unknown);
804 gNVOOBdata.payloadInfo[payloadType].actualTotalPayloadWritten +=
805 payloadInfo.payloadCurrentSize;
806 return ipmi::responseSuccess(payloadInfo.payloadCurrentSize);
807 }
808 break;
809 case ipmi::PTState::EndTransfer:
810 {
811 PayloadEndTransfer* pPayloadEndTransfer =
812 reinterpret_cast<PayloadEndTransfer*>(payload.data());
813 PayloadInfo payloadInfo = gNVOOBdata.payloadInfo[payloadType];
814 if (pPayloadEndTransfer->payloadReservationID !=
815 payloadInfo.payloadReservationID)
816 {
817 return ipmi::responseInvalidReservationId();
818 }
819 gNVOOBdata.payloadInfo[payloadType].payloadStatus =
820 static_cast<uint8_t>(ipmi::PStatus::Unknown);
821
822 if (gNVOOBdata.payloadInfo[payloadType].actualTotalPayloadWritten !=
823 gNVOOBdata.payloadInfo[payloadType].payloadTotalSize)
824 {
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800825 return ipmi::response(ipmiCCPayloadPayloadInComplete);
826 }
827 std::string tempFilePath =
828 "/var/oob/temp" + std::to_string(payloadType);
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000829 std::string payloadFilePath =
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800830 "/var/oob/Payload" + std::to_string(payloadType);
831 auto renamestatus =
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000832 std::rename(tempFilePath.c_str(), payloadFilePath.c_str());
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800833 if (renamestatus)
834 {
835 phosphor::logging::log<phosphor::logging::level::ERR>(
836 "ipmiOEMSetPayload: Renaming Payload file - failed");
837 }
838
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800839 if (payloadType == static_cast<uint8_t>(ipmi::PType::IntelXMLType0))
840 {
841 // Unzip the Intel format XML file type 0
842 auto response = generateBIOSXMLFile("/usr/bin/lzcat", "-d",
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000843 payloadFilePath.c_str());
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800844 if (response)
845 {
846
847 phosphor::logging::log<phosphor::logging::level::ERR>(
848 "ipmiOEMSetPayload: generateBIOSXMLFile - failed");
849 gNVOOBdata.payloadInfo[payloadType].payloadStatus =
850 static_cast<uint8_t>(ipmi::PStatus::Corrupted);
851 return ipmi::response(ipmiCCPayloadPayloadPacketMissed);
852 }
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000853 phosphor::logging::log<phosphor::logging::level::INFO>(
854 " ipmiOEMSetPayload : Convert XML into native-dbus DONE");
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000855
Arun Lal K Me7725612021-07-15 18:20:58 +0000856 /* So that we don't block the call */
857 auto io = getIoContext();
858 auto dbus = getSdBus();
859 if (io && dbus)
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000860 {
Arun Lal K Me7725612021-07-15 18:20:58 +0000861 std::string service = getService(*dbus, biosConfigIntf,
862 biosConfigBaseMgrPath);
863
864 boost::asio::post(*io, [service, payloadType] {
865 generateAndSendAttributesData(service, payloadType);
866 });
867 }
868 else
869 {
870 phosphor::logging::log<phosphor::logging::level::INFO>(
871 "ipmiOEMSetPayload: Unable to get io context or sdbus");
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000872 return ipmi::responseResponseError();
873 }
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800874 }
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800875
876 struct stat filestat;
877
878 /* Get entry's information. */
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000879 if (!stat(payloadFilePath.c_str(), &filestat))
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800880 {
881 gNVOOBdata.payloadInfo[payloadType].payloadTimeStamp =
882 filestat.st_mtime;
883 gNVOOBdata.payloadInfo[payloadType].payloadTotalSize =
884 filestat.st_size;
Snehalatha Venkatesh0d0dc342022-01-20 11:36:56 +0000885 gNVOOBdata.payloadInfo[payloadType].payloadStatus =
886 static_cast<uint8_t>(ipmi::PStatus::Valid);
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800887 }
888 else
889 {
890 return ipmi::responseResponseError();
891 }
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800892 flushNVOOBdata();
893 return ipmi::responseSuccess(
894 gNVOOBdata.payloadInfo[payloadType].actualTotalPayloadWritten);
895 }
896 break;
897 case ipmi::PTState::UserAbort:
898 {
899 PayloadEndTransfer* pPayloadEndTransfer =
900 reinterpret_cast<PayloadEndTransfer*>(payload.data());
901 PayloadInfo payloadInfo = gNVOOBdata.payloadInfo[payloadType];
902 if (pPayloadEndTransfer->payloadReservationID !=
903 payloadInfo.payloadReservationID)
904 {
905 return ipmi::responseInvalidReservationId();
906 }
907 gNVOOBdata.payloadInfo[payloadType].payloadReservationID = 0;
908 gNVOOBdata.payloadInfo[payloadType].payloadType = 0;
909 gNVOOBdata.payloadInfo[payloadType].payloadTotalSize = 0;
910 // Delete the temp file
911 std::string tempFilePath =
912 "/var/oob/temp" + std::to_string(payloadType);
913 unlink(tempFilePath.c_str());
914 flushNVOOBdata();
915 return ipmi::responseSuccess();
916 }
917 break;
918 default:
919 return ipmi::responseInvalidFieldRequest();
920 }
921 return ipmi::responseResponseError();
922}
923
924ipmi::RspType<message::Payload>
925 ipmiOEMGetPayload(ipmi::Context::ptr ctx, uint8_t paramSel,
926 uint8_t payloadType, ipmi::message::Payload& payload)
927{
928 // 1-OOB BIOS config is supported
929 message::Payload retValue;
930
Matt Simmering2daecd62022-05-19 12:50:53 -0700931 if (static_cast<GetPayloadParameter>(paramSel) >=
932 ipmi::GetPayloadParameter::MaxPayloadParameters)
933 {
934 return ipmi::responseInvalidFieldRequest();
935 }
936
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800937 if (!(gNVOOBdata.mBIOSCapabilities.OOBCapability & (biosCapOffsetBit)))
938 {
939 return ipmi::response(ipmiCCBIOSCapabilityInitNotDone);
940 }
941 // Validate the Payload Type
942 if (payloadType > maxPayloadSupported)
943 {
944 return ipmi::responseInvalidFieldRequest();
945 }
946
Arun Lal K Mb0caca02021-09-05 22:09:33 +0000947 if (payloadType == static_cast<uint8_t>(ipmi::PType::IntelXMLType1))
948 {
949 if (!payload1::update(ctx))
950 {
951 phosphor::logging::log<phosphor::logging::level::ERR>(
952 "ipmiOEMGetPayload: unable to update NVOOBdata for payloadType "
953 "= IntelXMLType1");
954 return ipmi::response(ipmi::ccUnspecifiedError);
955 }
956 }
957
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800958 struct PayloadInfo res = gNVOOBdata.payloadInfo[payloadType];
959
960 switch (static_cast<GetPayloadParameter>(paramSel))
961 {
962 case ipmi::GetPayloadParameter::GetPayloadInfo:
963 {
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000964 std::string payloadFilePath =
965 "/var/oob/Payload" + std::to_string(payloadType);
966
967 std::ifstream ifs(payloadFilePath,
968 std::ios::in | std::ios::binary | std::ios::ate);
969
970 if (!ifs.good())
971 {
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000972 phosphor::logging::log<phosphor::logging::level::ERR>(
973 "ipmiOEMGetPayload: Payload File Error");
974 // File does not exist code here
975 return ipmi::response(ipmi::ccUnspecifiedError);
976 }
Arun Lal K Mb0caca02021-09-05 22:09:33 +0000977
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000978 ifs.close();
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800979 retValue.pack(res.payloadVersion);
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +0000980 retValue.pack(payloadType);
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +0800981 retValue.pack(res.payloadTotalSize);
982 retValue.pack(res.payloadTotalChecksum);
983 retValue.pack(res.payloadflag);
984 retValue.pack(res.payloadStatus);
985 retValue.pack(res.payloadTimeStamp);
986
987 return ipmi::responseSuccess(std::move(retValue));
988 }
989
990 break;
991 case ipmi::GetPayloadParameter::GetPayloadData:
992 {
993 if (res.payloadStatus ==
994 (static_cast<uint8_t>(ipmi::PStatus::Valid)))
995 {
996 std::vector<uint32_t> reqData;
997 if (payload.unpack(reqData) || !payload.fullyUnpacked())
998 {
999 return ipmi::responseReqDataLenInvalid();
1000 }
1001 uint32_t offset = reqData.at(0);
1002 uint32_t length = reqData.at(1);
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +00001003 std::string payloadFilePath =
1004 "/var/oob/Payload" + std::to_string(payloadType);
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001005
Snehalatha Venkatesh0d0dc342022-01-20 11:36:56 +00001006 if (length > static_cast<uint32_t>(maxGetPayloadDataSize))
Snehalatha Venkatesh2ff15bf2021-12-30 11:51:14 +00001007 {
1008 phosphor::logging::log<phosphor::logging::level::ERR>(
1009 "ipmiOEMGetPayload: length > maxGetPayloadDataSize",
1010 phosphor::logging::entry("LENGTH=%d", length),
1011 phosphor::logging::entry("maxGetPayloadDataSize=%d",
1012 maxGetPayloadDataSize));
1013 return ipmi::responseInvalidFieldRequest();
1014 }
1015
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +00001016 std::ifstream ifs(payloadFilePath, std::ios::in |
1017 std::ios::binary |
1018 std::ios::ate);
1019
1020 if (!ifs.good())
1021 {
Suryakanth Sekar5dd161f2021-06-16 13:02:25 +00001022 phosphor::logging::log<phosphor::logging::level::ERR>(
1023 "ipmiOEMGetPayload: Payload File Error");
1024 // File does not exist code here
1025 return ipmi::response(ipmi::ccUnspecifiedError);
1026 }
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001027 std::ifstream::pos_type fileSize = ifs.tellg();
1028 // Total file data within given offset
1029 if (fileSize < static_cast<uint64_t>(offset))
1030 {
Snehalatha Venkatesh2ff15bf2021-12-30 11:51:14 +00001031 phosphor::logging::log<phosphor::logging::level::ERR>(
1032 "ipmiOEMGetPayload: filesize < offset");
1033 return ipmi::responseInvalidFieldRequest();
1034 }
1035
1036 if ((static_cast<uint64_t>(fileSize) - offset) < length)
1037 {
1038 phosphor::logging::log<phosphor::logging::level::ERR>(
1039 "ipmiOEMGetPayload: (filesize - offset) < length ");
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001040 return ipmi::responseInvalidFieldRequest();
1041 }
1042
1043 ifs.seekg(offset, std::ios::beg);
1044 std::array<uint8_t, maxGetPayloadDataSize> Buffer;
1045 ifs.read(reinterpret_cast<char*>(Buffer.data()), length);
1046 uint32_t readCount = ifs.gcount();
1047 ifs.close();
1048
1049 boost::crc_32_type calcChecksum;
1050 calcChecksum.process_bytes(
1051 reinterpret_cast<char*>(Buffer.data()), readCount);
1052 uint32_t chkSum = calcChecksum.checksum();
1053 retValue.pack(payloadType);
1054 retValue.pack(readCount);
1055 retValue.pack(chkSum);
1056
1057 for (int i = 0; i < readCount; i++)
1058 {
1059 retValue.pack(Buffer.at(i));
1060 }
Arun Lal K Mb0caca02021-09-05 22:09:33 +00001061
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001062 return ipmi::responseSuccess(std::move(retValue));
1063 }
1064 else
1065 {
1066 return ipmi::responseResponseError();
1067 }
1068 }
1069 break;
1070 case ipmi::GetPayloadParameter::GetPayloadStatus:
1071 {
1072 retValue.pack(gNVOOBdata.payloadInfo[payloadType].payloadStatus);
1073 return ipmi::responseSuccess(std::move(retValue));
1074 }
1075 break;
1076 default:
1077 return ipmi::responseInvalidFieldRequest();
1078 }
1079 return ipmi::responseInvalidFieldRequest();
1080}
1081
1082ipmi::RspType<> ipmiOEMSetBIOSHashInfo(
1083 ipmi::Context::ptr ctx, std::array<uint8_t, maxSeedSize>& pwdSeed,
Ayushi Smriti32381872021-06-23 11:05:48 +05301084 uint8_t algoInfo, std::array<uint8_t, maxHashSize>& adminPwdHash)
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001085{
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001086 // We should not support this command after System Booted - After Exit Boot
1087 // service called
Arun Lal K M382dc972022-01-20 22:18:23 +00001088 if (getPostCompleted())
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{
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001131 nlohmann::json data = nullptr;
1132
Arun Lal K M1d0bac92022-02-11 00:23:13 +00001133 // We should not support this command after System Booted - After Exit Boot
1134 // service called
Arun Lal K M3a1be322022-02-08 21:37:30 +00001135 if (getPostCompleted())
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001136 {
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001137 return ipmi::response(ipmiCCNotSupportedInCurrentState);
1138 }
Arun Lal K M3a1be322022-02-08 21:37:30 +00001139
1140 std::string HashFilePath = "/var/lib/bios-settings-manager/seedData";
1141
1142 std::ifstream devIdFile(HashFilePath);
1143 if (!devIdFile.is_open())
1144 {
1145 return ipmi::responseResponseError();
1146 }
1147
1148 try
1149 {
1150 data = nlohmann::json::parse(devIdFile, nullptr, false);
1151 }
1152 catch (const nlohmann::json::parse_error& e)
1153 {
1154 return ipmi::responseResponseError();
1155 }
1156
1157 if (data.is_discarded())
1158 {
1159 return ipmi::responseResponseError();
1160 }
1161
1162 std::array<uint8_t, maxHashSize> newAdminHash;
1163 std::array<uint8_t, maxSeedSize> seed;
1164
1165 uint8_t flag = 0;
1166 uint8_t adminPwdChangedFlag = 0;
1167 if (!data.is_discarded())
1168 {
1169
1170 adminPwdChangedFlag = data["IsAdminPwdChanged"];
1171 newAdminHash = data["AdminPwdHash"];
1172 seed = data["Seed"];
1173 }
1174
1175 auto status = getResetBIOSSettings(flag);
1176 if (status)
1177 {
1178 return ipmi::responseResponseError();
1179 }
Snehalatha Venkatesh6346e982022-03-09 06:49:18 +00001180 if (flag)
1181 {
1182 flag |= restoreDefaultValues;
1183 }
Arun Lal K M3a1be322022-02-08 21:37:30 +00001184 if (adminPwdChangedFlag)
1185 {
1186 flag |= adminPasswordChanged;
1187 }
1188
1189 std::copy(std::begin(newAdminHash), std::end(newAdminHash),
1190 std::begin(newAdminHash));
1191
1192 return ipmi::responseSuccess(seed, flag, newAdminHash);
Kuiying Wang6d6dc7a2020-04-02 10:15:19 +08001193}
1194
1195static void registerBIOSConfigFunctions(void)
1196{
1197 phosphor::logging::log<phosphor::logging::level::INFO>(
1198 "BIOSConfig module initialization");
1199 InitNVOOBdata();
1200
1201 registerHandler(prioOemBase, intel::netFnGeneral,
1202 intel::general::cmdSetBIOSCap, Privilege::Admin,
1203 ipmiOEMSetBIOSCap);
1204
1205 registerHandler(prioOemBase, intel::netFnGeneral,
1206 intel::general::cmdGetBIOSCap, Privilege::User,
1207 ipmiOEMGetBIOSCap);
1208 registerHandler(prioOemBase, intel::netFnGeneral,
1209 intel::general::cmdSetBIOSPwdHashInfo, Privilege::Admin,
1210 ipmiOEMSetBIOSHashInfo);
1211
1212 registerHandler(prioOemBase, intel::netFnGeneral,
1213 intel::general::cmdGetBIOSPwdHash, Privilege::User,
1214 ipmiOEMGetBIOSHash);
1215
1216 registerHandler(prioOemBase, intel::netFnGeneral,
1217 intel::general::cmdGetPayload, Privilege::User,
1218 ipmiOEMGetPayload);
1219 registerHandler(prioOemBase, intel::netFnGeneral,
1220 intel::general::cmdSetPayload, Privilege::Admin,
1221 ipmiOEMSetPayload);
1222
1223 return;
1224}
1225
1226} // namespace ipmi