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