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