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