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