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