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