xref: /openbmc/bmcweb/redfish-core/lib/systems.hpp (revision caa3ce3cd0c310185034ba25c0f8464909fa54cb)
1 /*
2 // Copyright (c) 2018 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 #pragma once
17 
18 #include "health.hpp"
19 #include "led.hpp"
20 #include "pcie.hpp"
21 #include "redfish_util.hpp"
22 
23 #include <boost/container/flat_map.hpp>
24 #include <node.hpp>
25 #include <utils/fw_utils.hpp>
26 #include <utils/json_utils.hpp>
27 
28 #include <variant>
29 
30 namespace redfish
31 {
32 
33 /**
34  * @brief Updates the Functional State of DIMMs
35  *
36  * @param[in] aResp Shared pointer for completing asynchronous calls
37  * @param[in] dimmState Dimm's Functional state, true/false
38  *
39  * @return None.
40  */
41 void updateDimmProperties(std::shared_ptr<AsyncResp> aResp,
42                           const std::variant<bool>& dimmState)
43 {
44     const bool* isDimmFunctional = std::get_if<bool>(&dimmState);
45     if (isDimmFunctional == nullptr)
46     {
47         messages::internalError(aResp->res);
48         return;
49     }
50     BMCWEB_LOG_DEBUG << "Dimm Functional: " << *isDimmFunctional;
51 
52     // Set it as Enabled if at least one DIMM is functional
53     // Update STATE only if previous State was DISABLED and current Dimm is
54     // ENABLED.
55     nlohmann::json& prevMemSummary =
56         aResp->res.jsonValue["MemorySummary"]["Status"]["State"];
57     if (prevMemSummary == "Disabled")
58     {
59         if (*isDimmFunctional == true)
60         {
61             aResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
62                 "Enabled";
63         }
64     }
65 }
66 
67 /*
68  * @brief Update "ProcessorSummary" "Count" based on Cpu PresenceState
69  *
70  * @param[in] aResp Shared pointer for completing asynchronous calls
71  * @param[in] cpuPresenceState CPU present or not
72  *
73  * @return None.
74  */
75 void modifyCpuPresenceState(std::shared_ptr<AsyncResp> aResp,
76                             const std::variant<bool>& cpuPresenceState)
77 {
78     const bool* isCpuPresent = std::get_if<bool>(&cpuPresenceState);
79 
80     if (isCpuPresent == nullptr)
81     {
82         messages::internalError(aResp->res);
83         return;
84     }
85     BMCWEB_LOG_DEBUG << "Cpu Present: " << *isCpuPresent;
86 
87     if (*isCpuPresent == true)
88     {
89         nlohmann::json& procCount =
90             aResp->res.jsonValue["ProcessorSummary"]["Count"];
91         auto procCountPtr =
92             procCount.get_ptr<nlohmann::json::number_integer_t*>();
93         if (procCountPtr != nullptr)
94         {
95             // shouldn't be possible to be nullptr
96             *procCountPtr += 1;
97         }
98     }
99 }
100 
101 /*
102  * @brief Update "ProcessorSummary" "Status" "State" based on
103  *        CPU Functional State
104  *
105  * @param[in] aResp Shared pointer for completing asynchronous calls
106  * @param[in] cpuFunctionalState is CPU functional true/false
107  *
108  * @return None.
109  */
110 void modifyCpuFunctionalState(std::shared_ptr<AsyncResp> aResp,
111                               const std::variant<bool>& cpuFunctionalState)
112 {
113     const bool* isCpuFunctional = std::get_if<bool>(&cpuFunctionalState);
114 
115     if (isCpuFunctional == nullptr)
116     {
117         messages::internalError(aResp->res);
118         return;
119     }
120     BMCWEB_LOG_DEBUG << "Cpu Functional: " << *isCpuFunctional;
121 
122     nlohmann::json& prevProcState =
123         aResp->res.jsonValue["ProcessorSummary"]["Status"]["State"];
124 
125     // Set it as Enabled if at least one CPU is functional
126     // Update STATE only if previous State was Non_Functional and current CPU is
127     // Functional.
128     if (prevProcState == "Disabled")
129     {
130         if (*isCpuFunctional == true)
131         {
132             aResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
133                 "Enabled";
134         }
135     }
136 }
137 
138 /*
139  * @brief Retrieves computer system properties over dbus
140  *
141  * @param[in] aResp Shared pointer for completing asynchronous calls
142  * @param[in] name  Computer system name from request
143  *
144  * @return None.
145  */
146 void getComputerSystem(std::shared_ptr<AsyncResp> aResp,
147                        std::shared_ptr<HealthPopulate> systemHealth)
148 {
149     BMCWEB_LOG_DEBUG << "Get available system components.";
150 
151     crow::connections::systemBus->async_method_call(
152         [aResp, systemHealth](
153             const boost::system::error_code ec,
154             const std::vector<std::pair<
155                 std::string,
156                 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
157                 subtree) {
158             if (ec)
159             {
160                 BMCWEB_LOG_DEBUG << "DBUS response error";
161                 messages::internalError(aResp->res);
162                 return;
163             }
164             // Iterate over all retrieved ObjectPaths.
165             for (const std::pair<std::string,
166                                  std::vector<std::pair<
167                                      std::string, std::vector<std::string>>>>&
168                      object : subtree)
169             {
170                 const std::string& path = object.first;
171                 BMCWEB_LOG_DEBUG << "Got path: " << path;
172                 const std::vector<
173                     std::pair<std::string, std::vector<std::string>>>&
174                     connectionNames = object.second;
175                 if (connectionNames.size() < 1)
176                 {
177                     continue;
178                 }
179 
180                 auto memoryHealth = std::make_shared<HealthPopulate>(
181                     aResp, aResp->res.jsonValue["MemorySummary"]["Status"]);
182 
183                 auto cpuHealth = std::make_shared<HealthPopulate>(
184                     aResp, aResp->res.jsonValue["ProcessorSummary"]["Status"]);
185 
186                 systemHealth->children.emplace_back(memoryHealth);
187                 systemHealth->children.emplace_back(cpuHealth);
188 
189                 // This is not system, so check if it's cpu, dimm, UUID or
190                 // BiosVer
191                 for (const auto& connection : connectionNames)
192                 {
193                     for (const auto& interfaceName : connection.second)
194                     {
195                         if (interfaceName ==
196                             "xyz.openbmc_project.Inventory.Item.Dimm")
197                         {
198                             BMCWEB_LOG_DEBUG
199                                 << "Found Dimm, now get its properties.";
200 
201                             crow::connections::systemBus->async_method_call(
202                                 [aResp, service{connection.first},
203                                  path(std::move(path))](
204                                     const boost::system::error_code ec,
205                                     const std::vector<
206                                         std::pair<std::string, VariantType>>&
207                                         properties) {
208                                     if (ec)
209                                     {
210                                         BMCWEB_LOG_ERROR
211                                             << "DBUS response error " << ec;
212                                         messages::internalError(aResp->res);
213                                         return;
214                                     }
215                                     BMCWEB_LOG_DEBUG << "Got "
216                                                      << properties.size()
217                                                      << " Dimm properties.";
218 
219                                     if (properties.size() > 0)
220                                     {
221                                         for (const std::pair<std::string,
222                                                              VariantType>&
223                                                  property : properties)
224                                         {
225                                             if (property.first !=
226                                                 "MemorySizeInKB")
227                                             {
228                                                 continue;
229                                             }
230                                             const uint32_t* value =
231                                                 std::get_if<uint32_t>(
232                                                     &property.second);
233                                             if (value == nullptr)
234                                             {
235                                                 BMCWEB_LOG_DEBUG
236                                                     << "Find incorrect type of "
237                                                        "MemorySize";
238                                                 continue;
239                                             }
240                                             nlohmann::json& totalMemory =
241                                                 aResp->res
242                                                     .jsonValue["MemorySummar"
243                                                                "y"]
244                                                               ["TotalSystemMe"
245                                                                "moryGiB"];
246                                             uint64_t* preValue =
247                                                 totalMemory
248                                                     .get_ptr<uint64_t*>();
249                                             if (preValue == nullptr)
250                                             {
251                                                 continue;
252                                             }
253                                             aResp->res
254                                                 .jsonValue["MemorySummary"]
255                                                           ["TotalSystemMemoryGi"
256                                                            "B"] =
257                                                 *value / (1024 * 1024) +
258                                                 *preValue;
259                                             aResp->res
260                                                 .jsonValue["MemorySummary"]
261                                                           ["Status"]["State"] =
262                                                 "Enabled";
263                                         }
264                                     }
265                                     else
266                                     {
267                                         auto getDimmProperties =
268                                             [aResp](
269                                                 const boost::system::error_code
270                                                     ec,
271                                                 const std::variant<bool>&
272                                                     dimmState) {
273                                                 if (ec)
274                                                 {
275                                                     BMCWEB_LOG_ERROR
276                                                         << "DBUS response "
277                                                            "error "
278                                                         << ec;
279                                                     return;
280                                                 }
281                                                 updateDimmProperties(aResp,
282                                                                      dimmState);
283                                             };
284                                         crow::connections::systemBus
285                                             ->async_method_call(
286                                                 std::move(getDimmProperties),
287                                                 service, path,
288                                                 "org.freedesktop.DBus."
289                                                 "Properties",
290                                                 "Get",
291                                                 "xyz.openbmc_project.State."
292                                                 "Decorator.OperationalStatus",
293                                                 "Functional");
294                                     }
295                                 },
296                                 connection.first, path,
297                                 "org.freedesktop.DBus.Properties", "GetAll",
298                                 "xyz.openbmc_project.Inventory.Item.Dimm");
299 
300                             memoryHealth->inventory.emplace_back(path);
301                         }
302                         else if (interfaceName ==
303                                  "xyz.openbmc_project.Inventory.Item.Cpu")
304                         {
305                             BMCWEB_LOG_DEBUG
306                                 << "Found Cpu, now get its properties.";
307 
308                             crow::connections::systemBus->async_method_call(
309                                 [aResp, service{connection.first},
310                                  path(std::move(path))](
311                                     const boost::system::error_code ec,
312                                     const std::vector<
313                                         std::pair<std::string, VariantType>>&
314                                         properties) {
315                                     if (ec)
316                                     {
317                                         BMCWEB_LOG_ERROR
318                                             << "DBUS response error " << ec;
319                                         messages::internalError(aResp->res);
320                                         return;
321                                     }
322                                     BMCWEB_LOG_DEBUG << "Got "
323                                                      << properties.size()
324                                                      << " Cpu properties.";
325 
326                                     if (properties.size() > 0)
327                                     {
328                                         for (const auto& property : properties)
329                                         {
330                                             if (property.first ==
331                                                 "ProcessorFamily")
332                                             {
333                                                 const std::string* value =
334                                                     std::get_if<std::string>(
335                                                         &property.second);
336                                                 if (value != nullptr)
337                                                 {
338                                                     nlohmann::json&
339                                                         procSummary =
340                                                             aResp->res.jsonValue
341                                                                 ["ProcessorSumm"
342                                                                  "ary"];
343                                                     nlohmann::json& procCount =
344                                                         procSummary["Count"];
345 
346                                                     auto procCountPtr =
347                                                         procCount.get_ptr<
348                                                             nlohmann::json::
349                                                                 number_integer_t*>();
350                                                     if (procCountPtr != nullptr)
351                                                     {
352                                                         // shouldn't be possible
353                                                         // to be nullptr
354                                                         *procCountPtr += 1;
355                                                     }
356                                                     procSummary["Status"]
357                                                                ["State"] =
358                                                                    "Enabled";
359                                                     procSummary["Model"] =
360                                                         *value;
361                                                 }
362                                             }
363                                         }
364                                     }
365                                     else
366                                     {
367                                         auto getCpuPresenceState =
368                                             [aResp](
369                                                 const boost::system::error_code
370                                                     ec,
371                                                 const std::variant<bool>&
372                                                     cpuPresenceCheck) {
373                                                 if (ec)
374                                                 {
375                                                     BMCWEB_LOG_ERROR
376                                                         << "DBUS response "
377                                                            "error "
378                                                         << ec;
379                                                     return;
380                                                 }
381                                                 modifyCpuPresenceState(
382                                                     aResp, cpuPresenceCheck);
383                                             };
384 
385                                         auto getCpuFunctionalState =
386                                             [aResp](
387                                                 const boost::system::error_code
388                                                     ec,
389                                                 const std::variant<bool>&
390                                                     cpuFunctionalCheck) {
391                                                 if (ec)
392                                                 {
393                                                     BMCWEB_LOG_ERROR
394                                                         << "DBUS response "
395                                                            "error "
396                                                         << ec;
397                                                     return;
398                                                 }
399                                                 modifyCpuFunctionalState(
400                                                     aResp, cpuFunctionalCheck);
401                                             };
402                                         // Get the Presence of CPU
403                                         crow::connections::systemBus
404                                             ->async_method_call(
405                                                 std::move(getCpuPresenceState),
406                                                 service, path,
407                                                 "org.freedesktop.DBus."
408                                                 "Properties",
409                                                 "Get",
410                                                 "xyz.openbmc_project.Inventory."
411                                                 "Item",
412                                                 "Present");
413 
414                                         // Get the Functional State
415                                         crow::connections::systemBus
416                                             ->async_method_call(
417                                                 std::move(
418                                                     getCpuFunctionalState),
419                                                 service, path,
420                                                 "org.freedesktop.DBus."
421                                                 "Properties",
422                                                 "Get",
423                                                 "xyz.openbmc_project.State."
424                                                 "Decorator."
425                                                 "OperationalStatus",
426                                                 "Functional");
427 
428                                         // Get the MODEL from
429                                         // xyz.openbmc_project.Inventory.Decorator.Asset
430                                         // support it later as Model  is Empty
431                                         // currently.
432                                     }
433                                 },
434                                 connection.first, path,
435                                 "org.freedesktop.DBus.Properties", "GetAll",
436                                 "xyz.openbmc_project.Inventory.Item.Cpu");
437 
438                             cpuHealth->inventory.emplace_back(path);
439                         }
440                         else if (interfaceName ==
441                                  "xyz.openbmc_project.Common.UUID")
442                         {
443                             BMCWEB_LOG_DEBUG
444                                 << "Found UUID, now get its properties.";
445                             crow::connections::systemBus->async_method_call(
446                                 [aResp](
447                                     const boost::system::error_code ec,
448                                     const std::vector<
449                                         std::pair<std::string, VariantType>>&
450                                         properties) {
451                                     if (ec)
452                                     {
453                                         BMCWEB_LOG_DEBUG
454                                             << "DBUS response error " << ec;
455                                         messages::internalError(aResp->res);
456                                         return;
457                                     }
458                                     BMCWEB_LOG_DEBUG << "Got "
459                                                      << properties.size()
460                                                      << " UUID properties.";
461                                     for (const std::pair<std::string,
462                                                          VariantType>&
463                                              property : properties)
464                                     {
465                                         if (property.first == "UUID")
466                                         {
467                                             const std::string* value =
468                                                 std::get_if<std::string>(
469                                                     &property.second);
470 
471                                             if (value != nullptr)
472                                             {
473                                                 std::string valueStr = *value;
474                                                 if (valueStr.size() == 32)
475                                                 {
476                                                     valueStr.insert(8, 1, '-');
477                                                     valueStr.insert(13, 1, '-');
478                                                     valueStr.insert(18, 1, '-');
479                                                     valueStr.insert(23, 1, '-');
480                                                 }
481                                                 BMCWEB_LOG_DEBUG << "UUID = "
482                                                                  << valueStr;
483                                                 aResp->res.jsonValue["UUID"] =
484                                                     valueStr;
485                                             }
486                                         }
487                                     }
488                                 },
489                                 connection.first, path,
490                                 "org.freedesktop.DBus.Properties", "GetAll",
491                                 "xyz.openbmc_project.Common.UUID");
492                         }
493                         else if (interfaceName ==
494                                  "xyz.openbmc_project.Inventory.Item.System")
495                         {
496                             crow::connections::systemBus->async_method_call(
497                                 [aResp](
498                                     const boost::system::error_code ec,
499                                     const std::vector<
500                                         std::pair<std::string, VariantType>>&
501                                         propertiesList) {
502                                     if (ec)
503                                     {
504                                         // doesn't have to include this
505                                         // interface
506                                         return;
507                                     }
508                                     BMCWEB_LOG_DEBUG
509                                         << "Got " << propertiesList.size()
510                                         << " properties for system";
511                                     for (const std::pair<std::string,
512                                                          VariantType>&
513                                              property : propertiesList)
514                                     {
515                                         const std::string& propertyName =
516                                             property.first;
517                                         if ((propertyName == "PartNumber") ||
518                                             (propertyName == "SerialNumber") ||
519                                             (propertyName == "Manufacturer") ||
520                                             (propertyName == "Model"))
521                                         {
522                                             const std::string* value =
523                                                 std::get_if<std::string>(
524                                                     &property.second);
525                                             if (value != nullptr)
526                                             {
527                                                 aResp->res
528                                                     .jsonValue[propertyName] =
529                                                     *value;
530                                             }
531                                         }
532                                     }
533 
534                                     // Grab the bios version
535                                     fw_util::getActiveFwVersion(
536                                         aResp, fw_util::biosPurpose,
537                                         "BiosVersion");
538                                 },
539                                 connection.first, path,
540                                 "org.freedesktop.DBus.Properties", "GetAll",
541                                 "xyz.openbmc_project.Inventory.Decorator."
542                                 "Asset");
543 
544                             crow::connections::systemBus->async_method_call(
545                                 [aResp](
546                                     const boost::system::error_code ec,
547                                     const std::variant<std::string>& property) {
548                                     if (ec)
549                                     {
550                                         // doesn't have to include this
551                                         // interface
552                                         return;
553                                     }
554 
555                                     const std::string* value =
556                                         std::get_if<std::string>(&property);
557                                     if (value != nullptr)
558                                     {
559                                         aResp->res.jsonValue["AssetTag"] =
560                                             *value;
561                                     }
562                                 },
563                                 connection.first, path,
564                                 "org.freedesktop.DBus.Properties", "Get",
565                                 "xyz.openbmc_project.Inventory.Decorator."
566                                 "AssetTag",
567                                 "AssetTag");
568                         }
569                     }
570                 }
571             }
572         },
573         "xyz.openbmc_project.ObjectMapper",
574         "/xyz/openbmc_project/object_mapper",
575         "xyz.openbmc_project.ObjectMapper", "GetSubTree",
576         "/xyz/openbmc_project/inventory", int32_t(0),
577         std::array<const char*, 5>{
578             "xyz.openbmc_project.Inventory.Decorator.Asset",
579             "xyz.openbmc_project.Inventory.Item.Cpu",
580             "xyz.openbmc_project.Inventory.Item.Dimm",
581             "xyz.openbmc_project.Inventory.Item.System",
582             "xyz.openbmc_project.Common.UUID",
583         });
584 }
585 
586 /**
587  * @brief Retrieves host state properties over dbus
588  *
589  * @param[in] aResp     Shared pointer for completing asynchronous calls.
590  *
591  * @return None.
592  */
593 void getHostState(std::shared_ptr<AsyncResp> aResp)
594 {
595     BMCWEB_LOG_DEBUG << "Get host information.";
596     crow::connections::systemBus->async_method_call(
597         [aResp](const boost::system::error_code ec,
598                 const std::variant<std::string>& hostState) {
599             if (ec)
600             {
601                 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
602                 messages::internalError(aResp->res);
603                 return;
604             }
605 
606             const std::string* s = std::get_if<std::string>(&hostState);
607             BMCWEB_LOG_DEBUG << "Host state: " << *s;
608             if (s != nullptr)
609             {
610                 // Verify Host State
611                 if (*s == "xyz.openbmc_project.State.Host.HostState.Running")
612                 {
613                     aResp->res.jsonValue["PowerState"] = "On";
614                     aResp->res.jsonValue["Status"]["State"] = "Enabled";
615                 }
616                 else if (*s == "xyz.openbmc_project.State.Host.HostState."
617                                "Quiesced")
618                 {
619                     aResp->res.jsonValue["PowerState"] = "On";
620                     aResp->res.jsonValue["Status"]["State"] = "Quiesced";
621                 }
622                 else if (*s == "xyz.openbmc_project.State.Host.HostState."
623                                "DiagnosticMode")
624                 {
625                     aResp->res.jsonValue["PowerState"] = "On";
626                     aResp->res.jsonValue["Status"]["State"] = "InTest";
627                 }
628                 else
629                 {
630                     aResp->res.jsonValue["PowerState"] = "Off";
631                     aResp->res.jsonValue["Status"]["State"] = "Disabled";
632                 }
633             }
634         },
635         "xyz.openbmc_project.State.Host", "/xyz/openbmc_project/state/host0",
636         "org.freedesktop.DBus.Properties", "Get",
637         "xyz.openbmc_project.State.Host", "CurrentHostState");
638 }
639 
640 /**
641  * @brief Translates boot source DBUS property value to redfish.
642  *
643  * @param[in] dbusSource    The boot source in DBUS speak.
644  *
645  * @return Returns as a string, the boot source in Redfish terms. If translation
646  * cannot be done, returns an empty string.
647  */
648 static std::string dbusToRfBootSource(const std::string& dbusSource)
649 {
650     if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Default")
651     {
652         return "None";
653     }
654     else if (dbusSource ==
655              "xyz.openbmc_project.Control.Boot.Source.Sources.Disk")
656     {
657         return "Hdd";
658     }
659     else if (dbusSource ==
660              "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia")
661     {
662         return "Cd";
663     }
664     else if (dbusSource ==
665              "xyz.openbmc_project.Control.Boot.Source.Sources.Network")
666     {
667         return "Pxe";
668     }
669     else if (dbusSource ==
670              "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia")
671     {
672         return "Usb";
673     }
674     else
675     {
676         return "";
677     }
678 }
679 
680 /**
681  * @brief Translates boot mode DBUS property value to redfish.
682  *
683  * @param[in] dbusMode    The boot mode in DBUS speak.
684  *
685  * @return Returns as a string, the boot mode in Redfish terms. If translation
686  * cannot be done, returns an empty string.
687  */
688 static std::string dbusToRfBootMode(const std::string& dbusMode)
689 {
690     if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
691     {
692         return "None";
693     }
694     else if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe")
695     {
696         return "Diags";
697     }
698     else if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup")
699     {
700         return "BiosSetup";
701     }
702     else
703     {
704         return "";
705     }
706 }
707 
708 /**
709  * @brief Translates boot source from Redfish to the DBus boot paths.
710  *
711  * @param[in] rfSource    The boot source in Redfish.
712  * @param[out] bootSource The DBus source
713  * @param[out] bootMode   the DBus boot mode
714  *
715  * @return Integer error code.
716  */
717 static int assignBootParameters(std::shared_ptr<AsyncResp> aResp,
718                                 const std::string& rfSource,
719                                 std::string& bootSource, std::string& bootMode)
720 {
721     // The caller has initialized the bootSource and bootMode to:
722     // bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
723     // bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
724     // Only modify the bootSource/bootMode variable needed to achieve the
725     // desired boot action.
726 
727     if (rfSource == "None")
728     {
729         return 0;
730     }
731     else if (rfSource == "Pxe")
732     {
733         bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Network";
734     }
735     else if (rfSource == "Hdd")
736     {
737         bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Disk";
738     }
739     else if (rfSource == "Diags")
740     {
741         bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe";
742     }
743     else if (rfSource == "Cd")
744     {
745         bootSource =
746             "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia";
747     }
748     else if (rfSource == "BiosSetup")
749     {
750         bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup";
751     }
752     else if (rfSource == "Usb")
753     {
754         bootSource =
755             "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia";
756     }
757     else
758     {
759         BMCWEB_LOG_DEBUG << "Invalid property value for "
760                             "BootSourceOverrideTarget: "
761                          << bootSource;
762         messages::propertyValueNotInList(aResp->res, rfSource,
763                                          "BootSourceTargetOverride");
764         return -1;
765     }
766     return 0;
767 }
768 
769 /**
770  * @brief Retrieves boot mode over DBUS and fills out the response
771  *
772  * @param[in] aResp         Shared pointer for generating response message.
773  * @param[in] bootDbusObj   The dbus object to query for boot properties.
774  *
775  * @return None.
776  */
777 static void getBootMode(std::shared_ptr<AsyncResp> aResp,
778                         std::string bootDbusObj)
779 {
780     crow::connections::systemBus->async_method_call(
781         [aResp](const boost::system::error_code ec,
782                 const std::variant<std::string>& bootMode) {
783             if (ec)
784             {
785                 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
786                 messages::internalError(aResp->res);
787                 return;
788             }
789 
790             const std::string* bootModeStr =
791                 std::get_if<std::string>(&bootMode);
792 
793             if (!bootModeStr)
794             {
795                 messages::internalError(aResp->res);
796                 return;
797             }
798 
799             BMCWEB_LOG_DEBUG << "Boot mode: " << *bootModeStr;
800 
801             // TODO (Santosh): Do we need to support override mode?
802             aResp->res.jsonValue["Boot"]["BootSourceOverrideMode"] = "Legacy";
803             aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget@Redfish."
804                                          "AllowableValues"] = {
805                 "None", "Pxe", "Hdd", "Cd", "Diags", "BiosSetup", "Usb"};
806 
807             if (*bootModeStr !=
808                 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
809             {
810                 auto rfMode = dbusToRfBootMode(*bootModeStr);
811                 if (!rfMode.empty())
812                 {
813                     aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
814                         rfMode;
815                 }
816             }
817 
818             // If the BootSourceOverrideTarget is still "None" at the end,
819             // reset the BootSourceOverrideEnabled to indicate that
820             // overrides are disabled
821             if (aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] ==
822                 "None")
823             {
824                 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
825                     "Disabled";
826             }
827         },
828         "xyz.openbmc_project.Settings", bootDbusObj,
829         "org.freedesktop.DBus.Properties", "Get",
830         "xyz.openbmc_project.Control.Boot.Mode", "BootMode");
831 }
832 
833 /**
834  * @brief Retrieves boot source over DBUS
835  *
836  * @param[in] aResp         Shared pointer for generating response message.
837  * @param[in] oneTimeEnable Boolean to indicate boot properties are one-time.
838  *
839  * @return None.
840  */
841 static void getBootSource(std::shared_ptr<AsyncResp> aResp, bool oneTimeEnabled)
842 {
843     std::string bootDbusObj =
844         oneTimeEnabled ? "/xyz/openbmc_project/control/host0/boot/one_time"
845                        : "/xyz/openbmc_project/control/host0/boot";
846 
847     BMCWEB_LOG_DEBUG << "Is one time: " << oneTimeEnabled;
848     aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
849         (oneTimeEnabled) ? "Once" : "Continuous";
850 
851     crow::connections::systemBus->async_method_call(
852         [aResp, bootDbusObj](const boost::system::error_code ec,
853                              const std::variant<std::string>& bootSource) {
854             if (ec)
855             {
856                 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
857                 messages::internalError(aResp->res);
858                 return;
859             }
860 
861             const std::string* bootSourceStr =
862                 std::get_if<std::string>(&bootSource);
863 
864             if (!bootSourceStr)
865             {
866                 messages::internalError(aResp->res);
867                 return;
868             }
869             BMCWEB_LOG_DEBUG << "Boot source: " << *bootSourceStr;
870 
871             auto rfSource = dbusToRfBootSource(*bootSourceStr);
872             if (!rfSource.empty())
873             {
874                 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
875                     rfSource;
876             }
877         },
878         "xyz.openbmc_project.Settings", bootDbusObj,
879         "org.freedesktop.DBus.Properties", "Get",
880         "xyz.openbmc_project.Control.Boot.Source", "BootSource");
881     getBootMode(std::move(aResp), std::move(bootDbusObj));
882 }
883 
884 /**
885  * @brief Retrieves "One time" enabled setting over DBUS and calls function to
886  * get boot source and boot mode.
887  *
888  * @param[in] aResp     Shared pointer for generating response message.
889  *
890  * @return None.
891  */
892 static void getBootProperties(std::shared_ptr<AsyncResp> aResp)
893 {
894     BMCWEB_LOG_DEBUG << "Get boot information.";
895 
896     crow::connections::systemBus->async_method_call(
897         [aResp](const boost::system::error_code ec,
898                 const std::variant<bool>& oneTime) {
899             if (ec)
900             {
901                 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
902                 // not an error, don't have to have the interface
903                 return;
904             }
905 
906             const bool* oneTimePtr = std::get_if<bool>(&oneTime);
907 
908             if (!oneTimePtr)
909             {
910                 messages::internalError(aResp->res);
911                 return;
912             }
913             getBootSource(aResp, *oneTimePtr);
914         },
915         "xyz.openbmc_project.Settings",
916         "/xyz/openbmc_project/control/host0/boot/one_time",
917         "org.freedesktop.DBus.Properties", "Get",
918         "xyz.openbmc_project.Object.Enable", "Enabled");
919 }
920 
921 /**
922  * @brief Retrieves the Last Reset Time
923  *
924  * "Reset" is an overloaded term in Redfish, "Reset" includes power on
925  * and power off. Even though this is the "system" Redfish object look at the
926  * chassis D-Bus interface for the LastStateChangeTime since this has the
927  * last power operation time.
928  *
929  * @param[in] aResp     Shared pointer for generating response message.
930  *
931  * @return None.
932  */
933 void getLastResetTime(std::shared_ptr<AsyncResp> aResp)
934 {
935     BMCWEB_LOG_DEBUG << "Getting System Last Reset Time";
936 
937     crow::connections::systemBus->async_method_call(
938         [aResp](const boost::system::error_code ec,
939                 std::variant<uint64_t>& lastResetTime) {
940             if (ec)
941             {
942                 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
943                 return;
944             }
945 
946             const uint64_t* lastResetTimePtr =
947                 std::get_if<uint64_t>(&lastResetTime);
948 
949             if (!lastResetTimePtr)
950             {
951                 messages::internalError(aResp->res);
952                 return;
953             }
954             // LastStateChangeTime is epoch time, in milliseconds
955             // https://github.com/openbmc/phosphor-dbus-interfaces/blob/33e8e1dd64da53a66e888d33dc82001305cd0bf9/xyz/openbmc_project/State/Chassis.interface.yaml#L19
956             time_t lastResetTimeStamp =
957                 static_cast<time_t>(*lastResetTimePtr / 1000);
958 
959             // Convert to ISO 8601 standard
960             aResp->res.jsonValue["LastResetTime"] =
961                 crow::utility::getDateTime(lastResetTimeStamp);
962         },
963         "xyz.openbmc_project.State.Chassis",
964         "/xyz/openbmc_project/state/chassis0",
965         "org.freedesktop.DBus.Properties", "Get",
966         "xyz.openbmc_project.State.Chassis", "LastStateChangeTime");
967 }
968 
969 /**
970  * @brief Retrieves Automatic Retry properties. Known on D-Bus as AutoReboot.
971  *
972  * @param[in] aResp     Shared pointer for generating response message.
973  *
974  * @return None.
975  */
976 void getAutomaticRetry(std::shared_ptr<AsyncResp> aResp)
977 {
978     BMCWEB_LOG_DEBUG << "Get Automatic Retry policy";
979 
980     crow::connections::systemBus->async_method_call(
981         [aResp](const boost::system::error_code ec,
982                 std::variant<bool>& autoRebootEnabled) {
983             if (ec)
984             {
985                 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
986                 return;
987             }
988 
989             const bool* autoRebootEnabledPtr =
990                 std::get_if<bool>(&autoRebootEnabled);
991 
992             if (!autoRebootEnabledPtr)
993             {
994                 messages::internalError(aResp->res);
995                 return;
996             }
997 
998             BMCWEB_LOG_DEBUG << "Auto Reboot: " << *autoRebootEnabledPtr;
999             if (*autoRebootEnabledPtr == true)
1000             {
1001                 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1002                     "RetryAttempts";
1003                 // If AutomaticRetry (AutoReboot) is enabled see how many
1004                 // attempts are left
1005                 crow::connections::systemBus->async_method_call(
1006                     [aResp](const boost::system::error_code ec,
1007                             std::variant<uint32_t>& autoRebootAttemptsLeft) {
1008                         if (ec)
1009                         {
1010                             BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
1011                             return;
1012                         }
1013 
1014                         const uint32_t* autoRebootAttemptsLeftPtr =
1015                             std::get_if<uint32_t>(&autoRebootAttemptsLeft);
1016 
1017                         if (!autoRebootAttemptsLeftPtr)
1018                         {
1019                             messages::internalError(aResp->res);
1020                             return;
1021                         }
1022 
1023                         BMCWEB_LOG_DEBUG << "Auto Reboot Attempts Left: "
1024                                          << *autoRebootAttemptsLeftPtr;
1025 
1026                         aResp->res
1027                             .jsonValue["Boot"]
1028                                       ["RemainingAutomaticRetryAttempts"] =
1029                             *autoRebootAttemptsLeftPtr;
1030                     },
1031                     "xyz.openbmc_project.State.Host",
1032                     "/xyz/openbmc_project/state/host0",
1033                     "org.freedesktop.DBus.Properties", "Get",
1034                     "xyz.openbmc_project.Control.Boot.RebootAttempts",
1035                     "AttemptsLeft");
1036             }
1037             else
1038             {
1039                 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1040                     "Disabled";
1041             }
1042 
1043             // Not on D-Bus. Hardcoded here:
1044             // https://github.com/openbmc/phosphor-state-manager/blob/1dbbef42675e94fb1f78edb87d6b11380260535a/meson_options.txt#L71
1045             aResp->res.jsonValue["Boot"]["AutomaticRetryAttempts"] = 3;
1046 
1047             // "AutomaticRetryConfig" can be 3 values, Disabled, RetryAlways,
1048             // and RetryAttempts. OpenBMC only supports Disabled and
1049             // RetryAttempts.
1050             aResp->res.jsonValue["Boot"]["AutomaticRetryConfig@Redfish."
1051                                          "AllowableValues"] = {"Disabled",
1052                                                                "RetryAttempts"};
1053         },
1054         "xyz.openbmc_project.Settings",
1055         "/xyz/openbmc_project/control/host0/auto_reboot",
1056         "org.freedesktop.DBus.Properties", "Get",
1057         "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot");
1058 }
1059 
1060 /**
1061  * @brief Retrieves power restore policy over DBUS.
1062  *
1063  * @param[in] aResp     Shared pointer for generating response message.
1064  *
1065  * @return None.
1066  */
1067 void getPowerRestorePolicy(std::shared_ptr<AsyncResp> aResp)
1068 {
1069     BMCWEB_LOG_DEBUG << "Get power restore policy";
1070 
1071     crow::connections::systemBus->async_method_call(
1072         [aResp](const boost::system::error_code ec,
1073                 std::variant<std::string>& policy) {
1074             if (ec)
1075             {
1076                 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1077                 return;
1078             }
1079 
1080             const boost::container::flat_map<std::string, std::string>
1081                 policyMaps = {
1082                     {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy."
1083                      "AlwaysOn",
1084                      "AlwaysOn"},
1085                     {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy."
1086                      "AlwaysOff",
1087                      "AlwaysOff"},
1088                     {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy."
1089                      "LastState",
1090                      "LastState"}};
1091 
1092             const std::string* policyPtr = std::get_if<std::string>(&policy);
1093 
1094             if (!policyPtr)
1095             {
1096                 messages::internalError(aResp->res);
1097                 return;
1098             }
1099 
1100             auto policyMapsIt = policyMaps.find(*policyPtr);
1101             if (policyMapsIt == policyMaps.end())
1102             {
1103                 messages::internalError(aResp->res);
1104                 return;
1105             }
1106 
1107             aResp->res.jsonValue["PowerRestorePolicy"] = policyMapsIt->second;
1108         },
1109         "xyz.openbmc_project.Settings",
1110         "/xyz/openbmc_project/control/host0/power_restore_policy",
1111         "org.freedesktop.DBus.Properties", "Get",
1112         "xyz.openbmc_project.Control.Power.RestorePolicy",
1113         "PowerRestorePolicy");
1114 }
1115 
1116 /**
1117  * @brief Sets boot properties into DBUS object(s).
1118  *
1119  * @param[in] aResp           Shared pointer for generating response message.
1120  * @param[in] oneTimeEnabled  Is "one-time" setting already enabled.
1121  * @param[in] bootSource      The boot source to set.
1122  * @param[in] bootEnable      The source override "enable" to set.
1123  *
1124  * @return Integer error code.
1125  */
1126 static void setBootModeOrSource(std::shared_ptr<AsyncResp> aResp,
1127                                 bool oneTimeEnabled,
1128                                 std::optional<std::string> bootSource,
1129                                 std::optional<std::string> bootEnable)
1130 {
1131     std::string bootSourceStr =
1132         "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
1133     std::string bootModeStr =
1134         "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
1135     bool oneTimeSetting = oneTimeEnabled;
1136     bool useBootSource = true;
1137 
1138     // Validate incoming parameters
1139     if (bootEnable)
1140     {
1141         if (*bootEnable == "Once")
1142         {
1143             oneTimeSetting = true;
1144         }
1145         else if (*bootEnable == "Continuous")
1146         {
1147             oneTimeSetting = false;
1148         }
1149         else if (*bootEnable == "Disabled")
1150         {
1151             BMCWEB_LOG_DEBUG << "Boot source override will be disabled";
1152             oneTimeSetting = false;
1153             useBootSource = false;
1154         }
1155         else
1156         {
1157             BMCWEB_LOG_DEBUG << "Unsupported value for "
1158                                 "BootSourceOverrideEnabled: "
1159                              << *bootEnable;
1160             messages::propertyValueNotInList(aResp->res, *bootEnable,
1161                                              "BootSourceOverrideEnabled");
1162             return;
1163         }
1164     }
1165 
1166     if (bootSource && useBootSource)
1167     {
1168         // Source target specified
1169         BMCWEB_LOG_DEBUG << "Boot source: " << *bootSource;
1170         // Figure out which DBUS interface and property to use
1171         if (assignBootParameters(aResp, *bootSource, bootSourceStr,
1172                                  bootModeStr))
1173         {
1174             BMCWEB_LOG_DEBUG
1175                 << "Invalid property value for BootSourceOverrideTarget: "
1176                 << *bootSource;
1177             messages::propertyValueNotInList(aResp->res, *bootSource,
1178                                              "BootSourceTargetOverride");
1179             return;
1180         }
1181     }
1182 
1183     // Act on validated parameters
1184     BMCWEB_LOG_DEBUG << "DBUS boot source: " << bootSourceStr;
1185     BMCWEB_LOG_DEBUG << "DBUS boot mode: " << bootModeStr;
1186     const char* bootObj =
1187         oneTimeSetting ? "/xyz/openbmc_project/control/host0/boot/one_time"
1188                        : "/xyz/openbmc_project/control/host0/boot";
1189 
1190     crow::connections::systemBus->async_method_call(
1191         [aResp](const boost::system::error_code ec) {
1192             if (ec)
1193             {
1194                 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1195                 messages::internalError(aResp->res);
1196                 return;
1197             }
1198             BMCWEB_LOG_DEBUG << "Boot source update done.";
1199         },
1200         "xyz.openbmc_project.Settings", bootObj,
1201         "org.freedesktop.DBus.Properties", "Set",
1202         "xyz.openbmc_project.Control.Boot.Source", "BootSource",
1203         std::variant<std::string>(bootSourceStr));
1204 
1205     crow::connections::systemBus->async_method_call(
1206         [aResp](const boost::system::error_code ec) {
1207             if (ec)
1208             {
1209                 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1210                 messages::internalError(aResp->res);
1211                 return;
1212             }
1213             BMCWEB_LOG_DEBUG << "Boot mode update done.";
1214         },
1215         "xyz.openbmc_project.Settings", bootObj,
1216         "org.freedesktop.DBus.Properties", "Set",
1217         "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
1218         std::variant<std::string>(bootModeStr));
1219 
1220     crow::connections::systemBus->async_method_call(
1221         [aResp{std::move(aResp)}](const boost::system::error_code ec) {
1222             if (ec)
1223             {
1224                 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1225                 messages::internalError(aResp->res);
1226                 return;
1227             }
1228             BMCWEB_LOG_DEBUG << "Boot enable update done.";
1229         },
1230         "xyz.openbmc_project.Settings",
1231         "/xyz/openbmc_project/control/host0/boot/one_time",
1232         "org.freedesktop.DBus.Properties", "Set",
1233         "xyz.openbmc_project.Object.Enable", "Enabled",
1234         std::variant<bool>(oneTimeSetting));
1235 }
1236 
1237 /**
1238  * @brief Retrieves "One time" enabled setting over DBUS and calls function to
1239  * set boot source/boot mode properties.
1240  *
1241  * @param[in] aResp      Shared pointer for generating response message.
1242  * @param[in] bootSource The boot source from incoming RF request.
1243  * @param[in] bootEnable The boot override enable from incoming RF request.
1244  *
1245  * @return Integer error code.
1246  */
1247 static void setBootSourceProperties(std::shared_ptr<AsyncResp> aResp,
1248                                     std::optional<std::string> bootSource,
1249                                     std::optional<std::string> bootEnable)
1250 {
1251     BMCWEB_LOG_DEBUG << "Set boot information.";
1252 
1253     crow::connections::systemBus->async_method_call(
1254         [aResp, bootSource{std::move(bootSource)},
1255          bootEnable{std::move(bootEnable)}](const boost::system::error_code ec,
1256                                             const std::variant<bool>& oneTime) {
1257             if (ec)
1258             {
1259                 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1260                 messages::internalError(aResp->res);
1261                 return;
1262             }
1263 
1264             const bool* oneTimePtr = std::get_if<bool>(&oneTime);
1265 
1266             if (!oneTimePtr)
1267             {
1268                 messages::internalError(aResp->res);
1269                 return;
1270             }
1271 
1272             BMCWEB_LOG_DEBUG << "Got one time: " << *oneTimePtr;
1273 
1274             setBootModeOrSource(aResp, *oneTimePtr, std::move(bootSource),
1275                                 std::move(bootEnable));
1276         },
1277         "xyz.openbmc_project.Settings",
1278         "/xyz/openbmc_project/control/host0/boot/one_time",
1279         "org.freedesktop.DBus.Properties", "Get",
1280         "xyz.openbmc_project.Object.Enable", "Enabled");
1281 }
1282 
1283 /**
1284  * @brief Sets automaticRetry (Auto Reboot)
1285  *
1286  * @param[in] aResp   Shared pointer for generating response message.
1287  * @param[in] automaticRetryConfig  "AutomaticRetryConfig" from request.
1288  *
1289  * @return None.
1290  */
1291 static void setAutomaticRetry(std::shared_ptr<AsyncResp> aResp,
1292                               const std::string&& automaticRetryConfig)
1293 {
1294     BMCWEB_LOG_DEBUG << "Set Automatic Retry.";
1295 
1296     // OpenBMC only supports "Disabled" and "RetryAttempts".
1297     bool autoRebootEnabled;
1298 
1299     if (automaticRetryConfig == "Disabled")
1300     {
1301         autoRebootEnabled = false;
1302     }
1303     else if (automaticRetryConfig == "RetryAttempts")
1304     {
1305         autoRebootEnabled = true;
1306     }
1307     else
1308     {
1309         BMCWEB_LOG_DEBUG << "Invalid property value for "
1310                             "AutomaticRetryConfig: "
1311                          << automaticRetryConfig;
1312         messages::propertyValueNotInList(aResp->res, automaticRetryConfig,
1313                                          "AutomaticRetryConfig");
1314         return;
1315     }
1316 
1317     crow::connections::systemBus->async_method_call(
1318         [aResp](const boost::system::error_code ec) {
1319             if (ec)
1320             {
1321                 messages::internalError(aResp->res);
1322                 return;
1323             }
1324         },
1325         "xyz.openbmc_project.Settings",
1326         "/xyz/openbmc_project/control/host0/auto_reboot",
1327         "org.freedesktop.DBus.Properties", "Set",
1328         "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
1329         std::variant<bool>(autoRebootEnabled));
1330 }
1331 
1332 /**
1333  * @brief Sets power restore policy properties.
1334  *
1335  * @param[in] aResp   Shared pointer for generating response message.
1336  * @param[in] policy  power restore policy properties from request.
1337  *
1338  * @return None.
1339  */
1340 static void setPowerRestorePolicy(std::shared_ptr<AsyncResp> aResp,
1341                                   std::optional<std::string> policy)
1342 {
1343     BMCWEB_LOG_DEBUG << "Set power restore policy.";
1344 
1345     const boost::container::flat_map<std::string, std::string> policyMaps = {
1346         {"AlwaysOn", "xyz.openbmc_project.Control.Power.RestorePolicy.Policy."
1347                      "AlwaysOn"},
1348         {"AlwaysOff", "xyz.openbmc_project.Control.Power.RestorePolicy.Policy."
1349                       "AlwaysOff"},
1350         {"LastState", "xyz.openbmc_project.Control.Power.RestorePolicy.Policy."
1351                       "LastState"}};
1352 
1353     std::string powerRestorPolicy;
1354 
1355     auto policyMapsIt = policyMaps.find(*policy);
1356     if (policyMapsIt == policyMaps.end())
1357     {
1358         messages::internalError(aResp->res);
1359         return;
1360     }
1361 
1362     powerRestorPolicy = policyMapsIt->second;
1363 
1364     crow::connections::systemBus->async_method_call(
1365         [aResp](const boost::system::error_code ec) {
1366             if (ec)
1367             {
1368                 messages::internalError(aResp->res);
1369                 return;
1370             }
1371         },
1372         "xyz.openbmc_project.Settings",
1373         "/xyz/openbmc_project/control/host0/power_restore_policy",
1374         "org.freedesktop.DBus.Properties", "Set",
1375         "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
1376         std::variant<std::string>(powerRestorPolicy));
1377 }
1378 
1379 #ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
1380 /**
1381  * @brief Retrieves provisioning status
1382  *
1383  * @param[in] aResp     Shared pointer for completing asynchronous calls.
1384  *
1385  * @return None.
1386  */
1387 void getProvisioningStatus(std::shared_ptr<AsyncResp> aResp)
1388 {
1389     BMCWEB_LOG_DEBUG << "Get OEM information.";
1390     crow::connections::systemBus->async_method_call(
1391         [aResp](const boost::system::error_code ec,
1392                 const std::vector<std::pair<std::string, VariantType>>&
1393                     propertiesList) {
1394             nlohmann::json& oemPFR =
1395                 aResp->res.jsonValue["Oem"]["OpenBmc"]["FirmwareProvisioning"];
1396             if (ec)
1397             {
1398                 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1399                 // not an error, don't have to have the interface
1400                 oemPFR["ProvisioningStatus"] = "NotProvisioned";
1401                 return;
1402             }
1403 
1404             const bool* provState = nullptr;
1405             const bool* lockState = nullptr;
1406             for (const std::pair<std::string, VariantType>& property :
1407                  propertiesList)
1408             {
1409                 if (property.first == "UfmProvisioned")
1410                 {
1411                     provState = std::get_if<bool>(&property.second);
1412                 }
1413                 else if (property.first == "UfmLocked")
1414                 {
1415                     lockState = std::get_if<bool>(&property.second);
1416                 }
1417             }
1418 
1419             if ((provState == nullptr) || (lockState == nullptr))
1420             {
1421                 BMCWEB_LOG_DEBUG << "Unable to get PFR attributes.";
1422                 messages::internalError(aResp->res);
1423                 return;
1424             }
1425 
1426             if (*provState == true)
1427             {
1428                 if (*lockState == true)
1429                 {
1430                     oemPFR["ProvisioningStatus"] = "ProvisionedAndLocked";
1431                 }
1432                 else
1433                 {
1434                     oemPFR["ProvisioningStatus"] = "ProvisionedButNotLocked";
1435                 }
1436             }
1437             else
1438             {
1439                 oemPFR["ProvisioningStatus"] = "NotProvisioned";
1440             }
1441         },
1442         "xyz.openbmc_project.PFR.Manager", "/xyz/openbmc_project/pfr",
1443         "org.freedesktop.DBus.Properties", "GetAll",
1444         "xyz.openbmc_project.PFR.Attributes");
1445 }
1446 #endif
1447 
1448 /**
1449  * @brief Translates watchdog timeout action DBUS property value to redfish.
1450  *
1451  * @param[in] dbusAction    The watchdog timeout action in D-BUS.
1452  *
1453  * @return Returns as a string, the timeout action in Redfish terms. If
1454  * translation cannot be done, returns an empty string.
1455  */
1456 static std::string dbusToRfWatchdogAction(const std::string& dbusAction)
1457 {
1458     if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.None")
1459     {
1460         return "None";
1461     }
1462     else if (dbusAction ==
1463              "xyz.openbmc_project.State.Watchdog.Action.HardReset")
1464     {
1465         return "ResetSystem";
1466     }
1467     else if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerOff")
1468     {
1469         return "PowerDown";
1470     }
1471     else if (dbusAction ==
1472              "xyz.openbmc_project.State.Watchdog.Action.PowerCycle")
1473     {
1474         return "PowerCycle";
1475     }
1476 
1477     return "";
1478 }
1479 
1480 /**
1481  *@brief Translates timeout action from Redfish to DBUS property value.
1482  *
1483  *@param[in] rfAction The timeout action in Redfish.
1484  *
1485  *@return Returns as a string, the time_out action as expected by DBUS.
1486  *If translation cannot be done, returns an empty string.
1487  */
1488 
1489 static std::string rfToDbusWDTTimeOutAct(const std::string& rfAction)
1490 {
1491     if (rfAction == "None")
1492     {
1493         return "xyz.openbmc_project.State.Watchdog.Action.None";
1494     }
1495     else if (rfAction == "PowerCycle")
1496     {
1497         return "xyz.openbmc_project.State.Watchdog.Action.PowerCycle";
1498     }
1499     else if (rfAction == "PowerDown")
1500     {
1501         return "xyz.openbmc_project.State.Watchdog.Action.PowerOff";
1502     }
1503     else if (rfAction == "ResetSystem")
1504     {
1505         return "xyz.openbmc_project.State.Watchdog.Action.HardReset";
1506     }
1507 
1508     return "";
1509 }
1510 
1511 /**
1512  * @brief Retrieves host watchdog timer properties over DBUS
1513  *
1514  * @param[in] aResp     Shared pointer for completing asynchronous calls.
1515  *
1516  * @return None.
1517  */
1518 void getHostWatchdogTimer(std::shared_ptr<AsyncResp> aResp)
1519 {
1520     BMCWEB_LOG_DEBUG << "Get host watchodg";
1521     crow::connections::systemBus->async_method_call(
1522         [aResp](const boost::system::error_code ec,
1523                 PropertiesType& properties) {
1524             if (ec)
1525             {
1526                 // watchdog service is stopped
1527                 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1528                 return;
1529             }
1530 
1531             BMCWEB_LOG_DEBUG << "Got " << properties.size() << " wdt prop.";
1532 
1533             nlohmann::json& hostWatchdogTimer =
1534                 aResp->res.jsonValue["HostWatchdogTimer"];
1535 
1536             // watchdog service is running/enabled
1537             hostWatchdogTimer["Status"]["State"] = "Enabled";
1538 
1539             for (const auto& property : properties)
1540             {
1541                 BMCWEB_LOG_DEBUG << "prop=" << property.first;
1542                 if (property.first == "Enabled")
1543                 {
1544                     const bool* state = std::get_if<bool>(&property.second);
1545 
1546                     if (!state)
1547                     {
1548                         messages::internalError(aResp->res);
1549                         continue;
1550                     }
1551 
1552                     hostWatchdogTimer["FunctionEnabled"] = *state;
1553                 }
1554                 else if (property.first == "ExpireAction")
1555                 {
1556                     const std::string* s =
1557                         std::get_if<std::string>(&property.second);
1558                     if (!s)
1559                     {
1560                         messages::internalError(aResp->res);
1561                         continue;
1562                     }
1563 
1564                     std::string action = dbusToRfWatchdogAction(*s);
1565                     if (action.empty())
1566                     {
1567                         messages::internalError(aResp->res);
1568                         continue;
1569                     }
1570                     hostWatchdogTimer["TimeoutAction"] = action;
1571                 }
1572             }
1573         },
1574         "xyz.openbmc_project.Watchdog", "/xyz/openbmc_project/watchdog/host0",
1575         "org.freedesktop.DBus.Properties", "GetAll",
1576         "xyz.openbmc_project.State.Watchdog");
1577 }
1578 
1579 /**
1580  * @brief Sets Host WatchDog Timer properties.
1581  *
1582  * @param[in] aResp      Shared pointer for generating response message.
1583  * @param[in] wdtEnable  The WDTimer Enable value (true/false) from incoming
1584  *                       RF request.
1585  * @param[in] wdtTimeOutAction The WDT Timeout action, from incoming RF request.
1586  *
1587  * @return None.
1588  */
1589 static void setWDTProperties(std::shared_ptr<AsyncResp> aResp,
1590                              const std::optional<bool> wdtEnable,
1591                              const std::optional<std::string>& wdtTimeOutAction)
1592 {
1593     BMCWEB_LOG_DEBUG << "Set host watchdog";
1594 
1595     if (wdtTimeOutAction)
1596     {
1597         std::string wdtTimeOutActStr = rfToDbusWDTTimeOutAct(*wdtTimeOutAction);
1598         // check if TimeOut Action is Valid
1599         if (wdtTimeOutActStr.empty())
1600         {
1601             BMCWEB_LOG_DEBUG << "Unsupported value for TimeoutAction: "
1602                              << *wdtTimeOutAction;
1603             messages::propertyValueNotInList(aResp->res, *wdtTimeOutAction,
1604                                              "TimeoutAction");
1605             return;
1606         }
1607 
1608         crow::connections::systemBus->async_method_call(
1609             [aResp](const boost::system::error_code ec) {
1610                 if (ec)
1611                 {
1612                     BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1613                     messages::internalError(aResp->res);
1614                     return;
1615                 }
1616             },
1617             "xyz.openbmc_project.Watchdog",
1618             "/xyz/openbmc_project/watchdog/host0",
1619             "org.freedesktop.DBus.Properties", "Set",
1620             "xyz.openbmc_project.State.Watchdog", "ExpireAction",
1621             std::variant<std::string>(wdtTimeOutActStr));
1622     }
1623 
1624     if (wdtEnable)
1625     {
1626         crow::connections::systemBus->async_method_call(
1627             [aResp](const boost::system::error_code ec) {
1628                 if (ec)
1629                 {
1630                     BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1631                     messages::internalError(aResp->res);
1632                     return;
1633                 }
1634             },
1635             "xyz.openbmc_project.Watchdog",
1636             "/xyz/openbmc_project/watchdog/host0",
1637             "org.freedesktop.DBus.Properties", "Set",
1638             "xyz.openbmc_project.State.Watchdog", "Enabled",
1639             std::variant<bool>(*wdtEnable));
1640     }
1641 }
1642 
1643 /**
1644  * SystemsCollection derived class for delivering ComputerSystems Collection
1645  * Schema
1646  */
1647 class SystemsCollection : public Node
1648 {
1649   public:
1650     SystemsCollection(CrowApp& app) : Node(app, "/redfish/v1/Systems/")
1651     {
1652         entityPrivileges = {
1653             {boost::beast::http::verb::get, {{"Login"}}},
1654             {boost::beast::http::verb::head, {{"Login"}}},
1655             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
1656             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
1657             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
1658             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
1659     }
1660 
1661   private:
1662     void doGet(crow::Response& res, const crow::Request& req,
1663                const std::vector<std::string>& params) override
1664     {
1665         std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
1666         res.jsonValue["@odata.type"] =
1667             "#ComputerSystemCollection.ComputerSystemCollection";
1668         res.jsonValue["@odata.id"] = "/redfish/v1/Systems";
1669         res.jsonValue["Name"] = "Computer System Collection";
1670 
1671         crow::connections::systemBus->async_method_call(
1672             [asyncResp](const boost::system::error_code ec,
1673                         const std::variant<std::string>& hostName) {
1674                 nlohmann::json& iface_array =
1675                     asyncResp->res.jsonValue["Members"];
1676                 iface_array = nlohmann::json::array();
1677                 auto& count = asyncResp->res.jsonValue["Members@odata.count"];
1678                 count = 0;
1679                 if (ec)
1680                 {
1681                     iface_array.push_back(
1682                         {{"@odata.id", "/redfish/v1/Systems/system"}});
1683                     count = iface_array.size();
1684                     return;
1685                 }
1686                 BMCWEB_LOG_DEBUG << "Hypervisor is available";
1687                 iface_array.push_back(
1688                     {{"@odata.id", "/redfish/v1/Systems/system"}});
1689                 iface_array.push_back(
1690                     {{"@odata.id", "/redfish/v1/Systems/hypervisor"}});
1691                 count = iface_array.size();
1692             },
1693             "xyz.openbmc_project.Settings",
1694             "/xyz/openbmc_project/network/hypervisor",
1695             "org.freedesktop.DBus.Properties", "Get",
1696             "xyz.openbmc_project.Network.SystemConfiguration", "HostName");
1697     }
1698 };
1699 
1700 /**
1701  * SystemActionsReset class supports handle POST method for Reset action.
1702  * The class retrieves and sends data directly to D-Bus.
1703  */
1704 class SystemActionsReset : public Node
1705 {
1706   public:
1707     SystemActionsReset(CrowApp& app) :
1708         Node(app, "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset/")
1709     {
1710         entityPrivileges = {
1711             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
1712     }
1713 
1714   private:
1715     /**
1716      * Function handles POST method request.
1717      * Analyzes POST body message before sends Reset request data to D-Bus.
1718      */
1719     void doPost(crow::Response& res, const crow::Request& req,
1720                 const std::vector<std::string>& params) override
1721     {
1722         auto asyncResp = std::make_shared<AsyncResp>(res);
1723 
1724         std::string resetType;
1725         if (!json_util::readJson(req, res, "ResetType", resetType))
1726         {
1727             return;
1728         }
1729 
1730         // Get the command and host vs. chassis
1731         std::string command;
1732         bool hostCommand;
1733         if (resetType == "On")
1734         {
1735             command = "xyz.openbmc_project.State.Host.Transition.On";
1736             hostCommand = true;
1737         }
1738         else if (resetType == "ForceOff")
1739         {
1740             command = "xyz.openbmc_project.State.Chassis.Transition.Off";
1741             hostCommand = false;
1742         }
1743         else if (resetType == "ForceOn")
1744         {
1745             command = "xyz.openbmc_project.State.Host.Transition.On";
1746             hostCommand = true;
1747         }
1748         else if (resetType == "ForceRestart")
1749         {
1750             command =
1751                 "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot";
1752             hostCommand = true;
1753         }
1754         else if (resetType == "GracefulShutdown")
1755         {
1756             command = "xyz.openbmc_project.State.Host.Transition.Off";
1757             hostCommand = true;
1758         }
1759         else if (resetType == "GracefulRestart")
1760         {
1761             command =
1762                 "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot";
1763             hostCommand = true;
1764         }
1765         else if (resetType == "PowerCycle")
1766         {
1767             command = "xyz.openbmc_project.State.Host.Transition.Reboot";
1768             hostCommand = true;
1769         }
1770         else if (resetType == "Nmi")
1771         {
1772             doNMI(asyncResp);
1773             return;
1774         }
1775         else
1776         {
1777             messages::actionParameterUnknown(res, "Reset", resetType);
1778             return;
1779         }
1780 
1781         if (hostCommand)
1782         {
1783             crow::connections::systemBus->async_method_call(
1784                 [asyncResp, resetType](const boost::system::error_code ec) {
1785                     if (ec)
1786                     {
1787                         BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
1788                         if (ec.value() == boost::asio::error::invalid_argument)
1789                         {
1790                             messages::actionParameterNotSupported(
1791                                 asyncResp->res, resetType, "Reset");
1792                         }
1793                         else
1794                         {
1795                             messages::internalError(asyncResp->res);
1796                         }
1797                         return;
1798                     }
1799                     messages::success(asyncResp->res);
1800                 },
1801                 "xyz.openbmc_project.State.Host",
1802                 "/xyz/openbmc_project/state/host0",
1803                 "org.freedesktop.DBus.Properties", "Set",
1804                 "xyz.openbmc_project.State.Host", "RequestedHostTransition",
1805                 std::variant<std::string>{command});
1806         }
1807         else
1808         {
1809             crow::connections::systemBus->async_method_call(
1810                 [asyncResp, resetType](const boost::system::error_code ec) {
1811                     if (ec)
1812                     {
1813                         BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
1814                         if (ec.value() == boost::asio::error::invalid_argument)
1815                         {
1816                             messages::actionParameterNotSupported(
1817                                 asyncResp->res, resetType, "Reset");
1818                         }
1819                         else
1820                         {
1821                             messages::internalError(asyncResp->res);
1822                         }
1823                         return;
1824                     }
1825                     messages::success(asyncResp->res);
1826                 },
1827                 "xyz.openbmc_project.State.Chassis",
1828                 "/xyz/openbmc_project/state/chassis0",
1829                 "org.freedesktop.DBus.Properties", "Set",
1830                 "xyz.openbmc_project.State.Chassis", "RequestedPowerTransition",
1831                 std::variant<std::string>{command});
1832         }
1833     }
1834     /**
1835      * Function transceives data with dbus directly.
1836      */
1837     void doNMI(const std::shared_ptr<AsyncResp>& asyncResp)
1838     {
1839         constexpr char const* serviceName =
1840             "xyz.openbmc_project.Control.Host.NMI";
1841         constexpr char const* objectPath =
1842             "/xyz/openbmc_project/control/host0/nmi";
1843         constexpr char const* interfaceName =
1844             "xyz.openbmc_project.Control.Host.NMI";
1845         constexpr char const* method = "NMI";
1846 
1847         crow::connections::systemBus->async_method_call(
1848             [asyncResp](const boost::system::error_code ec) {
1849                 if (ec)
1850                 {
1851                     BMCWEB_LOG_ERROR << " Bad D-Bus request error: " << ec;
1852                     messages::internalError(asyncResp->res);
1853                     return;
1854                 }
1855                 messages::success(asyncResp->res);
1856             },
1857             serviceName, objectPath, interfaceName, method);
1858     }
1859 };
1860 
1861 /**
1862  * Systems derived class for delivering Computer Systems Schema.
1863  */
1864 class Systems : public Node
1865 {
1866   public:
1867     /*
1868      * Default Constructor
1869      */
1870     Systems(CrowApp& app) : Node(app, "/redfish/v1/Systems/system/")
1871     {
1872         entityPrivileges = {
1873             {boost::beast::http::verb::get, {{"Login"}}},
1874             {boost::beast::http::verb::head, {{"Login"}}},
1875             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
1876             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
1877             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
1878             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
1879     }
1880 
1881   private:
1882     /**
1883      * Functions triggers appropriate requests on DBus
1884      */
1885     void doGet(crow::Response& res, const crow::Request& req,
1886                const std::vector<std::string>& params) override
1887     {
1888         res.jsonValue["@odata.type"] = "#ComputerSystem.v1_12_0.ComputerSystem";
1889         res.jsonValue["Name"] = "system";
1890         res.jsonValue["Id"] = "system";
1891         res.jsonValue["SystemType"] = "Physical";
1892         res.jsonValue["Description"] = "Computer System";
1893         res.jsonValue["ProcessorSummary"]["Count"] = 0;
1894         res.jsonValue["ProcessorSummary"]["Status"]["State"] = "Disabled";
1895         res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] = uint64_t(0);
1896         res.jsonValue["MemorySummary"]["Status"]["State"] = "Disabled";
1897         res.jsonValue["@odata.id"] = "/redfish/v1/Systems/system";
1898 
1899         res.jsonValue["Processors"] = {
1900             {"@odata.id", "/redfish/v1/Systems/system/Processors"}};
1901         res.jsonValue["Memory"] = {
1902             {"@odata.id", "/redfish/v1/Systems/system/Memory"}};
1903         res.jsonValue["Storage"] = {
1904             {"@odata.id", "/redfish/v1/Systems/system/Storage"}};
1905 
1906         res.jsonValue["Actions"]["#ComputerSystem.Reset"] = {
1907             {"target",
1908              "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset"},
1909             {"ResetType@Redfish.AllowableValues",
1910              {"On", "ForceOff", "ForceOn", "ForceRestart", "GracefulRestart",
1911               "GracefulShutdown", "PowerCycle", "Nmi"}}};
1912 
1913         res.jsonValue["LogServices"] = {
1914             {"@odata.id", "/redfish/v1/Systems/system/LogServices"}};
1915 
1916         res.jsonValue["Bios"] = {
1917             {"@odata.id", "/redfish/v1/Systems/system/Bios"}};
1918 
1919         res.jsonValue["Links"]["ManagedBy"] = {
1920             {{"@odata.id", "/redfish/v1/Managers/bmc"}}};
1921 
1922         res.jsonValue["Status"] = {
1923             {"Health", "OK"},
1924             {"State", "Enabled"},
1925         };
1926         auto asyncResp = std::make_shared<AsyncResp>(res);
1927 
1928         constexpr const std::array<const char*, 4> inventoryForSystems = {
1929             "xyz.openbmc_project.Inventory.Item.Dimm",
1930             "xyz.openbmc_project.Inventory.Item.Cpu",
1931             "xyz.openbmc_project.Inventory.Item.Drive",
1932             "xyz.openbmc_project.Inventory.Item.StorageController"};
1933 
1934         auto health = std::make_shared<HealthPopulate>(asyncResp);
1935         crow::connections::systemBus->async_method_call(
1936             [health](const boost::system::error_code ec,
1937                      std::vector<std::string>& resp) {
1938                 if (ec)
1939                 {
1940                     // no inventory
1941                     return;
1942                 }
1943 
1944                 health->inventory = std::move(resp);
1945             },
1946             "xyz.openbmc_project.ObjectMapper",
1947             "/xyz/openbmc_project/object_mapper",
1948             "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", "/",
1949             int32_t(0), inventoryForSystems);
1950 
1951         health->populate();
1952 
1953         getMainChassisId(asyncResp, [](const std::string& chassisId,
1954                                        std::shared_ptr<AsyncResp> aRsp) {
1955             aRsp->res.jsonValue["Links"]["Chassis"] = {
1956                 {{"@odata.id", "/redfish/v1/Chassis/" + chassisId}}};
1957         });
1958 
1959         getIndicatorLedState(asyncResp);
1960         getComputerSystem(asyncResp, health);
1961         getHostState(asyncResp);
1962         getBootProperties(asyncResp);
1963         getPCIeDeviceList(asyncResp, "PCIeDevices");
1964         getHostWatchdogTimer(asyncResp);
1965         getPowerRestorePolicy(asyncResp);
1966         getAutomaticRetry(asyncResp);
1967         getLastResetTime(asyncResp);
1968 #ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
1969         getProvisioningStatus(asyncResp);
1970 #endif
1971     }
1972 
1973     void doPatch(crow::Response& res, const crow::Request& req,
1974                  const std::vector<std::string>& params) override
1975     {
1976         std::optional<std::string> indicatorLed;
1977         std::optional<nlohmann::json> bootProps;
1978         std::optional<nlohmann::json> wdtTimerProps;
1979         std::optional<std::string> powerRestorePolicy;
1980         auto asyncResp = std::make_shared<AsyncResp>(res);
1981 
1982         if (!json_util::readJson(req, res, "IndicatorLED", indicatorLed, "Boot",
1983                                  bootProps, "WatchdogTimer", wdtTimerProps,
1984                                  "PowerRestorePolicy", powerRestorePolicy))
1985         {
1986             return;
1987         }
1988 
1989         res.result(boost::beast::http::status::no_content);
1990 
1991         if (wdtTimerProps)
1992         {
1993             std::optional<bool> wdtEnable;
1994             std::optional<std::string> wdtTimeOutAction;
1995 
1996             if (!json_util::readJson(*wdtTimerProps, asyncResp->res,
1997                                      "FunctionEnabled", wdtEnable,
1998                                      "TimeoutAction", wdtTimeOutAction))
1999             {
2000                 return;
2001             }
2002             setWDTProperties(asyncResp, std::move(wdtEnable),
2003                              std::move(wdtTimeOutAction));
2004         }
2005 
2006         if (bootProps)
2007         {
2008             std::optional<std::string> bootSource;
2009             std::optional<std::string> bootEnable;
2010             std::optional<std::string> automaticRetryConfig;
2011 
2012             if (!json_util::readJson(
2013                     *bootProps, asyncResp->res, "BootSourceOverrideTarget",
2014                     bootSource, "BootSourceOverrideEnabled", bootEnable,
2015                     "AutomaticRetryConfig", automaticRetryConfig))
2016             {
2017                 return;
2018             }
2019             if (bootSource || bootEnable)
2020             {
2021                 setBootSourceProperties(asyncResp, std::move(bootSource),
2022                                         std::move(bootEnable));
2023             }
2024             if (automaticRetryConfig)
2025             {
2026                 setAutomaticRetry(asyncResp, std::move(*automaticRetryConfig));
2027             }
2028         }
2029 
2030         if (indicatorLed)
2031         {
2032             setIndicatorLedState(asyncResp, std::move(*indicatorLed));
2033         }
2034 
2035         if (powerRestorePolicy)
2036         {
2037             setPowerRestorePolicy(asyncResp, std::move(*powerRestorePolicy));
2038         }
2039     }
2040 };
2041 } // namespace redfish
2042