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