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