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