xref: /openbmc/bmcweb/features/redfish/lib/systems.hpp (revision 3a2d042432168ad1b555e4fc9f13c2ae0d35e0c7)
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 <app.hpp>
24 #include <boost/container/flat_map.hpp>
25 #include <utils/fw_utils.hpp>
26 #include <utils/json_utils.hpp>
27 
28 #include <variant>
29 
30 namespace redfish
31 {
32 
33 /**
34  * @brief Updates the Functional State of DIMMs
35  *
36  * @param[in] aResp Shared pointer for completing asynchronous calls
37  * @param[in] dimmState Dimm's Functional state, true/false
38  *
39  * @return None.
40  */
41 inline void
42     updateDimmProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
43                          const std::variant<bool>& dimmState)
44 {
45     const bool* isDimmFunctional = std::get_if<bool>(&dimmState);
46     if (isDimmFunctional == nullptr)
47     {
48         messages::internalError(aResp->res);
49         return;
50     }
51     BMCWEB_LOG_DEBUG << "Dimm Functional: " << *isDimmFunctional;
52 
53     // Set it as Enabled if at least one DIMM is functional
54     // Update STATE only if previous State was DISABLED and current Dimm is
55     // ENABLED.
56     nlohmann::json& prevMemSummary =
57         aResp->res.jsonValue["MemorySummary"]["Status"]["State"];
58     if (prevMemSummary == "Disabled")
59     {
60         if (*isDimmFunctional == true)
61         {
62             aResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
63                 "Enabled";
64         }
65     }
66 }
67 
68 /*
69  * @brief Update "ProcessorSummary" "Count" based on Cpu PresenceState
70  *
71  * @param[in] aResp Shared pointer for completing asynchronous calls
72  * @param[in] cpuPresenceState CPU present or not
73  *
74  * @return None.
75  */
76 inline void
77     modifyCpuPresenceState(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
78                            const std::variant<bool>& cpuPresenceState)
79 {
80     const bool* isCpuPresent = std::get_if<bool>(&cpuPresenceState);
81 
82     if (isCpuPresent == nullptr)
83     {
84         messages::internalError(aResp->res);
85         return;
86     }
87     BMCWEB_LOG_DEBUG << "Cpu Present: " << *isCpuPresent;
88 
89     if (*isCpuPresent == true)
90     {
91         nlohmann::json& procCount =
92             aResp->res.jsonValue["ProcessorSummary"]["Count"];
93         auto procCountPtr =
94             procCount.get_ptr<nlohmann::json::number_integer_t*>();
95         if (procCountPtr != nullptr)
96         {
97             // shouldn't be possible to be nullptr
98             *procCountPtr += 1;
99         }
100     }
101 }
102 
103 /*
104  * @brief Update "ProcessorSummary" "Status" "State" based on
105  *        CPU Functional State
106  *
107  * @param[in] aResp Shared pointer for completing asynchronous calls
108  * @param[in] cpuFunctionalState is CPU functional true/false
109  *
110  * @return None.
111  */
112 inline void
113     modifyCpuFunctionalState(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
114                              const std::variant<bool>& cpuFunctionalState)
115 {
116     const bool* isCpuFunctional = std::get_if<bool>(&cpuFunctionalState);
117 
118     if (isCpuFunctional == nullptr)
119     {
120         messages::internalError(aResp->res);
121         return;
122     }
123     BMCWEB_LOG_DEBUG << "Cpu Functional: " << *isCpuFunctional;
124 
125     nlohmann::json& prevProcState =
126         aResp->res.jsonValue["ProcessorSummary"]["Status"]["State"];
127 
128     // Set it as Enabled if at least one CPU is functional
129     // Update STATE only if previous State was Non_Functional and current CPU is
130     // Functional.
131     if (prevProcState == "Disabled")
132     {
133         if (*isCpuFunctional == true)
134         {
135             aResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
136                 "Enabled";
137         }
138     }
139 }
140 
141 /*
142  * @brief Retrieves computer system properties over dbus
143  *
144  * @param[in] aResp Shared pointer for completing asynchronous calls
145  * @param[in] systemHealth  Shared HealthPopulate pointer
146  *
147  * @return None.
148  */
149 inline void
150     getComputerSystem(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
151                       const std::shared_ptr<HealthPopulate>& systemHealth)
152 {
153     BMCWEB_LOG_DEBUG << "Get available system components.";
154 
155     crow::connections::systemBus->async_method_call(
156         [aResp, systemHealth](
157             const boost::system::error_code ec,
158             const std::vector<std::pair<
159                 std::string,
160                 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
161                 subtree) {
162             if (ec)
163             {
164                 BMCWEB_LOG_DEBUG << "DBUS response error";
165                 messages::internalError(aResp->res);
166                 return;
167             }
168             // Iterate over all retrieved ObjectPaths.
169             for (const std::pair<std::string,
170                                  std::vector<std::pair<
171                                      std::string, std::vector<std::string>>>>&
172                      object : subtree)
173             {
174                 const std::string& path = object.first;
175                 BMCWEB_LOG_DEBUG << "Got path: " << path;
176                 const std::vector<
177                     std::pair<std::string, std::vector<std::string>>>&
178                     connectionNames = object.second;
179                 if (connectionNames.size() < 1)
180                 {
181                     continue;
182                 }
183 
184                 auto memoryHealth = std::make_shared<HealthPopulate>(
185                     aResp, aResp->res.jsonValue["MemorySummary"]["Status"]);
186 
187                 auto cpuHealth = std::make_shared<HealthPopulate>(
188                     aResp, aResp->res.jsonValue["ProcessorSummary"]["Status"]);
189 
190                 systemHealth->children.emplace_back(memoryHealth);
191                 systemHealth->children.emplace_back(cpuHealth);
192 
193                 // This is not system, so check if it's cpu, dimm, UUID or
194                 // BiosVer
195                 for (const auto& connection : connectionNames)
196                 {
197                     for (const auto& interfaceName : connection.second)
198                     {
199                         if (interfaceName ==
200                             "xyz.openbmc_project.Inventory.Item.Dimm")
201                         {
202                             BMCWEB_LOG_DEBUG
203                                 << "Found Dimm, now get its properties.";
204 
205                             crow::connections::systemBus->async_method_call(
206                                 [aResp, service{connection.first},
207                                  path](const boost::system::error_code ec2,
208                                        const std::vector<
209                                            std::pair<std::string, VariantType>>&
210                                            properties) {
211                                     if (ec2)
212                                     {
213                                         BMCWEB_LOG_ERROR
214                                             << "DBUS response error " << ec2;
215                                         messages::internalError(aResp->res);
216                                         return;
217                                     }
218                                     BMCWEB_LOG_DEBUG << "Got "
219                                                      << properties.size()
220                                                      << " Dimm properties.";
221 
222                                     if (properties.size() > 0)
223                                     {
224                                         for (const std::pair<std::string,
225                                                              VariantType>&
226                                                  property : properties)
227                                         {
228                                             if (property.first !=
229                                                 "MemorySizeInKB")
230                                             {
231                                                 continue;
232                                             }
233                                             const uint32_t* value =
234                                                 std::get_if<uint32_t>(
235                                                     &property.second);
236                                             if (value == nullptr)
237                                             {
238                                                 BMCWEB_LOG_DEBUG
239                                                     << "Find incorrect type of "
240                                                        "MemorySize";
241                                                 continue;
242                                             }
243                                             nlohmann::json& totalMemory =
244                                                 aResp->res
245                                                     .jsonValue["MemorySummar"
246                                                                "y"]
247                                                               ["TotalSystemMe"
248                                                                "moryGiB"];
249                                             uint64_t* preValue =
250                                                 totalMemory
251                                                     .get_ptr<uint64_t*>();
252                                             if (preValue == nullptr)
253                                             {
254                                                 continue;
255                                             }
256                                             aResp->res
257                                                 .jsonValue["MemorySummary"]
258                                                           ["TotalSystemMemoryGi"
259                                                            "B"] =
260                                                 *value / (1024 * 1024) +
261                                                 *preValue;
262                                             aResp->res
263                                                 .jsonValue["MemorySummary"]
264                                                           ["Status"]["State"] =
265                                                 "Enabled";
266                                         }
267                                     }
268                                     else
269                                     {
270                                         auto getDimmProperties =
271                                             [aResp](
272                                                 const boost::system::error_code
273                                                     ec3,
274                                                 const std::variant<bool>&
275                                                     dimmState) {
276                                                 if (ec3)
277                                                 {
278                                                     BMCWEB_LOG_ERROR
279                                                         << "DBUS response "
280                                                            "error "
281                                                         << ec3;
282                                                     return;
283                                                 }
284                                                 updateDimmProperties(aResp,
285                                                                      dimmState);
286                                             };
287                                         crow::connections::systemBus
288                                             ->async_method_call(
289                                                 std::move(getDimmProperties),
290                                                 service, path,
291                                                 "org.freedesktop.DBus."
292                                                 "Properties",
293                                                 "Get",
294                                                 "xyz.openbmc_project.State."
295                                                 "Decorator.OperationalStatus",
296                                                 "Functional");
297                                     }
298                                 },
299                                 connection.first, path,
300                                 "org.freedesktop.DBus.Properties", "GetAll",
301                                 "xyz.openbmc_project.Inventory.Item.Dimm");
302 
303                             memoryHealth->inventory.emplace_back(path);
304                         }
305                         else if (interfaceName ==
306                                  "xyz.openbmc_project.Inventory.Item.Cpu")
307                         {
308                             BMCWEB_LOG_DEBUG
309                                 << "Found Cpu, now get its properties.";
310 
311                             crow::connections::systemBus->async_method_call(
312                                 [aResp, service{connection.first},
313                                  path](const boost::system::error_code ec2,
314                                        const std::vector<
315                                            std::pair<std::string, VariantType>>&
316                                            properties) {
317                                     if (ec2)
318                                     {
319                                         BMCWEB_LOG_ERROR
320                                             << "DBUS response error " << ec2;
321                                         messages::internalError(aResp->res);
322                                         return;
323                                     }
324                                     BMCWEB_LOG_DEBUG << "Got "
325                                                      << properties.size()
326                                                      << " Cpu properties.";
327 
328                                     if (properties.size() > 0)
329                                     {
330                                         const uint64_t* processorId = nullptr;
331                                         const std::string* procFamily = nullptr;
332                                         nlohmann::json& procSummary =
333                                             aResp->res.jsonValue["ProcessorSumm"
334                                                                  "ary"];
335                                         nlohmann::json& procCount =
336                                             procSummary["Count"];
337 
338                                         auto procCountPtr = procCount.get_ptr<
339                                             nlohmann::json::
340                                                 number_integer_t*>();
341                                         if (procCountPtr == nullptr)
342                                         {
343                                             messages::internalError(aResp->res);
344                                             return;
345                                         }
346                                         for (const auto& property : properties)
347                                         {
348 
349                                             if (property.first == "Id")
350                                             {
351                                                 processorId =
352                                                     std::get_if<uint64_t>(
353                                                         &property.second);
354                                                 if (nullptr != procFamily)
355                                                 {
356                                                     break;
357                                                 }
358                                                 continue;
359                                             }
360 
361                                             if (property.first == "Family")
362                                             {
363                                                 procFamily =
364                                                     std::get_if<std::string>(
365                                                         &property.second);
366                                                 if (nullptr != processorId)
367                                                 {
368                                                     break;
369                                                 }
370                                                 continue;
371                                             }
372                                         }
373 
374                                         if (procFamily != nullptr &&
375                                             processorId != nullptr)
376                                         {
377                                             if (procCountPtr != nullptr &&
378                                                 *processorId != 0)
379                                             {
380                                                 *procCountPtr += 1;
381                                                 procSummary["Status"]["State"] =
382                                                     "Enabled";
383 
384                                                 procSummary["Model"] =
385                                                     *procFamily;
386                                             }
387                                         }
388                                     }
389                                     else
390                                     {
391                                         auto getCpuPresenceState =
392                                             [aResp](
393                                                 const boost::system::error_code
394                                                     ec3,
395                                                 const std::variant<bool>&
396                                                     cpuPresenceCheck) {
397                                                 if (ec3)
398                                                 {
399                                                     BMCWEB_LOG_ERROR
400                                                         << "DBUS response "
401                                                            "error "
402                                                         << ec3;
403                                                     return;
404                                                 }
405                                                 modifyCpuPresenceState(
406                                                     aResp, cpuPresenceCheck);
407                                             };
408 
409                                         auto getCpuFunctionalState =
410                                             [aResp](
411                                                 const boost::system::error_code
412                                                     ec3,
413                                                 const std::variant<bool>&
414                                                     cpuFunctionalCheck) {
415                                                 if (ec3)
416                                                 {
417                                                     BMCWEB_LOG_ERROR
418                                                         << "DBUS response "
419                                                            "error "
420                                                         << ec3;
421                                                     return;
422                                                 }
423                                                 modifyCpuFunctionalState(
424                                                     aResp, cpuFunctionalCheck);
425                                             };
426                                         // Get the Presence of CPU
427                                         crow::connections::systemBus
428                                             ->async_method_call(
429                                                 std::move(getCpuPresenceState),
430                                                 service, path,
431                                                 "org.freedesktop.DBus."
432                                                 "Properties",
433                                                 "Get",
434                                                 "xyz.openbmc_project.Inventory."
435                                                 "Item",
436                                                 "Present");
437 
438                                         // Get the Functional State
439                                         crow::connections::systemBus
440                                             ->async_method_call(
441                                                 std::move(
442                                                     getCpuFunctionalState),
443                                                 service, path,
444                                                 "org.freedesktop.DBus."
445                                                 "Properties",
446                                                 "Get",
447                                                 "xyz.openbmc_project.State."
448                                                 "Decorator."
449                                                 "OperationalStatus",
450                                                 "Functional");
451 
452                                         // Get the MODEL from
453                                         // xyz.openbmc_project.Inventory.Decorator.Asset
454                                         // support it later as Model  is Empty
455                                         // currently.
456                                     }
457                                 },
458                                 connection.first, path,
459                                 "org.freedesktop.DBus.Properties", "GetAll",
460                                 "xyz.openbmc_project.Inventory.Item.Cpu");
461 
462                             cpuHealth->inventory.emplace_back(path);
463                         }
464                         else if (interfaceName ==
465                                  "xyz.openbmc_project.Common.UUID")
466                         {
467                             BMCWEB_LOG_DEBUG
468                                 << "Found UUID, now get its properties.";
469                             crow::connections::systemBus->async_method_call(
470                                 [aResp](
471                                     const boost::system::error_code ec3,
472                                     const std::vector<
473                                         std::pair<std::string, VariantType>>&
474                                         properties) {
475                                     if (ec3)
476                                     {
477                                         BMCWEB_LOG_DEBUG
478                                             << "DBUS response error " << ec3;
479                                         messages::internalError(aResp->res);
480                                         return;
481                                     }
482                                     BMCWEB_LOG_DEBUG << "Got "
483                                                      << properties.size()
484                                                      << " UUID properties.";
485                                     for (const std::pair<std::string,
486                                                          VariantType>&
487                                              property : properties)
488                                     {
489                                         if (property.first == "UUID")
490                                         {
491                                             const std::string* value =
492                                                 std::get_if<std::string>(
493                                                     &property.second);
494 
495                                             if (value != nullptr)
496                                             {
497                                                 std::string valueStr = *value;
498                                                 if (valueStr.size() == 32)
499                                                 {
500                                                     valueStr.insert(8, 1, '-');
501                                                     valueStr.insert(13, 1, '-');
502                                                     valueStr.insert(18, 1, '-');
503                                                     valueStr.insert(23, 1, '-');
504                                                 }
505                                                 BMCWEB_LOG_DEBUG << "UUID = "
506                                                                  << valueStr;
507                                                 aResp->res.jsonValue["UUID"] =
508                                                     valueStr;
509                                             }
510                                         }
511                                     }
512                                 },
513                                 connection.first, path,
514                                 "org.freedesktop.DBus.Properties", "GetAll",
515                                 "xyz.openbmc_project.Common.UUID");
516                         }
517                         else if (interfaceName ==
518                                  "xyz.openbmc_project.Inventory.Item.System")
519                         {
520                             crow::connections::systemBus->async_method_call(
521                                 [aResp](
522                                     const boost::system::error_code ec2,
523                                     const std::vector<
524                                         std::pair<std::string, VariantType>>&
525                                         propertiesList) {
526                                     if (ec2)
527                                     {
528                                         // doesn't have to include this
529                                         // interface
530                                         return;
531                                     }
532                                     BMCWEB_LOG_DEBUG
533                                         << "Got " << propertiesList.size()
534                                         << " properties for system";
535                                     for (const std::pair<std::string,
536                                                          VariantType>&
537                                              property : propertiesList)
538                                     {
539                                         const std::string& propertyName =
540                                             property.first;
541                                         if ((propertyName == "PartNumber") ||
542                                             (propertyName == "SerialNumber") ||
543                                             (propertyName == "Manufacturer") ||
544                                             (propertyName == "Model") ||
545                                             (propertyName == "SubModel"))
546                                         {
547                                             const std::string* value =
548                                                 std::get_if<std::string>(
549                                                     &property.second);
550                                             if (value != nullptr)
551                                             {
552                                                 aResp->res
553                                                     .jsonValue[propertyName] =
554                                                     *value;
555                                             }
556                                         }
557                                     }
558 
559                                     // Grab the bios version
560                                     fw_util::populateFirmwareInformation(
561                                         aResp, fw_util::biosPurpose,
562                                         "BiosVersion", false);
563                                 },
564                                 connection.first, path,
565                                 "org.freedesktop.DBus.Properties", "GetAll",
566                                 "xyz.openbmc_project.Inventory.Decorator."
567                                 "Asset");
568 
569                             crow::connections::systemBus->async_method_call(
570                                 [aResp](
571                                     const boost::system::error_code ec2,
572                                     const std::variant<std::string>& property) {
573                                     if (ec2)
574                                     {
575                                         // doesn't have to include this
576                                         // interface
577                                         return;
578                                     }
579 
580                                     const std::string* value =
581                                         std::get_if<std::string>(&property);
582                                     if (value != nullptr)
583                                     {
584                                         aResp->res.jsonValue["AssetTag"] =
585                                             *value;
586                                     }
587                                 },
588                                 connection.first, path,
589                                 "org.freedesktop.DBus.Properties", "Get",
590                                 "xyz.openbmc_project.Inventory.Decorator."
591                                 "AssetTag",
592                                 "AssetTag");
593                         }
594                     }
595                 }
596             }
597         },
598         "xyz.openbmc_project.ObjectMapper",
599         "/xyz/openbmc_project/object_mapper",
600         "xyz.openbmc_project.ObjectMapper", "GetSubTree",
601         "/xyz/openbmc_project/inventory", int32_t(0),
602         std::array<const char*, 5>{
603             "xyz.openbmc_project.Inventory.Decorator.Asset",
604             "xyz.openbmc_project.Inventory.Item.Cpu",
605             "xyz.openbmc_project.Inventory.Item.Dimm",
606             "xyz.openbmc_project.Inventory.Item.System",
607             "xyz.openbmc_project.Common.UUID",
608         });
609 }
610 
611 /**
612  * @brief Retrieves host state properties over dbus
613  *
614  * @param[in] aResp     Shared pointer for completing asynchronous calls.
615  *
616  * @return None.
617  */
618 inline void getHostState(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
619 {
620     BMCWEB_LOG_DEBUG << "Get host information.";
621     crow::connections::systemBus->async_method_call(
622         [aResp](const boost::system::error_code ec,
623                 const std::variant<std::string>& hostState) {
624             if (ec)
625             {
626                 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
627                 messages::internalError(aResp->res);
628                 return;
629             }
630 
631             const std::string* s = std::get_if<std::string>(&hostState);
632             BMCWEB_LOG_DEBUG << "Host state: " << *s;
633             if (s != nullptr)
634             {
635                 // Verify Host State
636                 if (*s == "xyz.openbmc_project.State.Host.HostState.Running")
637                 {
638                     aResp->res.jsonValue["PowerState"] = "On";
639                     aResp->res.jsonValue["Status"]["State"] = "Enabled";
640                 }
641                 else if (*s == "xyz.openbmc_project.State.Host.HostState."
642                                "Quiesced")
643                 {
644                     aResp->res.jsonValue["PowerState"] = "On";
645                     aResp->res.jsonValue["Status"]["State"] = "Quiesced";
646                 }
647                 else if (*s == "xyz.openbmc_project.State.Host.HostState."
648                                "DiagnosticMode")
649                 {
650                     aResp->res.jsonValue["PowerState"] = "On";
651                     aResp->res.jsonValue["Status"]["State"] = "InTest";
652                 }
653                 else if (*s == "xyz.openbmc_project.State.Host.HostState."
654                                "TransitioningToRunning")
655                 {
656                     aResp->res.jsonValue["PowerState"] = "PoweringOn";
657                     aResp->res.jsonValue["Status"]["State"] = "Starting";
658                 }
659                 else if (*s == "xyz.openbmc_project.State.Host.HostState."
660                                "TransitioningToOff")
661                 {
662                     aResp->res.jsonValue["PowerState"] = "PoweringOff";
663                     aResp->res.jsonValue["Status"]["State"] = "Disabled";
664                 }
665                 else
666                 {
667                     aResp->res.jsonValue["PowerState"] = "Off";
668                     aResp->res.jsonValue["Status"]["State"] = "Disabled";
669                 }
670             }
671         },
672         "xyz.openbmc_project.State.Host", "/xyz/openbmc_project/state/host0",
673         "org.freedesktop.DBus.Properties", "Get",
674         "xyz.openbmc_project.State.Host", "CurrentHostState");
675 }
676 
677 /**
678  * @brief Translates boot source DBUS property value to redfish.
679  *
680  * @param[in] dbusSource    The boot source in DBUS speak.
681  *
682  * @return Returns as a string, the boot source in Redfish terms. If translation
683  * cannot be done, returns an empty string.
684  */
685 inline std::string dbusToRfBootSource(const std::string& dbusSource)
686 {
687     if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Default")
688     {
689         return "None";
690     }
691     if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Disk")
692     {
693         return "Hdd";
694     }
695     if (dbusSource ==
696         "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia")
697     {
698         return "Cd";
699     }
700     if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Network")
701     {
702         return "Pxe";
703     }
704     if (dbusSource ==
705         "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia")
706     {
707         return "Usb";
708     }
709     return "";
710 }
711 
712 /**
713  * @brief Translates boot mode DBUS property value to redfish.
714  *
715  * @param[in] dbusMode    The boot mode in DBUS speak.
716  *
717  * @return Returns as a string, the boot mode in Redfish terms. If translation
718  * cannot be done, returns an empty string.
719  */
720 inline std::string dbusToRfBootMode(const std::string& dbusMode)
721 {
722     if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
723     {
724         return "None";
725     }
726     if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe")
727     {
728         return "Diags";
729     }
730     if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup")
731     {
732         return "BiosSetup";
733     }
734     return "";
735 }
736 
737 /**
738  * @brief Translates boot source from Redfish to the DBus boot paths.
739  *
740  * @param[in] rfSource    The boot source in Redfish.
741  * @param[out] bootSource The DBus source
742  * @param[out] bootMode   the DBus boot mode
743  *
744  * @return Integer error code.
745  */
746 inline int assignBootParameters(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
747                                 const std::string& rfSource,
748                                 std::string& bootSource, std::string& bootMode)
749 {
750     // The caller has initialized the bootSource and bootMode to:
751     // bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
752     // bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
753     // Only modify the bootSource/bootMode variable needed to achieve the
754     // desired boot action.
755 
756     if (rfSource == "None")
757     {
758         return 0;
759     }
760     if (rfSource == "Pxe")
761     {
762         bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Network";
763     }
764     else if (rfSource == "Hdd")
765     {
766         bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Disk";
767     }
768     else if (rfSource == "Diags")
769     {
770         bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe";
771     }
772     else if (rfSource == "Cd")
773     {
774         bootSource =
775             "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia";
776     }
777     else if (rfSource == "BiosSetup")
778     {
779         bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup";
780     }
781     else if (rfSource == "Usb")
782     {
783         bootSource =
784             "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia";
785     }
786     else
787     {
788         BMCWEB_LOG_DEBUG << "Invalid property value for "
789                             "BootSourceOverrideTarget: "
790                          << bootSource;
791         messages::propertyValueNotInList(aResp->res, rfSource,
792                                          "BootSourceTargetOverride");
793         return -1;
794     }
795     return 0;
796 }
797 
798 /**
799  * @brief Retrieves boot progress of the system
800  *
801  * @param[in] aResp  Shared pointer for generating response message.
802  *
803  * @return None.
804  */
805 inline void getBootProgress(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
806 {
807     crow::connections::systemBus->async_method_call(
808         [aResp](const boost::system::error_code ec,
809                 const std::variant<std::string>& bootProgress) {
810             if (ec)
811             {
812                 // BootProgress is an optional object so just do nothing if
813                 // not found
814                 return;
815             }
816 
817             const std::string* bootProgressStr =
818                 std::get_if<std::string>(&bootProgress);
819 
820             if (!bootProgressStr)
821             {
822                 // Interface implemented but property not found, return error
823                 // for that
824                 messages::internalError(aResp->res);
825                 return;
826             }
827 
828             BMCWEB_LOG_DEBUG << "Boot Progress: " << *bootProgressStr;
829 
830             // Now convert the D-Bus BootProgress to the appropriate Redfish
831             // enum
832             std::string rfBpLastState = "None";
833             if (*bootProgressStr == "xyz.openbmc_project.State.Boot.Progress."
834                                     "ProgressStages.Unspecified")
835             {
836                 rfBpLastState = "None";
837             }
838             else if (*bootProgressStr ==
839                      "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
840                      "PrimaryProcInit")
841             {
842                 rfBpLastState = "PrimaryProcessorInitializationStarted";
843             }
844             else if (*bootProgressStr ==
845                      "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
846                      "BusInit")
847             {
848                 rfBpLastState = "BusInitializationStarted";
849             }
850             else if (*bootProgressStr ==
851                      "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
852                      "MemoryInit")
853             {
854                 rfBpLastState = "MemoryInitializationStarted";
855             }
856             else if (*bootProgressStr ==
857                      "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
858                      "SecondaryProcInit")
859             {
860                 rfBpLastState = "SecondaryProcessorInitializationStarted";
861             }
862             else if (*bootProgressStr ==
863                      "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
864                      "PCIInit")
865             {
866                 rfBpLastState = "PCIResourceConfigStarted";
867             }
868             else if (*bootProgressStr ==
869                      "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
870                      "SystemInitComplete")
871             {
872                 rfBpLastState = "SystemHardwareInitializationComplete";
873             }
874             else if (*bootProgressStr ==
875                      "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
876                      "OSStart")
877             {
878                 rfBpLastState = "OSBootStarted";
879             }
880             else if (*bootProgressStr ==
881                      "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
882                      "OSRunning")
883             {
884                 rfBpLastState = "OSRunning";
885             }
886             else
887             {
888                 BMCWEB_LOG_DEBUG << "Unsupported D-Bus BootProgress "
889                                  << *bootProgressStr;
890                 // Just return the default
891             }
892 
893             aResp->res.jsonValue["BootProgress"]["LastState"] = rfBpLastState;
894         },
895         "xyz.openbmc_project.State.Host", "/xyz/openbmc_project/state/host0",
896         "org.freedesktop.DBus.Properties", "Get",
897         "xyz.openbmc_project.State.Boot.Progress", "BootProgress");
898 }
899 
900 /**
901  * @brief Retrieves boot mode over DBUS and fills out the response
902  *
903  * @param[in] aResp         Shared pointer for generating response message.
904  * @param[in] bootDbusObj   The dbus object to query for boot properties.
905  *
906  * @return None.
907  */
908 inline void getBootMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
909                         const std::string& bootDbusObj)
910 {
911     crow::connections::systemBus->async_method_call(
912         [aResp](const boost::system::error_code ec,
913                 const std::variant<std::string>& bootMode) {
914             if (ec)
915             {
916                 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
917                 messages::internalError(aResp->res);
918                 return;
919             }
920 
921             const std::string* bootModeStr =
922                 std::get_if<std::string>(&bootMode);
923 
924             if (!bootModeStr)
925             {
926                 messages::internalError(aResp->res);
927                 return;
928             }
929 
930             BMCWEB_LOG_DEBUG << "Boot mode: " << *bootModeStr;
931 
932             // TODO (Santosh): Do we need to support override mode?
933             aResp->res.jsonValue["Boot"]["BootSourceOverrideMode"] = "Legacy";
934             aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget@Redfish."
935                                          "AllowableValues"] = {
936                 "None", "Pxe", "Hdd", "Cd", "Diags", "BiosSetup", "Usb"};
937 
938             if (*bootModeStr !=
939                 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
940             {
941                 auto rfMode = dbusToRfBootMode(*bootModeStr);
942                 if (!rfMode.empty())
943                 {
944                     aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
945                         rfMode;
946                 }
947             }
948 
949             // If the BootSourceOverrideTarget is still "None" at the end,
950             // reset the BootSourceOverrideEnabled to indicate that
951             // overrides are disabled
952             if (aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] ==
953                 "None")
954             {
955                 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
956                     "Disabled";
957             }
958         },
959         "xyz.openbmc_project.Settings", bootDbusObj,
960         "org.freedesktop.DBus.Properties", "Get",
961         "xyz.openbmc_project.Control.Boot.Mode", "BootMode");
962 }
963 
964 /**
965  * @brief Retrieves boot source over DBUS
966  *
967  * @param[in] aResp         Shared pointer for generating response message.
968  * @param[in] oneTimeEnable Boolean to indicate boot properties are one-time.
969  *
970  * @return None.
971  */
972 inline void getBootSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
973                           bool oneTimeEnabled)
974 {
975     std::string bootDbusObj =
976         oneTimeEnabled ? "/xyz/openbmc_project/control/host0/boot/one_time"
977                        : "/xyz/openbmc_project/control/host0/boot";
978 
979     BMCWEB_LOG_DEBUG << "Is one time: " << oneTimeEnabled;
980     aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
981         (oneTimeEnabled) ? "Once" : "Continuous";
982 
983     crow::connections::systemBus->async_method_call(
984         [aResp, bootDbusObj](const boost::system::error_code ec,
985                              const std::variant<std::string>& bootSource) {
986             if (ec)
987             {
988                 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
989                 messages::internalError(aResp->res);
990                 return;
991             }
992 
993             const std::string* bootSourceStr =
994                 std::get_if<std::string>(&bootSource);
995 
996             if (!bootSourceStr)
997             {
998                 messages::internalError(aResp->res);
999                 return;
1000             }
1001             BMCWEB_LOG_DEBUG << "Boot source: " << *bootSourceStr;
1002 
1003             auto rfSource = dbusToRfBootSource(*bootSourceStr);
1004             if (!rfSource.empty())
1005             {
1006                 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
1007                     rfSource;
1008             }
1009         },
1010         "xyz.openbmc_project.Settings", bootDbusObj,
1011         "org.freedesktop.DBus.Properties", "Get",
1012         "xyz.openbmc_project.Control.Boot.Source", "BootSource");
1013     getBootMode(aResp, bootDbusObj);
1014 }
1015 
1016 /**
1017  * @brief Retrieves "One time" enabled setting over DBUS and calls function to
1018  * get boot source and boot mode.
1019  *
1020  * @param[in] aResp     Shared pointer for generating response message.
1021  *
1022  * @return None.
1023  */
1024 inline void getBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1025 {
1026     BMCWEB_LOG_DEBUG << "Get boot information.";
1027 
1028     crow::connections::systemBus->async_method_call(
1029         [aResp](const boost::system::error_code ec,
1030                 const std::variant<bool>& oneTime) {
1031             if (ec)
1032             {
1033                 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1034                 // not an error, don't have to have the interface
1035                 return;
1036             }
1037 
1038             const bool* oneTimePtr = std::get_if<bool>(&oneTime);
1039 
1040             if (!oneTimePtr)
1041             {
1042                 messages::internalError(aResp->res);
1043                 return;
1044             }
1045             getBootSource(aResp, *oneTimePtr);
1046         },
1047         "xyz.openbmc_project.Settings",
1048         "/xyz/openbmc_project/control/host0/boot/one_time",
1049         "org.freedesktop.DBus.Properties", "Get",
1050         "xyz.openbmc_project.Object.Enable", "Enabled");
1051 }
1052 
1053 /**
1054  * @brief Retrieves the Last Reset Time
1055  *
1056  * "Reset" is an overloaded term in Redfish, "Reset" includes power on
1057  * and power off. Even though this is the "system" Redfish object look at the
1058  * chassis D-Bus interface for the LastStateChangeTime since this has the
1059  * last power operation time.
1060  *
1061  * @param[in] aResp     Shared pointer for generating response message.
1062  *
1063  * @return None.
1064  */
1065 inline void getLastResetTime(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1066 {
1067     BMCWEB_LOG_DEBUG << "Getting System Last Reset Time";
1068 
1069     crow::connections::systemBus->async_method_call(
1070         [aResp](const boost::system::error_code ec,
1071                 std::variant<uint64_t>& lastResetTime) {
1072             if (ec)
1073             {
1074                 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
1075                 return;
1076             }
1077 
1078             const uint64_t* lastResetTimePtr =
1079                 std::get_if<uint64_t>(&lastResetTime);
1080 
1081             if (!lastResetTimePtr)
1082             {
1083                 messages::internalError(aResp->res);
1084                 return;
1085             }
1086             // LastStateChangeTime is epoch time, in milliseconds
1087             // https://github.com/openbmc/phosphor-dbus-interfaces/blob/33e8e1dd64da53a66e888d33dc82001305cd0bf9/xyz/openbmc_project/State/Chassis.interface.yaml#L19
1088             time_t lastResetTimeStamp =
1089                 static_cast<time_t>(*lastResetTimePtr / 1000);
1090 
1091             // Convert to ISO 8601 standard
1092             aResp->res.jsonValue["LastResetTime"] =
1093                 crow::utility::getDateTime(lastResetTimeStamp);
1094         },
1095         "xyz.openbmc_project.State.Chassis",
1096         "/xyz/openbmc_project/state/chassis0",
1097         "org.freedesktop.DBus.Properties", "Get",
1098         "xyz.openbmc_project.State.Chassis", "LastStateChangeTime");
1099 }
1100 
1101 /**
1102  * @brief Retrieves Automatic Retry properties. Known on D-Bus as AutoReboot.
1103  *
1104  * @param[in] aResp     Shared pointer for generating response message.
1105  *
1106  * @return None.
1107  */
1108 inline void getAutomaticRetry(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1109 {
1110     BMCWEB_LOG_DEBUG << "Get Automatic Retry policy";
1111 
1112     crow::connections::systemBus->async_method_call(
1113         [aResp](const boost::system::error_code ec,
1114                 std::variant<bool>& autoRebootEnabled) {
1115             if (ec)
1116             {
1117                 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
1118                 return;
1119             }
1120 
1121             const bool* autoRebootEnabledPtr =
1122                 std::get_if<bool>(&autoRebootEnabled);
1123 
1124             if (!autoRebootEnabledPtr)
1125             {
1126                 messages::internalError(aResp->res);
1127                 return;
1128             }
1129 
1130             BMCWEB_LOG_DEBUG << "Auto Reboot: " << *autoRebootEnabledPtr;
1131             if (*autoRebootEnabledPtr == true)
1132             {
1133                 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1134                     "RetryAttempts";
1135                 // If AutomaticRetry (AutoReboot) is enabled see how many
1136                 // attempts are left
1137                 crow::connections::systemBus->async_method_call(
1138                     [aResp](const boost::system::error_code ec2,
1139                             std::variant<uint32_t>& autoRebootAttemptsLeft) {
1140                         if (ec2)
1141                         {
1142                             BMCWEB_LOG_DEBUG << "D-BUS response error " << ec2;
1143                             return;
1144                         }
1145 
1146                         const uint32_t* autoRebootAttemptsLeftPtr =
1147                             std::get_if<uint32_t>(&autoRebootAttemptsLeft);
1148 
1149                         if (!autoRebootAttemptsLeftPtr)
1150                         {
1151                             messages::internalError(aResp->res);
1152                             return;
1153                         }
1154 
1155                         BMCWEB_LOG_DEBUG << "Auto Reboot Attempts Left: "
1156                                          << *autoRebootAttemptsLeftPtr;
1157 
1158                         aResp->res
1159                             .jsonValue["Boot"]
1160                                       ["RemainingAutomaticRetryAttempts"] =
1161                             *autoRebootAttemptsLeftPtr;
1162                     },
1163                     "xyz.openbmc_project.State.Host",
1164                     "/xyz/openbmc_project/state/host0",
1165                     "org.freedesktop.DBus.Properties", "Get",
1166                     "xyz.openbmc_project.Control.Boot.RebootAttempts",
1167                     "AttemptsLeft");
1168             }
1169             else
1170             {
1171                 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1172                     "Disabled";
1173             }
1174 
1175             // Not on D-Bus. Hardcoded here:
1176             // https://github.com/openbmc/phosphor-state-manager/blob/1dbbef42675e94fb1f78edb87d6b11380260535a/meson_options.txt#L71
1177             aResp->res.jsonValue["Boot"]["AutomaticRetryAttempts"] = 3;
1178 
1179             // "AutomaticRetryConfig" can be 3 values, Disabled, RetryAlways,
1180             // and RetryAttempts. OpenBMC only supports Disabled and
1181             // RetryAttempts.
1182             aResp->res.jsonValue["Boot"]["AutomaticRetryConfig@Redfish."
1183                                          "AllowableValues"] = {"Disabled",
1184                                                                "RetryAttempts"};
1185         },
1186         "xyz.openbmc_project.Settings",
1187         "/xyz/openbmc_project/control/host0/auto_reboot",
1188         "org.freedesktop.DBus.Properties", "Get",
1189         "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot");
1190 }
1191 
1192 /**
1193  * @brief Retrieves power restore policy over DBUS.
1194  *
1195  * @param[in] aResp     Shared pointer for generating response message.
1196  *
1197  * @return None.
1198  */
1199 inline void
1200     getPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1201 {
1202     BMCWEB_LOG_DEBUG << "Get power restore policy";
1203 
1204     crow::connections::systemBus->async_method_call(
1205         [aResp](const boost::system::error_code ec,
1206                 std::variant<std::string>& policy) {
1207             if (ec)
1208             {
1209                 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1210                 return;
1211             }
1212 
1213             const boost::container::flat_map<std::string, std::string>
1214                 policyMaps = {
1215                     {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy."
1216                      "AlwaysOn",
1217                      "AlwaysOn"},
1218                     {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy."
1219                      "AlwaysOff",
1220                      "AlwaysOff"},
1221                     {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy."
1222                      "Restore",
1223                      "LastState"}};
1224 
1225             const std::string* policyPtr = std::get_if<std::string>(&policy);
1226 
1227             if (!policyPtr)
1228             {
1229                 messages::internalError(aResp->res);
1230                 return;
1231             }
1232 
1233             auto policyMapsIt = policyMaps.find(*policyPtr);
1234             if (policyMapsIt == policyMaps.end())
1235             {
1236                 messages::internalError(aResp->res);
1237                 return;
1238             }
1239 
1240             aResp->res.jsonValue["PowerRestorePolicy"] = policyMapsIt->second;
1241         },
1242         "xyz.openbmc_project.Settings",
1243         "/xyz/openbmc_project/control/host0/power_restore_policy",
1244         "org.freedesktop.DBus.Properties", "Get",
1245         "xyz.openbmc_project.Control.Power.RestorePolicy",
1246         "PowerRestorePolicy");
1247 }
1248 
1249 /**
1250  * @brief Get TrustedModuleRequiredToBoot property. Determines whether or not
1251  * TPM is required for booting the host.
1252  *
1253  * @param[in] aResp     Shared pointer for generating response message.
1254  *
1255  * @return None.
1256  */
1257 inline void getTrustedModuleRequiredToBoot(
1258     const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1259 {
1260     BMCWEB_LOG_DEBUG << "Get TPM required to boot.";
1261 
1262     crow::connections::systemBus->async_method_call(
1263         [aResp](
1264             const boost::system::error_code ec,
1265             std::vector<std::pair<
1266                 std::string,
1267                 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
1268                 subtree) {
1269             if (ec)
1270             {
1271                 BMCWEB_LOG_DEBUG
1272                     << "DBUS response error on TPM.Policy GetSubTree" << ec;
1273                 // This is an optional D-Bus object so just return if
1274                 // error occurs
1275                 return;
1276             }
1277             if (subtree.size() == 0)
1278             {
1279                 // As noted above, this is an optional interface so just return
1280                 // if there is no instance found
1281                 return;
1282             }
1283 
1284             /* When there is more than one TPMEnable object... */
1285             if (subtree.size() > 1)
1286             {
1287                 BMCWEB_LOG_DEBUG
1288                     << "DBUS response has more than 1 TPM Enable object:"
1289                     << subtree.size();
1290                 // Throw an internal Error and return
1291                 messages::internalError(aResp->res);
1292                 return;
1293             }
1294 
1295             // Make sure the Dbus response map has a service and objectPath
1296             // field
1297             if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1298             {
1299                 BMCWEB_LOG_DEBUG << "TPM.Policy mapper error!";
1300                 messages::internalError(aResp->res);
1301                 return;
1302             }
1303 
1304             const std::string& path = subtree[0].first;
1305             const std::string& serv = subtree[0].second.begin()->first;
1306 
1307             // Valid TPM Enable object found, now reading the current value
1308             crow::connections::systemBus->async_method_call(
1309                 [aResp](const boost::system::error_code ec,
1310                         std::variant<bool>& tpmRequired) {
1311                     if (ec)
1312                     {
1313                         BMCWEB_LOG_DEBUG
1314                             << "D-BUS response error on TPM.Policy Get" << ec;
1315                         messages::internalError(aResp->res);
1316                         return;
1317                     }
1318 
1319                     const bool* tpmRequiredVal =
1320                         std::get_if<bool>(&tpmRequired);
1321 
1322                     if (!tpmRequiredVal)
1323                     {
1324                         messages::internalError(aResp->res);
1325                         return;
1326                     }
1327 
1328                     if (*tpmRequiredVal == true)
1329                     {
1330                         aResp->res
1331                             .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1332                             "Required";
1333                     }
1334                     else
1335                     {
1336                         aResp->res
1337                             .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1338                             "Disabled";
1339                     }
1340                 },
1341                 serv, path, "org.freedesktop.DBus.Properties", "Get",
1342                 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable");
1343         },
1344         "xyz.openbmc_project.ObjectMapper",
1345         "/xyz/openbmc_project/object_mapper",
1346         "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
1347         std::array<const char*, 1>{"xyz.openbmc_project.Control.TPM.Policy"});
1348 }
1349 
1350 /**
1351  * @brief Sets boot properties into DBUS object(s).
1352  *
1353  * @param[in] aResp           Shared pointer for generating response message.
1354  * @param[in] oneTimeEnabled  Is "one-time" setting already enabled.
1355  * @param[in] bootSource      The boot source to set.
1356  * @param[in] bootEnable      The source override "enable" to set.
1357  *
1358  * @return Integer error code.
1359  */
1360 inline void setBootModeOrSource(std::shared_ptr<bmcweb::AsyncResp> aResp,
1361                                 bool oneTimeEnabled,
1362                                 const std::optional<std::string>& bootSource,
1363                                 const std::optional<std::string>& bootEnable)
1364 {
1365     std::string bootSourceStr =
1366         "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
1367     std::string bootModeStr =
1368         "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
1369     bool oneTimeSetting = oneTimeEnabled;
1370     bool useBootSource = true;
1371 
1372     // Validate incoming parameters
1373     if (bootEnable)
1374     {
1375         if (*bootEnable == "Once")
1376         {
1377             oneTimeSetting = true;
1378         }
1379         else if (*bootEnable == "Continuous")
1380         {
1381             oneTimeSetting = false;
1382         }
1383         else if (*bootEnable == "Disabled")
1384         {
1385             BMCWEB_LOG_DEBUG << "Boot source override will be disabled";
1386             oneTimeSetting = false;
1387             useBootSource = false;
1388         }
1389         else
1390         {
1391             BMCWEB_LOG_DEBUG << "Unsupported value for "
1392                                 "BootSourceOverrideEnabled: "
1393                              << *bootEnable;
1394             messages::propertyValueNotInList(aResp->res, *bootEnable,
1395                                              "BootSourceOverrideEnabled");
1396             return;
1397         }
1398     }
1399 
1400     if (bootSource && useBootSource)
1401     {
1402         // Source target specified
1403         BMCWEB_LOG_DEBUG << "Boot source: " << *bootSource;
1404         // Figure out which DBUS interface and property to use
1405         if (assignBootParameters(aResp, *bootSource, bootSourceStr,
1406                                  bootModeStr))
1407         {
1408             BMCWEB_LOG_DEBUG
1409                 << "Invalid property value for BootSourceOverrideTarget: "
1410                 << *bootSource;
1411             messages::propertyValueNotInList(aResp->res, *bootSource,
1412                                              "BootSourceTargetOverride");
1413             return;
1414         }
1415     }
1416 
1417     // Act on validated parameters
1418     BMCWEB_LOG_DEBUG << "DBUS boot source: " << bootSourceStr;
1419     BMCWEB_LOG_DEBUG << "DBUS boot mode: " << bootModeStr;
1420     const char* bootObj =
1421         oneTimeSetting ? "/xyz/openbmc_project/control/host0/boot/one_time"
1422                        : "/xyz/openbmc_project/control/host0/boot";
1423 
1424     crow::connections::systemBus->async_method_call(
1425         [aResp](const boost::system::error_code ec) {
1426             if (ec)
1427             {
1428                 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1429                 messages::internalError(aResp->res);
1430                 return;
1431             }
1432             BMCWEB_LOG_DEBUG << "Boot source update done.";
1433         },
1434         "xyz.openbmc_project.Settings", bootObj,
1435         "org.freedesktop.DBus.Properties", "Set",
1436         "xyz.openbmc_project.Control.Boot.Source", "BootSource",
1437         std::variant<std::string>(bootSourceStr));
1438 
1439     crow::connections::systemBus->async_method_call(
1440         [aResp](const boost::system::error_code ec) {
1441             if (ec)
1442             {
1443                 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1444                 messages::internalError(aResp->res);
1445                 return;
1446             }
1447             BMCWEB_LOG_DEBUG << "Boot mode update done.";
1448         },
1449         "xyz.openbmc_project.Settings", bootObj,
1450         "org.freedesktop.DBus.Properties", "Set",
1451         "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
1452         std::variant<std::string>(bootModeStr));
1453 
1454     crow::connections::systemBus->async_method_call(
1455         [aResp{std::move(aResp)}](const boost::system::error_code ec) {
1456             if (ec)
1457             {
1458                 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1459                 messages::internalError(aResp->res);
1460                 return;
1461             }
1462             BMCWEB_LOG_DEBUG << "Boot enable update done.";
1463         },
1464         "xyz.openbmc_project.Settings",
1465         "/xyz/openbmc_project/control/host0/boot/one_time",
1466         "org.freedesktop.DBus.Properties", "Set",
1467         "xyz.openbmc_project.Object.Enable", "Enabled",
1468         std::variant<bool>(oneTimeSetting));
1469 }
1470 
1471 /**
1472  * @brief Retrieves "One time" enabled setting over DBUS and calls function to
1473  * set boot source/boot mode properties.
1474  *
1475  * @param[in] aResp      Shared pointer for generating response message.
1476  * @param[in] bootSource The boot source from incoming RF request.
1477  * @param[in] bootEnable The boot override enable from incoming RF request.
1478  *
1479  * @return Integer error code.
1480  */
1481 inline void
1482     setBootSourceProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1483                             std::optional<std::string> bootSource,
1484                             std::optional<std::string> bootEnable)
1485 {
1486     BMCWEB_LOG_DEBUG << "Set boot information.";
1487 
1488     crow::connections::systemBus->async_method_call(
1489         [aResp, bootSource{std::move(bootSource)},
1490          bootEnable{std::move(bootEnable)}](const boost::system::error_code ec,
1491                                             const std::variant<bool>& oneTime) {
1492             if (ec)
1493             {
1494                 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1495                 messages::internalError(aResp->res);
1496                 return;
1497             }
1498 
1499             const bool* oneTimePtr = std::get_if<bool>(&oneTime);
1500 
1501             if (!oneTimePtr)
1502             {
1503                 messages::internalError(aResp->res);
1504                 return;
1505             }
1506 
1507             BMCWEB_LOG_DEBUG << "Got one time: " << *oneTimePtr;
1508 
1509             setBootModeOrSource(aResp, *oneTimePtr, bootSource, bootEnable);
1510         },
1511         "xyz.openbmc_project.Settings",
1512         "/xyz/openbmc_project/control/host0/boot/one_time",
1513         "org.freedesktop.DBus.Properties", "Get",
1514         "xyz.openbmc_project.Object.Enable", "Enabled");
1515 }
1516 
1517 /**
1518  * @brief Sets AssetTag
1519  *
1520  * @param[in] aResp   Shared pointer for generating response message.
1521  * @param[in] assetTag  "AssetTag" from request.
1522  *
1523  * @return None.
1524  */
1525 inline void setAssetTag(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1526                         const std::string& assetTag)
1527 {
1528     crow::connections::systemBus->async_method_call(
1529         [aResp, assetTag](
1530             const boost::system::error_code ec,
1531             const std::vector<std::pair<
1532                 std::string,
1533                 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
1534                 subtree) {
1535             if (ec)
1536             {
1537                 BMCWEB_LOG_DEBUG << "D-Bus response error on GetSubTree " << ec;
1538                 messages::internalError(aResp->res);
1539                 return;
1540             }
1541             if (subtree.size() == 0)
1542             {
1543                 BMCWEB_LOG_DEBUG << "Can't find system D-Bus object!";
1544                 messages::internalError(aResp->res);
1545                 return;
1546             }
1547             // Assume only 1 system D-Bus object
1548             // Throw an error if there is more than 1
1549             if (subtree.size() > 1)
1550             {
1551                 BMCWEB_LOG_DEBUG << "Found more than 1 system D-Bus object!";
1552                 messages::internalError(aResp->res);
1553                 return;
1554             }
1555             if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1556             {
1557                 BMCWEB_LOG_DEBUG << "Asset Tag Set mapper error!";
1558                 messages::internalError(aResp->res);
1559                 return;
1560             }
1561 
1562             const std::string& path = subtree[0].first;
1563             const std::string& service = subtree[0].second.begin()->first;
1564 
1565             if (service.empty())
1566             {
1567                 BMCWEB_LOG_DEBUG << "Asset Tag Set service mapper error!";
1568                 messages::internalError(aResp->res);
1569                 return;
1570             }
1571 
1572             crow::connections::systemBus->async_method_call(
1573                 [aResp](const boost::system::error_code ec2) {
1574                     if (ec2)
1575                     {
1576                         BMCWEB_LOG_DEBUG
1577                             << "D-Bus response error on AssetTag Set " << ec2;
1578                         messages::internalError(aResp->res);
1579                         return;
1580                     }
1581                 },
1582                 service, path, "org.freedesktop.DBus.Properties", "Set",
1583                 "xyz.openbmc_project.Inventory.Decorator.AssetTag", "AssetTag",
1584                 std::variant<std::string>(assetTag));
1585         },
1586         "xyz.openbmc_project.ObjectMapper",
1587         "/xyz/openbmc_project/object_mapper",
1588         "xyz.openbmc_project.ObjectMapper", "GetSubTree",
1589         "/xyz/openbmc_project/inventory", int32_t(0),
1590         std::array<const char*, 1>{
1591             "xyz.openbmc_project.Inventory.Item.System"});
1592 }
1593 
1594 /**
1595  * @brief Sets automaticRetry (Auto Reboot)
1596  *
1597  * @param[in] aResp   Shared pointer for generating response message.
1598  * @param[in] automaticRetryConfig  "AutomaticRetryConfig" from request.
1599  *
1600  * @return None.
1601  */
1602 inline void setAutomaticRetry(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1603                               const std::string& automaticRetryConfig)
1604 {
1605     BMCWEB_LOG_DEBUG << "Set Automatic Retry.";
1606 
1607     // OpenBMC only supports "Disabled" and "RetryAttempts".
1608     bool autoRebootEnabled;
1609 
1610     if (automaticRetryConfig == "Disabled")
1611     {
1612         autoRebootEnabled = false;
1613     }
1614     else if (automaticRetryConfig == "RetryAttempts")
1615     {
1616         autoRebootEnabled = true;
1617     }
1618     else
1619     {
1620         BMCWEB_LOG_DEBUG << "Invalid property value for "
1621                             "AutomaticRetryConfig: "
1622                          << automaticRetryConfig;
1623         messages::propertyValueNotInList(aResp->res, automaticRetryConfig,
1624                                          "AutomaticRetryConfig");
1625         return;
1626     }
1627 
1628     crow::connections::systemBus->async_method_call(
1629         [aResp](const boost::system::error_code ec) {
1630             if (ec)
1631             {
1632                 messages::internalError(aResp->res);
1633                 return;
1634             }
1635         },
1636         "xyz.openbmc_project.Settings",
1637         "/xyz/openbmc_project/control/host0/auto_reboot",
1638         "org.freedesktop.DBus.Properties", "Set",
1639         "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
1640         std::variant<bool>(autoRebootEnabled));
1641 }
1642 
1643 /**
1644  * @brief Sets power restore policy properties.
1645  *
1646  * @param[in] aResp   Shared pointer for generating response message.
1647  * @param[in] policy  power restore policy properties from request.
1648  *
1649  * @return None.
1650  */
1651 inline void
1652     setPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1653                           const std::string& policy)
1654 {
1655     BMCWEB_LOG_DEBUG << "Set power restore policy.";
1656 
1657     const boost::container::flat_map<std::string, std::string> policyMaps = {
1658         {"AlwaysOn", "xyz.openbmc_project.Control.Power.RestorePolicy.Policy."
1659                      "AlwaysOn"},
1660         {"AlwaysOff", "xyz.openbmc_project.Control.Power.RestorePolicy.Policy."
1661                       "AlwaysOff"},
1662         {"LastState", "xyz.openbmc_project.Control.Power.RestorePolicy.Policy."
1663                       "Restore"}};
1664 
1665     std::string powerRestorPolicy;
1666 
1667     auto policyMapsIt = policyMaps.find(policy);
1668     if (policyMapsIt == policyMaps.end())
1669     {
1670         messages::propertyValueNotInList(aResp->res, policy,
1671                                          "PowerRestorePolicy");
1672         return;
1673     }
1674 
1675     powerRestorPolicy = policyMapsIt->second;
1676 
1677     crow::connections::systemBus->async_method_call(
1678         [aResp](const boost::system::error_code ec) {
1679             if (ec)
1680             {
1681                 messages::internalError(aResp->res);
1682                 return;
1683             }
1684         },
1685         "xyz.openbmc_project.Settings",
1686         "/xyz/openbmc_project/control/host0/power_restore_policy",
1687         "org.freedesktop.DBus.Properties", "Set",
1688         "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
1689         std::variant<std::string>(powerRestorPolicy));
1690 }
1691 
1692 #ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
1693 /**
1694  * @brief Retrieves provisioning status
1695  *
1696  * @param[in] aResp     Shared pointer for completing asynchronous calls.
1697  *
1698  * @return None.
1699  */
1700 inline void getProvisioningStatus(std::shared_ptr<bmcweb::AsyncResp> aResp)
1701 {
1702     BMCWEB_LOG_DEBUG << "Get OEM information.";
1703     crow::connections::systemBus->async_method_call(
1704         [aResp](const boost::system::error_code ec,
1705                 const std::vector<std::pair<std::string, VariantType>>&
1706                     propertiesList) {
1707             nlohmann::json& oemPFR =
1708                 aResp->res.jsonValue["Oem"]["OpenBmc"]["FirmwareProvisioning"];
1709             aResp->res.jsonValue["Oem"]["OpenBmc"]["@odata.type"] =
1710                 "#OemComputerSystem.OpenBmc";
1711             oemPFR["@odata.type"] = "#OemComputerSystem.FirmwareProvisioning";
1712 
1713             if (ec)
1714             {
1715                 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1716                 // not an error, don't have to have the interface
1717                 oemPFR["ProvisioningStatus"] = "NotProvisioned";
1718                 return;
1719             }
1720 
1721             const bool* provState = nullptr;
1722             const bool* lockState = nullptr;
1723             for (const std::pair<std::string, VariantType>& property :
1724                  propertiesList)
1725             {
1726                 if (property.first == "UfmProvisioned")
1727                 {
1728                     provState = std::get_if<bool>(&property.second);
1729                 }
1730                 else if (property.first == "UfmLocked")
1731                 {
1732                     lockState = std::get_if<bool>(&property.second);
1733                 }
1734             }
1735 
1736             if ((provState == nullptr) || (lockState == nullptr))
1737             {
1738                 BMCWEB_LOG_DEBUG << "Unable to get PFR attributes.";
1739                 messages::internalError(aResp->res);
1740                 return;
1741             }
1742 
1743             if (*provState == true)
1744             {
1745                 if (*lockState == true)
1746                 {
1747                     oemPFR["ProvisioningStatus"] = "ProvisionedAndLocked";
1748                 }
1749                 else
1750                 {
1751                     oemPFR["ProvisioningStatus"] = "ProvisionedButNotLocked";
1752                 }
1753             }
1754             else
1755             {
1756                 oemPFR["ProvisioningStatus"] = "NotProvisioned";
1757             }
1758         },
1759         "xyz.openbmc_project.PFR.Manager", "/xyz/openbmc_project/pfr",
1760         "org.freedesktop.DBus.Properties", "GetAll",
1761         "xyz.openbmc_project.PFR.Attributes");
1762 }
1763 #endif
1764 
1765 /**
1766  * @brief Translate the PowerMode to a response message.
1767  *
1768  * @param[in] aResp  Shared pointer for generating response message.
1769  * @param[in] modeValue  PowerMode value to be translated
1770  *
1771  * @return None.
1772  */
1773 inline void translatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1774                                const std::string& modeValue)
1775 {
1776     std::string modeString;
1777 
1778     if (modeValue == "xyz.openbmc_project.Control.Power.Mode."
1779                      "PowerMode.Static")
1780     {
1781         aResp->res.jsonValue["PowerMode"] = "Static";
1782     }
1783     else if (modeValue == "xyz.openbmc_project.Control.Power.Mode."
1784                           "PowerMode.MaximumPerformance")
1785     {
1786         aResp->res.jsonValue["PowerMode"] = "MaximumPerformance";
1787     }
1788     else if (modeValue == "xyz.openbmc_project.Control.Power.Mode."
1789                           "PowerMode.PowerSaving")
1790     {
1791         aResp->res.jsonValue["PowerMode"] = "PowerSaving";
1792     }
1793     else if (modeValue == "xyz.openbmc_project.Control.Power.Mode."
1794                           "PowerMode.OEM")
1795     {
1796         aResp->res.jsonValue["PowerMode"] = "OEM";
1797     }
1798     else
1799     {
1800         // Any other values would be invalid
1801         BMCWEB_LOG_DEBUG << "PowerMode value was not valid: " << modeValue;
1802         messages::internalError(aResp->res);
1803     }
1804 }
1805 
1806 /**
1807  * @brief Retrieves system power mode
1808  *
1809  * @param[in] aResp  Shared pointer for generating response message.
1810  *
1811  * @return None.
1812  */
1813 inline void getPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1814 {
1815     BMCWEB_LOG_DEBUG << "Get power mode.";
1816 
1817     // Get Power Mode object path:
1818     crow::connections::systemBus->async_method_call(
1819         [aResp](
1820             const boost::system::error_code ec,
1821             const std::vector<std::pair<
1822                 std::string,
1823                 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
1824                 subtree) {
1825             if (ec)
1826             {
1827                 BMCWEB_LOG_DEBUG
1828                     << "DBUS response error on Power.Mode GetSubTree " << ec;
1829                 // This is an optional D-Bus object so just return if
1830                 // error occurs
1831                 return;
1832             }
1833             if (subtree.empty())
1834             {
1835                 // As noted above, this is an optional interface so just return
1836                 // if there is no instance found
1837                 return;
1838             }
1839             if (subtree.size() > 1)
1840             {
1841                 // More then one PowerMode object is not supported and is an
1842                 // error
1843                 BMCWEB_LOG_DEBUG
1844                     << "Found more than 1 system D-Bus Power.Mode objects: "
1845                     << subtree.size();
1846                 messages::internalError(aResp->res);
1847                 return;
1848             }
1849             if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
1850             {
1851                 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
1852                 messages::internalError(aResp->res);
1853                 return;
1854             }
1855             const std::string& path = subtree[0].first;
1856             const std::string& service = subtree[0].second.begin()->first;
1857             if (service.empty())
1858             {
1859                 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
1860                 messages::internalError(aResp->res);
1861                 return;
1862             }
1863             // Valid Power Mode object found, now read the current value
1864             crow::connections::systemBus->async_method_call(
1865                 [aResp](const boost::system::error_code ec,
1866                         const std::variant<std::string>& pmode) {
1867                     if (ec)
1868                     {
1869                         BMCWEB_LOG_DEBUG
1870                             << "DBUS response error on PowerMode Get: " << ec;
1871                         messages::internalError(aResp->res);
1872                         return;
1873                     }
1874 
1875                     const std::string* s = std::get_if<std::string>(&pmode);
1876                     if (s == nullptr)
1877                     {
1878                         BMCWEB_LOG_DEBUG << "Unable to get PowerMode value";
1879                         messages::internalError(aResp->res);
1880                         return;
1881                     }
1882 
1883                     aResp->res.jsonValue["PowerMode@Redfish.AllowableValues"] =
1884                         {"Static", "MaximumPerformance", "PowerSaving"};
1885 
1886                     BMCWEB_LOG_DEBUG << "Current power mode: " << *s;
1887                     translatePowerMode(aResp, *s);
1888                 },
1889                 service, path, "org.freedesktop.DBus.Properties", "Get",
1890                 "xyz.openbmc_project.Control.Power.Mode", "PowerMode");
1891         },
1892         "xyz.openbmc_project.ObjectMapper",
1893         "/xyz/openbmc_project/object_mapper",
1894         "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
1895         std::array<const char*, 1>{"xyz.openbmc_project.Control.Power.Mode"});
1896 }
1897 
1898 /**
1899  * @brief Validate the specified mode is valid and return the PowerMode
1900  * name associated with that string
1901  *
1902  * @param[in] aResp   Shared pointer for generating response message.
1903  * @param[in] modeString  String representing the desired PowerMode
1904  *
1905  * @return PowerMode value or empty string if mode is not valid
1906  */
1907 inline std::string
1908     validatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1909                       const std::string& modeString)
1910 {
1911     std::string mode;
1912 
1913     if (modeString == "Static")
1914     {
1915         mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static";
1916     }
1917     else if (modeString == "MaximumPerformance")
1918     {
1919         mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode."
1920                "MaximumPerformance";
1921     }
1922     else if (modeString == "PowerSaving")
1923     {
1924         mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving";
1925     }
1926     else
1927     {
1928         messages::propertyValueNotInList(aResp->res, modeString, "PowerMode");
1929     }
1930     return mode;
1931 }
1932 
1933 /**
1934  * @brief Sets system power mode.
1935  *
1936  * @param[in] aResp   Shared pointer for generating response message.
1937  * @param[in] pmode   System power mode from request.
1938  *
1939  * @return None.
1940  */
1941 inline void setPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1942                          const std::string& pmode)
1943 {
1944     BMCWEB_LOG_DEBUG << "Set power mode.";
1945 
1946     std::string powerMode = validatePowerMode(aResp, pmode);
1947     if (powerMode.empty())
1948     {
1949         return;
1950     }
1951 
1952     // Get Power Mode object path:
1953     crow::connections::systemBus->async_method_call(
1954         [aResp, powerMode](
1955             const boost::system::error_code ec,
1956             const std::vector<std::pair<
1957                 std::string,
1958                 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
1959                 subtree) {
1960             if (ec)
1961             {
1962                 BMCWEB_LOG_DEBUG
1963                     << "DBUS response error on Power.Mode GetSubTree " << ec;
1964                 // This is an optional D-Bus object, but user attempted to patch
1965                 messages::internalError(aResp->res);
1966                 return;
1967             }
1968             if (subtree.empty())
1969             {
1970                 // This is an optional D-Bus object, but user attempted to patch
1971                 messages::resourceNotFound(aResp->res, "ComputerSystem",
1972                                            "PowerMode");
1973                 return;
1974             }
1975             if (subtree.size() > 1)
1976             {
1977                 // More then one PowerMode object is not supported and is an
1978                 // error
1979                 BMCWEB_LOG_DEBUG
1980                     << "Found more than 1 system D-Bus Power.Mode objects: "
1981                     << subtree.size();
1982                 messages::internalError(aResp->res);
1983                 return;
1984             }
1985             if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
1986             {
1987                 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
1988                 messages::internalError(aResp->res);
1989                 return;
1990             }
1991             const std::string& path = subtree[0].first;
1992             const std::string& service = subtree[0].second.begin()->first;
1993             if (service.empty())
1994             {
1995                 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
1996                 messages::internalError(aResp->res);
1997                 return;
1998             }
1999 
2000             BMCWEB_LOG_DEBUG << "Setting power mode(" << powerMode << ") -> "
2001                              << path;
2002 
2003             // Set the Power Mode property
2004             crow::connections::systemBus->async_method_call(
2005                 [aResp](const boost::system::error_code ec) {
2006                     if (ec)
2007                     {
2008                         messages::internalError(aResp->res);
2009                         return;
2010                     }
2011                 },
2012                 service, path, "org.freedesktop.DBus.Properties", "Set",
2013                 "xyz.openbmc_project.Control.Power.Mode", "PowerMode",
2014                 std::variant<std::string>(powerMode));
2015         },
2016         "xyz.openbmc_project.ObjectMapper",
2017         "/xyz/openbmc_project/object_mapper",
2018         "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2019         std::array<const char*, 1>{"xyz.openbmc_project.Control.Power.Mode"});
2020 }
2021 
2022 /**
2023  * @brief Translates watchdog timeout action DBUS property value to redfish.
2024  *
2025  * @param[in] dbusAction    The watchdog timeout action in D-BUS.
2026  *
2027  * @return Returns as a string, the timeout action in Redfish terms. If
2028  * translation cannot be done, returns an empty string.
2029  */
2030 inline std::string dbusToRfWatchdogAction(const std::string& dbusAction)
2031 {
2032     if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.None")
2033     {
2034         return "None";
2035     }
2036     if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.HardReset")
2037     {
2038         return "ResetSystem";
2039     }
2040     if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerOff")
2041     {
2042         return "PowerDown";
2043     }
2044     if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerCycle")
2045     {
2046         return "PowerCycle";
2047     }
2048 
2049     return "";
2050 }
2051 
2052 /**
2053  *@brief Translates timeout action from Redfish to DBUS property value.
2054  *
2055  *@param[in] rfAction The timeout action in Redfish.
2056  *
2057  *@return Returns as a string, the time_out action as expected by DBUS.
2058  *If translation cannot be done, returns an empty string.
2059  */
2060 
2061 inline std::string rfToDbusWDTTimeOutAct(const std::string& rfAction)
2062 {
2063     if (rfAction == "None")
2064     {
2065         return "xyz.openbmc_project.State.Watchdog.Action.None";
2066     }
2067     if (rfAction == "PowerCycle")
2068     {
2069         return "xyz.openbmc_project.State.Watchdog.Action.PowerCycle";
2070     }
2071     if (rfAction == "PowerDown")
2072     {
2073         return "xyz.openbmc_project.State.Watchdog.Action.PowerOff";
2074     }
2075     if (rfAction == "ResetSystem")
2076     {
2077         return "xyz.openbmc_project.State.Watchdog.Action.HardReset";
2078     }
2079 
2080     return "";
2081 }
2082 
2083 /**
2084  * @brief Retrieves host watchdog timer properties over DBUS
2085  *
2086  * @param[in] aResp     Shared pointer for completing asynchronous calls.
2087  *
2088  * @return None.
2089  */
2090 inline void
2091     getHostWatchdogTimer(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
2092 {
2093     BMCWEB_LOG_DEBUG << "Get host watchodg";
2094     crow::connections::systemBus->async_method_call(
2095         [aResp](const boost::system::error_code ec,
2096                 PropertiesType& properties) {
2097             if (ec)
2098             {
2099                 // watchdog service is stopped
2100                 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2101                 return;
2102             }
2103 
2104             BMCWEB_LOG_DEBUG << "Got " << properties.size() << " wdt prop.";
2105 
2106             nlohmann::json& hostWatchdogTimer =
2107                 aResp->res.jsonValue["HostWatchdogTimer"];
2108 
2109             // watchdog service is running/enabled
2110             hostWatchdogTimer["Status"]["State"] = "Enabled";
2111 
2112             for (const auto& property : properties)
2113             {
2114                 BMCWEB_LOG_DEBUG << "prop=" << property.first;
2115                 if (property.first == "Enabled")
2116                 {
2117                     const bool* state = std::get_if<bool>(&property.second);
2118 
2119                     if (!state)
2120                     {
2121                         messages::internalError(aResp->res);
2122                         return;
2123                     }
2124 
2125                     hostWatchdogTimer["FunctionEnabled"] = *state;
2126                 }
2127                 else if (property.first == "ExpireAction")
2128                 {
2129                     const std::string* s =
2130                         std::get_if<std::string>(&property.second);
2131                     if (!s)
2132                     {
2133                         messages::internalError(aResp->res);
2134                         return;
2135                     }
2136 
2137                     std::string action = dbusToRfWatchdogAction(*s);
2138                     if (action.empty())
2139                     {
2140                         messages::internalError(aResp->res);
2141                         return;
2142                     }
2143                     hostWatchdogTimer["TimeoutAction"] = action;
2144                 }
2145             }
2146         },
2147         "xyz.openbmc_project.Watchdog", "/xyz/openbmc_project/watchdog/host0",
2148         "org.freedesktop.DBus.Properties", "GetAll",
2149         "xyz.openbmc_project.State.Watchdog");
2150 }
2151 
2152 /**
2153  * @brief Sets Host WatchDog Timer properties.
2154  *
2155  * @param[in] aResp      Shared pointer for generating response message.
2156  * @param[in] wdtEnable  The WDTimer Enable value (true/false) from incoming
2157  *                       RF request.
2158  * @param[in] wdtTimeOutAction The WDT Timeout action, from incoming RF request.
2159  *
2160  * @return None.
2161  */
2162 inline void setWDTProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2163                              const std::optional<bool> wdtEnable,
2164                              const std::optional<std::string>& wdtTimeOutAction)
2165 {
2166     BMCWEB_LOG_DEBUG << "Set host watchdog";
2167 
2168     if (wdtTimeOutAction)
2169     {
2170         std::string wdtTimeOutActStr = rfToDbusWDTTimeOutAct(*wdtTimeOutAction);
2171         // check if TimeOut Action is Valid
2172         if (wdtTimeOutActStr.empty())
2173         {
2174             BMCWEB_LOG_DEBUG << "Unsupported value for TimeoutAction: "
2175                              << *wdtTimeOutAction;
2176             messages::propertyValueNotInList(aResp->res, *wdtTimeOutAction,
2177                                              "TimeoutAction");
2178             return;
2179         }
2180 
2181         crow::connections::systemBus->async_method_call(
2182             [aResp](const boost::system::error_code ec) {
2183                 if (ec)
2184                 {
2185                     BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2186                     messages::internalError(aResp->res);
2187                     return;
2188                 }
2189             },
2190             "xyz.openbmc_project.Watchdog",
2191             "/xyz/openbmc_project/watchdog/host0",
2192             "org.freedesktop.DBus.Properties", "Set",
2193             "xyz.openbmc_project.State.Watchdog", "ExpireAction",
2194             std::variant<std::string>(wdtTimeOutActStr));
2195     }
2196 
2197     if (wdtEnable)
2198     {
2199         crow::connections::systemBus->async_method_call(
2200             [aResp](const boost::system::error_code ec) {
2201                 if (ec)
2202                 {
2203                     BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2204                     messages::internalError(aResp->res);
2205                     return;
2206                 }
2207             },
2208             "xyz.openbmc_project.Watchdog",
2209             "/xyz/openbmc_project/watchdog/host0",
2210             "org.freedesktop.DBus.Properties", "Set",
2211             "xyz.openbmc_project.State.Watchdog", "Enabled",
2212             std::variant<bool>(*wdtEnable));
2213     }
2214 }
2215 
2216 /**
2217  * SystemsCollection derived class for delivering ComputerSystems Collection
2218  * Schema
2219  */
2220 inline void requestRoutesSystemsCollection(App& app)
2221 {
2222     BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
2223         .privileges({{"Login"}})
2224         .methods(boost::beast::http::verb::get)(
2225             [](const crow::Request& req,
2226                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2227                 asyncResp->res.jsonValue["@odata.type"] =
2228                     "#ComputerSystemCollection.ComputerSystemCollection";
2229                 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems";
2230                 asyncResp->res.jsonValue["Name"] = "Computer System Collection";
2231 
2232                 crow::connections::systemBus->async_method_call(
2233                     [asyncResp,
2234                      &req](const boost::system::error_code ec,
2235                            const std::variant<std::string>& /*hostName*/) {
2236                         nlohmann::json& ifaceArray =
2237                             asyncResp->res.jsonValue["Members"];
2238                         ifaceArray = nlohmann::json::array();
2239                         auto& count =
2240                             asyncResp->res.jsonValue["Members@odata.count"];
2241                         ifaceArray.push_back(
2242                             {{"@odata.id", "/redfish/v1/Systems/system"}});
2243                         count = ifaceArray.size();
2244                         if (!ec)
2245                         {
2246                             BMCWEB_LOG_DEBUG << "Hypervisor is available";
2247                             ifaceArray.push_back(
2248                                 {{"@odata.id",
2249                                   "/redfish/v1/Systems/hypervisor"}});
2250                             count = ifaceArray.size();
2251                         }
2252                     },
2253                     "xyz.openbmc_project.Settings",
2254                     "/xyz/openbmc_project/network/hypervisor",
2255                     "org.freedesktop.DBus.Properties", "Get",
2256                     "xyz.openbmc_project.Network.SystemConfiguration",
2257                     "HostName");
2258             });
2259 }
2260 
2261 /**
2262  * Function transceives data with dbus directly.
2263  */
2264 void doNMI(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
2265 {
2266     constexpr char const* serviceName = "xyz.openbmc_project.Control.Host.NMI";
2267     constexpr char const* objectPath = "/xyz/openbmc_project/control/host0/nmi";
2268     constexpr char const* interfaceName =
2269         "xyz.openbmc_project.Control.Host.NMI";
2270     constexpr char const* method = "NMI";
2271 
2272     crow::connections::systemBus->async_method_call(
2273         [asyncResp](const boost::system::error_code ec) {
2274             if (ec)
2275             {
2276                 BMCWEB_LOG_ERROR << " Bad D-Bus request error: " << ec;
2277                 messages::internalError(asyncResp->res);
2278                 return;
2279             }
2280             messages::success(asyncResp->res);
2281         },
2282         serviceName, objectPath, interfaceName, method);
2283 }
2284 
2285 /**
2286  * SystemActionsReset class supports handle POST method for Reset action.
2287  * The class retrieves and sends data directly to D-Bus.
2288  */
2289 inline void requestRoutesSystemActionsReset(App& app)
2290 {
2291     /**
2292      * Function handles POST method request.
2293      * Analyzes POST body message before sends Reset request data to D-Bus.
2294      */
2295     BMCWEB_ROUTE(app,
2296                  "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset/")
2297         .privileges({{"ConfigureComponent"}})
2298         .methods(
2299             boost::beast::http::verb::
2300                 post)([](const crow::Request& req,
2301                          const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2302             std::string resetType;
2303             if (!json_util::readJson(req, asyncResp->res, "ResetType",
2304                                      resetType))
2305             {
2306                 return;
2307             }
2308 
2309             // Get the command and host vs. chassis
2310             std::string command;
2311             bool hostCommand;
2312             if ((resetType == "On") || (resetType == "ForceOn"))
2313             {
2314                 command = "xyz.openbmc_project.State.Host.Transition.On";
2315                 hostCommand = true;
2316             }
2317             else if (resetType == "ForceOff")
2318             {
2319                 command = "xyz.openbmc_project.State.Chassis.Transition.Off";
2320                 hostCommand = false;
2321             }
2322             else if (resetType == "ForceRestart")
2323             {
2324                 command =
2325                     "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot";
2326                 hostCommand = true;
2327             }
2328             else if (resetType == "GracefulShutdown")
2329             {
2330                 command = "xyz.openbmc_project.State.Host.Transition.Off";
2331                 hostCommand = true;
2332             }
2333             else if (resetType == "GracefulRestart")
2334             {
2335                 command = "xyz.openbmc_project.State.Host.Transition."
2336                           "GracefulWarmReboot";
2337                 hostCommand = true;
2338             }
2339             else if (resetType == "PowerCycle")
2340             {
2341                 command = "xyz.openbmc_project.State.Host.Transition.Reboot";
2342                 hostCommand = true;
2343             }
2344             else if (resetType == "Nmi")
2345             {
2346                 doNMI(asyncResp);
2347                 return;
2348             }
2349             else
2350             {
2351                 messages::actionParameterUnknown(asyncResp->res, "Reset",
2352                                                  resetType);
2353                 return;
2354             }
2355 
2356             if (hostCommand)
2357             {
2358                 crow::connections::systemBus->async_method_call(
2359                     [asyncResp, resetType](const boost::system::error_code ec) {
2360                         if (ec)
2361                         {
2362                             BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
2363                             if (ec.value() ==
2364                                 boost::asio::error::invalid_argument)
2365                             {
2366                                 messages::actionParameterNotSupported(
2367                                     asyncResp->res, resetType, "Reset");
2368                             }
2369                             else
2370                             {
2371                                 messages::internalError(asyncResp->res);
2372                             }
2373                             return;
2374                         }
2375                         messages::success(asyncResp->res);
2376                     },
2377                     "xyz.openbmc_project.State.Host",
2378                     "/xyz/openbmc_project/state/host0",
2379                     "org.freedesktop.DBus.Properties", "Set",
2380                     "xyz.openbmc_project.State.Host", "RequestedHostTransition",
2381                     std::variant<std::string>{command});
2382             }
2383             else
2384             {
2385                 crow::connections::systemBus->async_method_call(
2386                     [asyncResp, resetType](const boost::system::error_code ec) {
2387                         if (ec)
2388                         {
2389                             BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
2390                             if (ec.value() ==
2391                                 boost::asio::error::invalid_argument)
2392                             {
2393                                 messages::actionParameterNotSupported(
2394                                     asyncResp->res, resetType, "Reset");
2395                             }
2396                             else
2397                             {
2398                                 messages::internalError(asyncResp->res);
2399                             }
2400                             return;
2401                         }
2402                         messages::success(asyncResp->res);
2403                     },
2404                     "xyz.openbmc_project.State.Chassis",
2405                     "/xyz/openbmc_project/state/chassis0",
2406                     "org.freedesktop.DBus.Properties", "Set",
2407                     "xyz.openbmc_project.State.Chassis",
2408                     "RequestedPowerTransition",
2409                     std::variant<std::string>{command});
2410             }
2411         });
2412 }
2413 
2414 /**
2415  * Systems derived class for delivering Computer Systems Schema.
2416  */
2417 inline void requestRoutesSystems(App& app)
2418 {
2419 
2420     /**
2421      * Functions triggers appropriate requests on DBus
2422      */
2423     BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/")
2424         .privileges({{"Login"}})
2425         .methods(
2426             boost::beast::http::verb::
2427                 get)([](const crow::Request&,
2428                         const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2429             asyncResp->res.jsonValue["@odata.type"] =
2430                 "#ComputerSystem.v1_15_0.ComputerSystem";
2431             asyncResp->res.jsonValue["Name"] = "system";
2432             asyncResp->res.jsonValue["Id"] = "system";
2433             asyncResp->res.jsonValue["SystemType"] = "Physical";
2434             asyncResp->res.jsonValue["Description"] = "Computer System";
2435             asyncResp->res.jsonValue["ProcessorSummary"]["Count"] = 0;
2436             asyncResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
2437                 "Disabled";
2438             asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
2439                 uint64_t(0);
2440             asyncResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
2441                 "Disabled";
2442             asyncResp->res.jsonValue["@odata.id"] =
2443                 "/redfish/v1/Systems/system";
2444 
2445             asyncResp->res.jsonValue["Processors"] = {
2446                 {"@odata.id", "/redfish/v1/Systems/system/Processors"}};
2447             asyncResp->res.jsonValue["Memory"] = {
2448                 {"@odata.id", "/redfish/v1/Systems/system/Memory"}};
2449             asyncResp->res.jsonValue["Storage"] = {
2450                 {"@odata.id", "/redfish/v1/Systems/system/Storage"}};
2451 
2452             asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"] = {
2453                 {"target",
2454                  "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset"},
2455                 {"@Redfish.ActionInfo",
2456                  "/redfish/v1/Systems/system/ResetActionInfo"}};
2457 
2458             asyncResp->res.jsonValue["LogServices"] = {
2459                 {"@odata.id", "/redfish/v1/Systems/system/LogServices"}};
2460 
2461             asyncResp->res.jsonValue["Bios"] = {
2462                 {"@odata.id", "/redfish/v1/Systems/system/Bios"}};
2463 
2464             asyncResp->res.jsonValue["Links"]["ManagedBy"] = {
2465                 {{"@odata.id", "/redfish/v1/Managers/bmc"}}};
2466 
2467             asyncResp->res.jsonValue["Status"] = {
2468                 {"Health", "OK"},
2469                 {"State", "Enabled"},
2470             };
2471 
2472             // Fill in SerialConsole info
2473             asyncResp->res.jsonValue["SerialConsole"]["MaxConcurrentSessions"] =
2474                 15;
2475             asyncResp->res.jsonValue["SerialConsole"]["IPMI"] = {
2476                 {"ServiceEnabled", true},
2477             };
2478             // TODO (Gunnar): Should look for obmc-console-ssh@2200.service
2479             asyncResp->res.jsonValue["SerialConsole"]["SSH"] = {
2480                 {"ServiceEnabled", true},
2481                 {"Port", 2200},
2482                 // https://github.com/openbmc/docs/blob/master/console.md
2483                 {"HotKeySequenceDisplay", "Press ~. to exit console"},
2484             };
2485 
2486 #ifdef BMCWEB_ENABLE_KVM
2487             // Fill in GraphicalConsole info
2488             asyncResp->res.jsonValue["GraphicalConsole"] = {
2489                 {"ServiceEnabled", true},
2490                 {"MaxConcurrentSessions", 4},
2491                 {"ConnectTypesSupported", {"KVMIP"}},
2492             };
2493 #endif // BMCWEB_ENABLE_KVM
2494             constexpr const std::array<const char*, 4> inventoryForSystems = {
2495                 "xyz.openbmc_project.Inventory.Item.Dimm",
2496                 "xyz.openbmc_project.Inventory.Item.Cpu",
2497                 "xyz.openbmc_project.Inventory.Item.Drive",
2498                 "xyz.openbmc_project.Inventory.Item.StorageController"};
2499 
2500             auto health = std::make_shared<HealthPopulate>(asyncResp);
2501             crow::connections::systemBus->async_method_call(
2502                 [health](const boost::system::error_code ec,
2503                          std::vector<std::string>& resp) {
2504                     if (ec)
2505                     {
2506                         // no inventory
2507                         return;
2508                     }
2509 
2510                     health->inventory = std::move(resp);
2511                 },
2512                 "xyz.openbmc_project.ObjectMapper",
2513                 "/xyz/openbmc_project/object_mapper",
2514                 "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", "/",
2515                 int32_t(0), inventoryForSystems);
2516 
2517             health->populate();
2518 
2519             getMainChassisId(
2520                 asyncResp, [](const std::string& chassisId,
2521                               const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
2522                     aRsp->res.jsonValue["Links"]["Chassis"] = {
2523                         {{"@odata.id", "/redfish/v1/Chassis/" + chassisId}}};
2524                 });
2525 
2526             getLocationIndicatorActive(asyncResp);
2527             // TODO (Gunnar): Remove IndicatorLED after enough time has passed
2528             getIndicatorLedState(asyncResp);
2529             getComputerSystem(asyncResp, health);
2530             getHostState(asyncResp);
2531             getBootProperties(asyncResp);
2532             getBootProgress(asyncResp);
2533             getPCIeDeviceList(asyncResp, "PCIeDevices");
2534             getHostWatchdogTimer(asyncResp);
2535             getPowerRestorePolicy(asyncResp);
2536             getAutomaticRetry(asyncResp);
2537             getLastResetTime(asyncResp);
2538 #ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
2539             getProvisioningStatus(asyncResp);
2540 #endif
2541             getTrustedModuleRequiredToBoot(asyncResp);
2542             getPowerMode(asyncResp);
2543         });
2544     BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/")
2545         .privileges({{"ConfigureComponent"}})
2546         .methods(boost::beast::http::verb::patch)(
2547             [](const crow::Request& req,
2548                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2549                 std::optional<bool> locationIndicatorActive;
2550                 std::optional<std::string> indicatorLed;
2551                 std::optional<nlohmann::json> bootProps;
2552                 std::optional<nlohmann::json> wdtTimerProps;
2553                 std::optional<std::string> assetTag;
2554                 std::optional<std::string> powerRestorePolicy;
2555                 std::optional<std::string> powerMode;
2556 
2557                 if (!json_util::readJson(
2558                         req, asyncResp->res, "IndicatorLED", indicatorLed,
2559                         "LocationIndicatorActive", locationIndicatorActive,
2560                         "Boot", bootProps, "WatchdogTimer", wdtTimerProps,
2561                         "PowerRestorePolicy", powerRestorePolicy, "AssetTag",
2562                         assetTag, "PowerMode", powerMode))
2563                 {
2564                     return;
2565                 }
2566 
2567                 asyncResp->res.result(boost::beast::http::status::no_content);
2568 
2569                 if (assetTag)
2570                 {
2571                     setAssetTag(asyncResp, *assetTag);
2572                 }
2573 
2574                 if (wdtTimerProps)
2575                 {
2576                     std::optional<bool> wdtEnable;
2577                     std::optional<std::string> wdtTimeOutAction;
2578 
2579                     if (!json_util::readJson(*wdtTimerProps, asyncResp->res,
2580                                              "FunctionEnabled", wdtEnable,
2581                                              "TimeoutAction", wdtTimeOutAction))
2582                     {
2583                         return;
2584                     }
2585                     setWDTProperties(asyncResp, wdtEnable, wdtTimeOutAction);
2586                 }
2587 
2588                 if (bootProps)
2589                 {
2590                     std::optional<std::string> bootSource;
2591                     std::optional<std::string> bootEnable;
2592                     std::optional<std::string> automaticRetryConfig;
2593 
2594                     if (!json_util::readJson(
2595                             *bootProps, asyncResp->res,
2596                             "BootSourceOverrideTarget", bootSource,
2597                             "BootSourceOverrideEnabled", bootEnable,
2598                             "AutomaticRetryConfig", automaticRetryConfig))
2599                     {
2600                         return;
2601                     }
2602                     if (bootSource || bootEnable)
2603                     {
2604                         setBootSourceProperties(asyncResp,
2605                                                 std::move(bootSource),
2606                                                 std::move(bootEnable));
2607                     }
2608                     if (automaticRetryConfig)
2609                     {
2610                         setAutomaticRetry(asyncResp, *automaticRetryConfig);
2611                     }
2612                 }
2613 
2614                 if (locationIndicatorActive)
2615                 {
2616                     setLocationIndicatorActive(asyncResp,
2617                                                *locationIndicatorActive);
2618                 }
2619 
2620                 // TODO (Gunnar): Remove IndicatorLED after enough time has
2621                 // passed
2622                 if (indicatorLed)
2623                 {
2624                     setIndicatorLedState(asyncResp, *indicatorLed);
2625                     asyncResp->res.addHeader(
2626                         boost::beast::http::field::warning,
2627                         "299 - \"IndicatorLED is deprecated. Use "
2628                         "LocationIndicatorActive instead.\"");
2629                 }
2630 
2631                 if (powerRestorePolicy)
2632                 {
2633                     setPowerRestorePolicy(asyncResp, *powerRestorePolicy);
2634                 }
2635 
2636                 if (powerMode)
2637                 {
2638                     setPowerMode(asyncResp, *powerMode);
2639                 }
2640             });
2641 }
2642 
2643 /**
2644  * SystemResetActionInfo derived class for delivering Computer Systems
2645  * ResetType AllowableValues using ResetInfo schema.
2646  */
2647 inline void requestRoutesSystemResetActionInfo(App& app)
2648 {
2649 
2650     /**
2651      * Functions triggers appropriate requests on DBus
2652      */
2653     BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/ResetActionInfo/")
2654         .privileges({{"Login"}})
2655         .methods(boost::beast::http::verb::get)(
2656             [](const crow::Request&,
2657                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2658                 asyncResp->res.jsonValue = {
2659                     {"@odata.type", "#ActionInfo.v1_1_2.ActionInfo"},
2660                     {"@odata.id", "/redfish/v1/Systems/system/ResetActionInfo"},
2661                     {"Name", "Reset Action Info"},
2662                     {"Id", "ResetActionInfo"},
2663                     {"Parameters",
2664                      {{{"Name", "ResetType"},
2665                        {"Required", true},
2666                        {"DataType", "String"},
2667                        {"AllowableValues",
2668                         {"On", "ForceOff", "ForceOn", "ForceRestart",
2669                          "GracefulRestart", "GracefulShutdown", "PowerCycle",
2670                          "Nmi"}}}}}};
2671             });
2672 }
2673 } // namespace redfish
2674