1 /* 2 // Copyright (c) 2018 Intel Corporation 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 */ 16 #pragma once 17 18 #include "health.hpp" 19 #include "pcie.hpp" 20 #include "redfish_util.hpp" 21 22 #include <boost/container/flat_map.hpp> 23 #include <node.hpp> 24 #include <utils/fw_utils.hpp> 25 #include <utils/json_utils.hpp> 26 #include <variant> 27 28 namespace redfish 29 { 30 31 /* 32 * @brief Update "ProcessorSummary" "Count" based on Cpu PresenceState 33 * 34 * @param[in] aResp Shared pointer for completing asynchronous calls 35 * @param[in] cpuPresenceState CPU present or not 36 * 37 * @return None. 38 */ 39 void modifyCpuPresenceState(std::shared_ptr<AsyncResp> aResp, 40 const std::variant<bool> &cpuPresenceState) 41 { 42 const bool *isCpuPresent = std::get_if<bool>(&cpuPresenceState); 43 44 if (isCpuPresent == nullptr) 45 { 46 messages::internalError(aResp->res); 47 return; 48 } 49 BMCWEB_LOG_DEBUG << "Cpu Present:" << *isCpuPresent; 50 51 nlohmann::json &procCount = 52 aResp->res.jsonValue["ProcessorSummary"]["Count"]; 53 if (*isCpuPresent == true) 54 { 55 procCount = procCount.get<int>() + 1; 56 } 57 aResp->res.jsonValue["ProcessorSummary"]["Count"] = procCount; 58 } 59 60 /* 61 * @brief Update "ProcessorSummary" "Status" "State" based on 62 * CPU Functional State 63 * 64 * @param[in] aResp Shared pointer for completing asynchronous calls 65 * @param[in] cpuFunctionalState is CPU functional true/false 66 * 67 * @return None. 68 */ 69 void modifyCpuFunctionalState(std::shared_ptr<AsyncResp> aResp, 70 const std::variant<bool> &cpuFunctionalState) 71 { 72 const bool *isCpuFunctional = std::get_if<bool>(&cpuFunctionalState); 73 74 if (isCpuFunctional == nullptr) 75 { 76 messages::internalError(aResp->res); 77 return; 78 } 79 BMCWEB_LOG_DEBUG << "Cpu Functional:" << *isCpuFunctional; 80 81 nlohmann::json &prevProcState = 82 aResp->res.jsonValue["ProcessorSummary"]["Status"]["State"]; 83 84 // Set it as Enabled if atleast one CPU is functional 85 // Update STATE only if previous State was Non_Functional and current CPU is 86 // Functional. 87 if (prevProcState == "Disabled") 88 { 89 if (*isCpuFunctional == true) 90 { 91 aResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] = 92 "Enabled"; 93 } 94 } 95 } 96 97 /* 98 * @brief Retrieves computer system properties over dbus 99 * 100 * @param[in] aResp Shared pointer for completing asynchronous calls 101 * @param[in] name Computer system name from request 102 * 103 * @return None. 104 */ 105 void getComputerSystem(std::shared_ptr<AsyncResp> aResp) 106 { 107 BMCWEB_LOG_DEBUG << "Get available system components."; 108 crow::connections::systemBus->async_method_call( 109 [aResp]( 110 const boost::system::error_code ec, 111 const std::vector<std::pair< 112 std::string, 113 std::vector<std::pair<std::string, std::vector<std::string>>>>> 114 &subtree) { 115 if (ec) 116 { 117 BMCWEB_LOG_DEBUG << "DBUS response error"; 118 messages::internalError(aResp->res); 119 return; 120 } 121 // Iterate over all retrieved ObjectPaths. 122 for (const std::pair<std::string, 123 std::vector<std::pair< 124 std::string, std::vector<std::string>>>> 125 &object : subtree) 126 { 127 const std::string &path = object.first; 128 BMCWEB_LOG_DEBUG << "Got path: " << path; 129 const std::vector< 130 std::pair<std::string, std::vector<std::string>>> 131 &connectionNames = object.second; 132 if (connectionNames.size() < 1) 133 { 134 continue; 135 } 136 137 // This is not system, so check if it's cpu, dimm, UUID or 138 // BiosVer 139 for (const auto &connection : connectionNames) 140 { 141 for (const auto &interfaceName : connection.second) 142 { 143 if (interfaceName == 144 "xyz.openbmc_project.Inventory.Item.Dimm") 145 { 146 BMCWEB_LOG_DEBUG 147 << "Found Dimm, now get its properties."; 148 crow::connections::systemBus->async_method_call( 149 [aResp](const boost::system::error_code ec, 150 const std::vector< 151 std::pair<std::string, VariantType>> 152 &properties) { 153 if (ec) 154 { 155 BMCWEB_LOG_ERROR 156 << "DBUS response error " << ec; 157 messages::internalError(aResp->res); 158 return; 159 } 160 BMCWEB_LOG_DEBUG << "Got " 161 << properties.size() 162 << "Dimm properties."; 163 for (const std::pair<std::string, 164 VariantType> 165 &property : properties) 166 { 167 if (property.first == "MemorySizeInKb") 168 { 169 const uint64_t *value = 170 sdbusplus::message::variant_ns:: 171 get_if<uint64_t>( 172 &property.second); 173 if (value != nullptr) 174 { 175 aResp->res.jsonValue 176 ["TotalSystemMemoryGi" 177 "B"] += 178 *value / (1024 * 1024); 179 aResp->res 180 .jsonValue["MemorySummary"] 181 ["Status"] 182 ["State"] = 183 "Enabled"; 184 } 185 } 186 } 187 }, 188 connection.first, path, 189 "org.freedesktop.DBus.Properties", "GetAll", 190 "xyz.openbmc_project.Inventory.Item.Dimm"); 191 } 192 else if (interfaceName == 193 "xyz.openbmc_project.Inventory.Item.Cpu") 194 { 195 BMCWEB_LOG_DEBUG 196 << "Found Cpu, now get its properties."; 197 198 crow::connections::systemBus->async_method_call( 199 [aResp, service{connection.first}, 200 path(std::move(path))]( 201 const boost::system::error_code ec, 202 const std::vector< 203 std::pair<std::string, VariantType>> 204 &properties) { 205 if (ec) 206 { 207 BMCWEB_LOG_ERROR 208 << "DBUS response error " << ec; 209 messages::internalError(aResp->res); 210 return; 211 } 212 BMCWEB_LOG_DEBUG << "Got " 213 << properties.size() 214 << "Cpu properties."; 215 216 if (properties.size() > 0) 217 { 218 for (const auto &property : properties) 219 { 220 if (property.first == 221 "ProcessorFamily") 222 { 223 const std::string *value = 224 sdbusplus::message:: 225 variant_ns::get_if< 226 std::string>( 227 &property.second); 228 if (value != nullptr) 229 { 230 nlohmann::json 231 &procSummary = 232 aResp->res.jsonValue 233 ["ProcessorSumm" 234 "ary"]; 235 nlohmann::json &procCount = 236 procSummary["Count"]; 237 procCount = 238 procCount.get<int>() + 239 1; 240 procSummary["Status"] 241 ["State"] = 242 "Enabled"; 243 procSummary["Model"] = 244 *value; 245 } 246 } 247 } 248 } 249 else 250 { 251 auto getCpuPresenceState = 252 [aResp]( 253 const boost::system::error_code 254 ec, 255 const std::variant<bool> 256 &cpuPresenceCheck) { 257 if (ec) 258 { 259 BMCWEB_LOG_ERROR 260 << "DBUS response " 261 "error " 262 << ec; 263 return; 264 } 265 modifyCpuPresenceState( 266 aResp, cpuPresenceCheck); 267 }; 268 269 auto getCpuFunctionalState = 270 [aResp]( 271 const boost::system::error_code 272 ec, 273 const std::variant<bool> 274 &cpuFunctionalCheck) { 275 if (ec) 276 { 277 BMCWEB_LOG_ERROR 278 << "DBUS response " 279 "error " 280 << ec; 281 return; 282 } 283 modifyCpuFunctionalState( 284 aResp, cpuFunctionalCheck); 285 }; 286 // Get the Presence of CPU 287 crow::connections::systemBus 288 ->async_method_call( 289 std::move(getCpuPresenceState), 290 service, path, 291 "org.freedesktop.DBus." 292 "Properties", 293 "Get", 294 "xyz.openbmc_project.Inventory." 295 "Item", 296 "Present"); 297 298 // Get the Functional State 299 crow::connections::systemBus 300 ->async_method_call( 301 std::move( 302 getCpuFunctionalState), 303 service, path, 304 "org.freedesktop.DBus." 305 "Properties", 306 "Get", 307 "xyz.openbmc_project.State." 308 "Decorator." 309 "OperationalStatus", 310 "Functional"); 311 312 // Get the MODEL from 313 // xyz.openbmc_project.Inventory.Decorator.Asset 314 // support it later as Model is Empty 315 // currently. 316 } 317 }, 318 connection.first, path, 319 "org.freedesktop.DBus.Properties", "GetAll", 320 "xyz.openbmc_project.Inventory.Item.Cpu"); 321 } 322 else if (interfaceName == 323 "xyz.openbmc_project.Common.UUID") 324 { 325 BMCWEB_LOG_DEBUG 326 << "Found UUID, now get its properties."; 327 crow::connections::systemBus->async_method_call( 328 [aResp](const boost::system::error_code ec, 329 const std::vector< 330 std::pair<std::string, VariantType>> 331 &properties) { 332 if (ec) 333 { 334 BMCWEB_LOG_DEBUG 335 << "DBUS response error " << ec; 336 messages::internalError(aResp->res); 337 return; 338 } 339 BMCWEB_LOG_DEBUG << "Got " 340 << properties.size() 341 << "UUID properties."; 342 for (const std::pair<std::string, 343 VariantType> 344 &property : properties) 345 { 346 if (property.first == "UUID") 347 { 348 const std::string *value = 349 sdbusplus::message::variant_ns:: 350 get_if<std::string>( 351 &property.second); 352 353 if (value != nullptr) 354 { 355 std::string valueStr = *value; 356 if (valueStr.size() == 32) 357 { 358 valueStr.insert(8, 1, '-'); 359 valueStr.insert(13, 1, '-'); 360 valueStr.insert(18, 1, '-'); 361 valueStr.insert(23, 1, '-'); 362 } 363 BMCWEB_LOG_DEBUG << "UUID = " 364 << valueStr; 365 aResp->res.jsonValue["UUID"] = 366 valueStr; 367 } 368 } 369 } 370 }, 371 connection.first, path, 372 "org.freedesktop.DBus.Properties", "GetAll", 373 "xyz.openbmc_project.Common.UUID"); 374 } 375 else if (interfaceName == 376 "xyz.openbmc_project.Inventory.Item.System") 377 { 378 crow::connections::systemBus->async_method_call( 379 [aResp](const boost::system::error_code ec, 380 const std::vector< 381 std::pair<std::string, VariantType>> 382 &propertiesList) { 383 if (ec) 384 { 385 // doesn't have to include this 386 // interface 387 return; 388 } 389 BMCWEB_LOG_DEBUG << "Got " 390 << propertiesList.size() 391 << "properties for system"; 392 for (const std::pair<std::string, 393 VariantType> 394 &property : propertiesList) 395 { 396 const std::string &propertyName = 397 property.first; 398 if ((propertyName == "PartNumber") || 399 (propertyName == "SerialNumber") || 400 (propertyName == "Manufacturer") || 401 (propertyName == "Model")) 402 { 403 const std::string *value = 404 std::get_if<std::string>( 405 &property.second); 406 if (value != nullptr) 407 { 408 aResp->res 409 .jsonValue[propertyName] = 410 *value; 411 } 412 } 413 } 414 aResp->res.jsonValue["Name"] = "system"; 415 aResp->res.jsonValue["Id"] = 416 aResp->res.jsonValue["SerialNumber"]; 417 // Grab the bios version 418 fw_util::getActiveFwVersion( 419 aResp, fw_util::biosPurpose, 420 "BiosVersion"); 421 }, 422 connection.first, path, 423 "org.freedesktop.DBus.Properties", "GetAll", 424 "xyz.openbmc_project.Inventory.Decorator." 425 "Asset"); 426 427 crow::connections::systemBus->async_method_call( 428 [aResp]( 429 const boost::system::error_code ec, 430 const std::variant<std::string> &property) { 431 if (ec) 432 { 433 // doesn't have to include this 434 // interface 435 return; 436 } 437 438 const std::string *value = 439 std::get_if<std::string>(&property); 440 if (value != nullptr) 441 { 442 aResp->res.jsonValue["AssetTag"] = 443 *value; 444 } 445 }, 446 connection.first, path, 447 "org.freedesktop.DBus.Properties", "Get", 448 "xyz.openbmc_project.Inventory.Decorator." 449 "AssetTag", 450 "AssetTag"); 451 } 452 } 453 } 454 } 455 }, 456 "xyz.openbmc_project.ObjectMapper", 457 "/xyz/openbmc_project/object_mapper", 458 "xyz.openbmc_project.ObjectMapper", "GetSubTree", 459 "/xyz/openbmc_project/inventory", int32_t(0), 460 std::array<const char *, 5>{ 461 "xyz.openbmc_project.Inventory.Decorator.Asset", 462 "xyz.openbmc_project.Inventory.Item.Cpu", 463 "xyz.openbmc_project.Inventory.Item.Dimm", 464 "xyz.openbmc_project.Inventory.Item.System", 465 "xyz.openbmc_project.Common.UUID", 466 }); 467 } 468 469 /** 470 * @brief Retrieves identify led group properties over dbus 471 * 472 * @param[in] aResp Shared pointer for generating response message. 473 * @param[in] callback Callback for process retrieved data. 474 * 475 * @return None. 476 */ 477 template <typename CallbackFunc> 478 void getLedGroupIdentify(std::shared_ptr<AsyncResp> aResp, 479 CallbackFunc &&callback) 480 { 481 BMCWEB_LOG_DEBUG << "Get led groups"; 482 crow::connections::systemBus->async_method_call( 483 [aResp, 484 callback{std::move(callback)}](const boost::system::error_code &ec, 485 const ManagedObjectsType &resp) { 486 if (ec) 487 { 488 BMCWEB_LOG_DEBUG << "DBUS response error " << ec; 489 messages::internalError(aResp->res); 490 return; 491 } 492 BMCWEB_LOG_DEBUG << "Got " << resp.size() << "led group objects."; 493 for (const auto &objPath : resp) 494 { 495 const std::string &path = objPath.first; 496 if (path.rfind("enclosure_identify") != std::string::npos) 497 { 498 for (const auto &interface : objPath.second) 499 { 500 if (interface.first == "xyz.openbmc_project.Led.Group") 501 { 502 for (const auto &property : interface.second) 503 { 504 if (property.first == "Asserted") 505 { 506 const bool *asserted = 507 std::get_if<bool>(&property.second); 508 if (nullptr != asserted) 509 { 510 callback(*asserted, aResp); 511 } 512 else 513 { 514 callback(false, aResp); 515 } 516 } 517 } 518 } 519 } 520 } 521 } 522 }, 523 "xyz.openbmc_project.LED.GroupManager", 524 "/xyz/openbmc_project/led/groups", "org.freedesktop.DBus.ObjectManager", 525 "GetManagedObjects"); 526 } 527 528 template <typename CallbackFunc> 529 void getLedIdentify(std::shared_ptr<AsyncResp> aResp, CallbackFunc &&callback) 530 { 531 BMCWEB_LOG_DEBUG << "Get identify led properties"; 532 crow::connections::systemBus->async_method_call( 533 [aResp, 534 callback{std::move(callback)}](const boost::system::error_code ec, 535 const PropertiesType &properties) { 536 if (ec) 537 { 538 BMCWEB_LOG_DEBUG << "DBUS response error " << ec; 539 messages::internalError(aResp->res); 540 return; 541 } 542 BMCWEB_LOG_DEBUG << "Got " << properties.size() 543 << "led properties."; 544 std::string output; 545 for (const auto &property : properties) 546 { 547 if (property.first == "State") 548 { 549 const std::string *s = 550 std::get_if<std::string>(&property.second); 551 if (nullptr != s) 552 { 553 BMCWEB_LOG_DEBUG << "Identify Led State: " << *s; 554 const auto pos = s->rfind('.'); 555 if (pos != std::string::npos) 556 { 557 auto led = s->substr(pos + 1); 558 for (const std::pair<const char *, const char *> 559 &p : 560 std::array< 561 std::pair<const char *, const char *>, 3>{ 562 {{"On", "Lit"}, 563 {"Blink", "Blinking"}, 564 {"Off", "Off"}}}) 565 { 566 if (led == p.first) 567 { 568 output = p.second; 569 } 570 } 571 } 572 } 573 } 574 } 575 callback(output, aResp); 576 }, 577 "xyz.openbmc_project.LED.Controller.identify", 578 "/xyz/openbmc_project/led/physical/identify", 579 "org.freedesktop.DBus.Properties", "GetAll", 580 "xyz.openbmc_project.Led.Physical"); 581 } 582 /** 583 * @brief Retrieves host state properties over dbus 584 * 585 * @param[in] aResp Shared pointer for completing asynchronous calls. 586 * 587 * @return None. 588 */ 589 void getHostState(std::shared_ptr<AsyncResp> aResp) 590 { 591 BMCWEB_LOG_DEBUG << "Get host information."; 592 crow::connections::systemBus->async_method_call( 593 [aResp](const boost::system::error_code ec, 594 const std::variant<std::string> &hostState) { 595 if (ec) 596 { 597 BMCWEB_LOG_DEBUG << "DBUS response error " << ec; 598 messages::internalError(aResp->res); 599 return; 600 } 601 602 const std::string *s = std::get_if<std::string>(&hostState); 603 BMCWEB_LOG_DEBUG << "Host state: " << *s; 604 if (s != nullptr) 605 { 606 // Verify Host State 607 if (*s == "xyz.openbmc_project.State.Host.HostState.Running") 608 { 609 aResp->res.jsonValue["PowerState"] = "On"; 610 aResp->res.jsonValue["Status"]["State"] = "Enabled"; 611 } 612 else 613 { 614 aResp->res.jsonValue["PowerState"] = "Off"; 615 aResp->res.jsonValue["Status"]["State"] = "Disabled"; 616 } 617 } 618 }, 619 "xyz.openbmc_project.State.Host", "/xyz/openbmc_project/state/host0", 620 "org.freedesktop.DBus.Properties", "Get", 621 "xyz.openbmc_project.State.Host", "CurrentHostState"); 622 } 623 624 /** 625 * @brief Traslates boot source DBUS property value to redfish. 626 * 627 * @param[in] dbusSource The boot source in DBUS speak. 628 * 629 * @return Returns as a string, the boot source in Redfish terms. If translation 630 * cannot be done, returns an empty string. 631 */ 632 static std::string dbusToRfBootSource(const std::string &dbusSource) 633 { 634 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Default") 635 { 636 return "None"; 637 } 638 else if (dbusSource == 639 "xyz.openbmc_project.Control.Boot.Source.Sources.Disk") 640 { 641 return "Hdd"; 642 } 643 else if (dbusSource == 644 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia") 645 { 646 return "Cd"; 647 } 648 else if (dbusSource == 649 "xyz.openbmc_project.Control.Boot.Source.Sources.Network") 650 { 651 return "Pxe"; 652 } 653 else if (dbusSource == 654 "xyz.openbmc_project.Control.Boot.Source.Sources.Removable") 655 { 656 return "Usb"; 657 } 658 else 659 { 660 return ""; 661 } 662 } 663 664 /** 665 * @brief Traslates boot mode DBUS property value to redfish. 666 * 667 * @param[in] dbusMode The boot mode in DBUS speak. 668 * 669 * @return Returns as a string, the boot mode in Redfish terms. If translation 670 * cannot be done, returns an empty string. 671 */ 672 static std::string dbusToRfBootMode(const std::string &dbusMode) 673 { 674 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular") 675 { 676 return "None"; 677 } 678 else if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe") 679 { 680 return "Diags"; 681 } 682 else if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup") 683 { 684 return "BiosSetup"; 685 } 686 else 687 { 688 return ""; 689 } 690 } 691 692 /** 693 * @brief Traslates boot source from Redfish to DBUS property value. 694 * 695 * @param[in] rfSource The boot source in Redfish. 696 * 697 * @return Returns as a string, the boot source as expected by DBUS. 698 * If translation cannot be done, returns an empty string. 699 */ 700 static std::string rfToDbusBootSource(const std::string &rfSource) 701 { 702 if (rfSource == "None") 703 { 704 return "xyz.openbmc_project.Control.Boot.Source.Sources.Default"; 705 } 706 else if (rfSource == "Hdd") 707 { 708 return "xyz.openbmc_project.Control.Boot.Source.Sources.Disk"; 709 } 710 else if (rfSource == "Cd") 711 { 712 return "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia"; 713 } 714 else if (rfSource == "Pxe") 715 { 716 return "xyz.openbmc_project.Control.Boot.Source.Sources.Network"; 717 } 718 else if (rfSource == "Usb") 719 { 720 return "xyz.openbmc_project.Control.Boot.Source.Sources.Removable"; 721 } 722 else 723 { 724 return ""; 725 } 726 } 727 728 /** 729 * @brief Traslates boot mode from Redfish to DBUS property value. 730 * 731 * @param[in] rfMode The boot mode in Redfish. 732 * 733 * @return Returns as a string, the boot mode as expected by DBUS. 734 * If translation cannot be done, returns an empty string. 735 */ 736 static std::string rfToDbusBootMode(const std::string &rfMode) 737 { 738 if (rfMode == "None") 739 { 740 return "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular"; 741 } 742 else if (rfMode == "Diags") 743 { 744 return "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe"; 745 } 746 else if (rfMode == "BiosSetup") 747 { 748 return "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup"; 749 } 750 else 751 { 752 return ""; 753 } 754 } 755 756 /** 757 * @brief Retrieves boot mode over DBUS and fills out the response 758 * 759 * @param[in] aResp Shared pointer for generating response message. 760 * @param[in] bootDbusObj The dbus object to query for boot properties. 761 * 762 * @return None. 763 */ 764 static void getBootMode(std::shared_ptr<AsyncResp> aResp, 765 std::string bootDbusObj) 766 { 767 crow::connections::systemBus->async_method_call( 768 [aResp](const boost::system::error_code ec, 769 const std::variant<std::string> &bootMode) { 770 if (ec) 771 { 772 BMCWEB_LOG_DEBUG << "DBUS response error " << ec; 773 messages::internalError(aResp->res); 774 return; 775 } 776 777 const std::string *bootModeStr = 778 std::get_if<std::string>(&bootMode); 779 780 if (!bootModeStr) 781 { 782 messages::internalError(aResp->res); 783 return; 784 } 785 786 BMCWEB_LOG_DEBUG << "Boot mode: " << *bootModeStr; 787 788 // TODO (Santosh): Do we need to support override mode? 789 aResp->res.jsonValue["Boot"]["BootSourceOverrideMode"] = "Legacy"; 790 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget@Redfish." 791 "AllowableValues"] = { 792 "None", "Pxe", "Hdd", "Cd", "Diags", "BiosSetup"}; 793 794 if (*bootModeStr != 795 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular") 796 { 797 auto rfMode = dbusToRfBootMode(*bootModeStr); 798 if (!rfMode.empty()) 799 { 800 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] = 801 rfMode; 802 } 803 } 804 805 // If the BootSourceOverrideTarget is still "None" at the end, 806 // reset the BootSourceOverrideEnabled to indicate that 807 // overrides are disabled 808 if (aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] == 809 "None") 810 { 811 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] = 812 "Disabled"; 813 } 814 }, 815 "xyz.openbmc_project.Settings", bootDbusObj, 816 "org.freedesktop.DBus.Properties", "Get", 817 "xyz.openbmc_project.Control.Boot.Mode", "BootMode"); 818 } 819 820 /** 821 * @brief Retrieves boot source over DBUS 822 * 823 * @param[in] aResp Shared pointer for generating response message. 824 * @param[in] oneTimeEnable Boolean to indicate boot properties are one-time. 825 * 826 * @return None. 827 */ 828 static void getBootSource(std::shared_ptr<AsyncResp> aResp, bool oneTimeEnabled) 829 { 830 std::string bootDbusObj = 831 oneTimeEnabled ? "/xyz/openbmc_project/control/host0/boot/one_time" 832 : "/xyz/openbmc_project/control/host0/boot"; 833 834 BMCWEB_LOG_DEBUG << "Is one time: " << oneTimeEnabled; 835 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] = 836 (oneTimeEnabled) ? "Once" : "Continuous"; 837 838 crow::connections::systemBus->async_method_call( 839 [aResp, bootDbusObj](const boost::system::error_code ec, 840 const std::variant<std::string> &bootSource) { 841 if (ec) 842 { 843 BMCWEB_LOG_DEBUG << "DBUS response error " << ec; 844 messages::internalError(aResp->res); 845 return; 846 } 847 848 const std::string *bootSourceStr = 849 std::get_if<std::string>(&bootSource); 850 851 if (!bootSourceStr) 852 { 853 messages::internalError(aResp->res); 854 return; 855 } 856 BMCWEB_LOG_DEBUG << "Boot source: " << *bootSourceStr; 857 858 auto rfSource = dbusToRfBootSource(*bootSourceStr); 859 if (!rfSource.empty()) 860 { 861 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] = 862 rfSource; 863 } 864 }, 865 "xyz.openbmc_project.Settings", bootDbusObj, 866 "org.freedesktop.DBus.Properties", "Get", 867 "xyz.openbmc_project.Control.Boot.Source", "BootSource"); 868 getBootMode(std::move(aResp), std::move(bootDbusObj)); 869 } 870 871 /** 872 * @brief Retrieves "One time" enabled setting over DBUS and calls function to 873 * get boot source and boot mode. 874 * 875 * @param[in] aResp Shared pointer for generating response message. 876 * 877 * @return None. 878 */ 879 static void getBootProperties(std::shared_ptr<AsyncResp> aResp) 880 { 881 BMCWEB_LOG_DEBUG << "Get boot information."; 882 883 crow::connections::systemBus->async_method_call( 884 [aResp](const boost::system::error_code ec, 885 const sdbusplus::message::variant<bool> &oneTime) { 886 if (ec) 887 { 888 BMCWEB_LOG_DEBUG << "DBUS response error " << ec; 889 messages::internalError(aResp->res); 890 return; 891 } 892 893 const bool *oneTimePtr = std::get_if<bool>(&oneTime); 894 895 if (!oneTimePtr) 896 { 897 messages::internalError(aResp->res); 898 return; 899 } 900 getBootSource(aResp, *oneTimePtr); 901 }, 902 "xyz.openbmc_project.Settings", 903 "/xyz/openbmc_project/control/host0/boot/one_time", 904 "org.freedesktop.DBus.Properties", "Get", 905 "xyz.openbmc_project.Object.Enable", "Enabled"); 906 } 907 908 /** 909 * @brief Sets boot properties into DBUS object(s). 910 * 911 * @param[in] aResp Shared pointer for generating response message. 912 * @param[in] oneTimeEnabled Is "one-time" setting already enabled. 913 * @param[in] bootSource The boot source to set. 914 * @param[in] bootEnable The source override "enable" to set. 915 * 916 * @return None. 917 */ 918 static void setBootModeOrSource(std::shared_ptr<AsyncResp> aResp, 919 bool oneTimeEnabled, 920 std::optional<std::string> bootSource, 921 std::optional<std::string> bootEnable) 922 { 923 if (bootEnable && (bootEnable != "Once") && (bootEnable != "Continuous") && 924 (bootEnable != "Disabled")) 925 { 926 BMCWEB_LOG_DEBUG << "Unsupported value for BootSourceOverrideEnabled: " 927 << *bootEnable; 928 messages::propertyValueNotInList(aResp->res, *bootEnable, 929 "BootSourceOverrideEnabled"); 930 return; 931 } 932 933 bool oneTimeSetting = oneTimeEnabled; 934 // Validate incoming parameters 935 if (bootEnable) 936 { 937 if (*bootEnable == "Once") 938 { 939 oneTimeSetting = true; 940 } 941 else if (*bootEnable == "Continuous") 942 { 943 oneTimeSetting = false; 944 } 945 else if (*bootEnable == "Disabled") 946 { 947 oneTimeSetting = false; 948 } 949 else 950 { 951 952 BMCWEB_LOG_DEBUG << "Unsupported value for " 953 "BootSourceOverrideEnabled: " 954 << *bootEnable; 955 messages::propertyValueNotInList(aResp->res, *bootEnable, 956 "BootSourceOverrideEnabled"); 957 return; 958 } 959 } 960 std::string bootSourceStr; 961 std::string bootModeStr; 962 if (bootSource) 963 { 964 bootSourceStr = rfToDbusBootSource(*bootSource); 965 bootModeStr = rfToDbusBootMode(*bootSource); 966 967 BMCWEB_LOG_DEBUG << "DBUS boot source: " << bootSourceStr; 968 BMCWEB_LOG_DEBUG << "DBUS boot mode: " << bootModeStr; 969 970 if (bootSourceStr.empty() && bootModeStr.empty()) 971 { 972 BMCWEB_LOG_DEBUG << "Invalid property value for " 973 "BootSourceOverrideTarget: " 974 << *bootSource; 975 messages::propertyValueNotInList(aResp->res, *bootSource, 976 "BootSourceTargetOverride"); 977 return; 978 } 979 } 980 const char *bootObj = 981 oneTimeSetting ? "/xyz/openbmc_project/control/host0/boot/one_time" 982 : "/xyz/openbmc_project/control/host0/boot"; 983 // Figure out what properties to set 984 if (bootEnable && (*bootEnable == "Disabled")) 985 { 986 BMCWEB_LOG_DEBUG << "Boot source override will be disabled"; 987 // Request to only turn OFF/ON enabled, if turning enabled OFF, need 988 // to reset the source and mode too. If turning it ON, we only need 989 // to set the enabled property 990 bootSourceStr = 991 "xyz.openbmc_project.Control.Boot.Source.Sources.Default"; 992 bootModeStr = "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular"; 993 } 994 else if (bootSource) 995 { 996 // Source target specified 997 BMCWEB_LOG_DEBUG << "Boot source: " << *bootSource; 998 // Figure out which DBUS interface and property to use 999 bootSourceStr = rfToDbusBootSource(*bootSource); 1000 bootModeStr = rfToDbusBootMode(*bootSource); 1001 1002 BMCWEB_LOG_DEBUG << "DBUS boot source: " << bootSourceStr; 1003 BMCWEB_LOG_DEBUG << "DBUS boot mode: " << bootModeStr; 1004 1005 if (bootSourceStr.empty() && bootModeStr.empty()) 1006 { 1007 BMCWEB_LOG_DEBUG << "Invalid property value for " 1008 "BootSourceOverrideTarget: " 1009 << *bootSource; 1010 messages::propertyValueNotInList(aResp->res, *bootSource, 1011 "BootSourceTargetOverride"); 1012 return; 1013 } 1014 1015 if (!bootSourceStr.empty()) 1016 { 1017 // If setting to anything other than default, also reset boot 1018 // mode property 1019 if (bootSourceStr != 1020 "xyz.openbmc_project.Control.Boot.Source.Sources.Default") 1021 { 1022 bootModeStr = 1023 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular"; 1024 } 1025 } 1026 else // if (!bootModeStr.empty()) 1027 { 1028 // If setting to anything other than default, also reset boot 1029 // source property 1030 if (bootModeStr != 1031 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular") 1032 { 1033 bootSourceStr = 1034 "xyz.openbmc_project.Control.Boot.Source.Sources.Default"; 1035 } 1036 } 1037 } 1038 if (!bootSourceStr.empty()) 1039 { 1040 crow::connections::systemBus->async_method_call( 1041 [aResp](const boost::system::error_code ec) { 1042 if (ec) 1043 { 1044 BMCWEB_LOG_DEBUG << "DBUS response error " << ec; 1045 messages::internalError(aResp->res); 1046 return; 1047 } 1048 BMCWEB_LOG_DEBUG << "Boot source update done."; 1049 }, 1050 "xyz.openbmc_project.Settings", bootObj, 1051 "org.freedesktop.DBus.Properties", "Set", 1052 "xyz.openbmc_project.Control.Boot.Source", "BootSource", 1053 std::variant<std::string>(bootSourceStr)); 1054 } 1055 if (!bootModeStr.empty()) 1056 { 1057 crow::connections::systemBus->async_method_call( 1058 [aResp](const boost::system::error_code ec) { 1059 if (ec) 1060 { 1061 BMCWEB_LOG_DEBUG << "DBUS response error " << ec; 1062 messages::internalError(aResp->res); 1063 return; 1064 } 1065 BMCWEB_LOG_DEBUG << "Boot mode update done."; 1066 }, 1067 "xyz.openbmc_project.Settings", bootObj, 1068 "org.freedesktop.DBus.Properties", "Set", 1069 "xyz.openbmc_project.Control.Boot.Mode", "BootMode", 1070 std::variant<std::string>(bootModeStr)); 1071 } 1072 crow::connections::systemBus->async_method_call( 1073 [aResp{std::move(aResp)}](const boost::system::error_code ec) { 1074 if (ec) 1075 { 1076 BMCWEB_LOG_DEBUG << "DBUS response error " << ec; 1077 messages::internalError(aResp->res); 1078 return; 1079 } 1080 BMCWEB_LOG_DEBUG << "Boot enable update done."; 1081 }, 1082 "xyz.openbmc_project.Settings", 1083 "/xyz/openbmc_project/control/host0/boot/one_time", 1084 "org.freedesktop.DBus.Properties", "Set", 1085 "xyz.openbmc_project.Object.Enable", "Enabled", 1086 std::variant<bool>(oneTimeSetting)); 1087 } 1088 1089 /** 1090 * @brief Retrieves "One time" enabled setting over DBUS and calls function to 1091 * set boot source/boot mode properties. 1092 * 1093 * @param[in] aResp Shared pointer for generating response message. 1094 * @param[in] bootSource The boot source from incoming RF request. 1095 * @param[in] bootEnable The boot override enable from incoming RF request. 1096 * 1097 * @return None. 1098 */ 1099 static void setBootProperties(std::shared_ptr<AsyncResp> aResp, 1100 std::optional<std::string> bootSource, 1101 std::optional<std::string> bootEnable) 1102 { 1103 BMCWEB_LOG_DEBUG << "Set boot information."; 1104 1105 crow::connections::systemBus->async_method_call( 1106 [aResp{std::move(aResp)}, bootSource{std::move(bootSource)}, 1107 bootEnable{std::move(bootEnable)}]( 1108 const boost::system::error_code ec, 1109 const sdbusplus::message::variant<bool> &oneTime) { 1110 if (ec) 1111 { 1112 BMCWEB_LOG_DEBUG << "DBUS response error " << ec; 1113 messages::internalError(aResp->res); 1114 return; 1115 } 1116 1117 const bool *oneTimePtr = std::get_if<bool>(&oneTime); 1118 1119 if (!oneTimePtr) 1120 { 1121 messages::internalError(aResp->res); 1122 return; 1123 } 1124 1125 BMCWEB_LOG_DEBUG << "Got one time: " << *oneTimePtr; 1126 1127 setBootModeOrSource(aResp, *oneTimePtr, std::move(bootSource), 1128 std::move(bootEnable)); 1129 }, 1130 "xyz.openbmc_project.Settings", 1131 "/xyz/openbmc_project/control/host0/boot/one_time", 1132 "org.freedesktop.DBus.Properties", "Get", 1133 "xyz.openbmc_project.Object.Enable", "Enabled"); 1134 } 1135 1136 /** 1137 * SystemsCollection derived class for delivering ComputerSystems Collection 1138 * Schema 1139 */ 1140 class SystemsCollection : public Node 1141 { 1142 public: 1143 SystemsCollection(CrowApp &app) : Node(app, "/redfish/v1/Systems/") 1144 { 1145 entityPrivileges = { 1146 {boost::beast::http::verb::get, {{"Login"}}}, 1147 {boost::beast::http::verb::head, {{"Login"}}}, 1148 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 1149 {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 1150 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 1151 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 1152 } 1153 1154 private: 1155 void doGet(crow::Response &res, const crow::Request &req, 1156 const std::vector<std::string> ¶ms) override 1157 { 1158 res.jsonValue["@odata.type"] = 1159 "#ComputerSystemCollection.ComputerSystemCollection"; 1160 res.jsonValue["@odata.id"] = "/redfish/v1/Systems"; 1161 res.jsonValue["@odata.context"] = 1162 "/redfish/v1/" 1163 "$metadata#ComputerSystemCollection.ComputerSystemCollection"; 1164 res.jsonValue["Name"] = "Computer System Collection"; 1165 res.jsonValue["Members"] = { 1166 {{"@odata.id", "/redfish/v1/Systems/system"}}}; 1167 res.jsonValue["Members@odata.count"] = 1; 1168 res.end(); 1169 } 1170 }; 1171 1172 /** 1173 * SystemActionsReset class supports handle POST method for Reset action. 1174 * The class retrieves and sends data directly to D-Bus. 1175 */ 1176 class SystemActionsReset : public Node 1177 { 1178 public: 1179 SystemActionsReset(CrowApp &app) : 1180 Node(app, "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset/") 1181 { 1182 entityPrivileges = { 1183 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 1184 } 1185 1186 private: 1187 /** 1188 * Function handles POST method request. 1189 * Analyzes POST body message before sends Reset request data to D-Bus. 1190 */ 1191 void doPost(crow::Response &res, const crow::Request &req, 1192 const std::vector<std::string> ¶ms) override 1193 { 1194 auto asyncResp = std::make_shared<AsyncResp>(res); 1195 1196 std::string resetType; 1197 if (!json_util::readJson(req, res, "ResetType", resetType)) 1198 { 1199 return; 1200 } 1201 1202 // Get the command and host vs. chassis 1203 std::string command; 1204 bool hostCommand; 1205 if (resetType == "On") 1206 { 1207 command = "xyz.openbmc_project.State.Host.Transition.On"; 1208 hostCommand = true; 1209 } 1210 else if (resetType == "ForceOff") 1211 { 1212 command = "xyz.openbmc_project.State.Chassis.Transition.Off"; 1213 hostCommand = false; 1214 } 1215 else if (resetType == "ForceOn") 1216 { 1217 command = "xyz.openbmc_project.State.Host.Transition.On"; 1218 hostCommand = true; 1219 } 1220 else if (resetType == "ForceRestart") 1221 { 1222 command = "xyz.openbmc_project.State.Chassis.Transition.Reset"; 1223 hostCommand = false; 1224 } 1225 else if (resetType == "GracefulShutdown") 1226 { 1227 command = "xyz.openbmc_project.State.Host.Transition.Off"; 1228 hostCommand = true; 1229 } 1230 else if (resetType == "GracefulRestart") 1231 { 1232 command = "xyz.openbmc_project.State.Host.Transition.Reboot"; 1233 hostCommand = true; 1234 } 1235 else if (resetType == "PowerCycle") 1236 { 1237 command = "xyz.openbmc_project.State.Chassis.Transition.PowerCycle"; 1238 hostCommand = false; 1239 } 1240 else if (resetType == "Nmi") 1241 { 1242 doNMI(asyncResp); 1243 return; 1244 } 1245 else 1246 { 1247 messages::actionParameterUnknown(res, "Reset", resetType); 1248 return; 1249 } 1250 1251 if (hostCommand) 1252 { 1253 crow::connections::systemBus->async_method_call( 1254 [asyncResp, resetType](const boost::system::error_code ec) { 1255 if (ec) 1256 { 1257 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; 1258 if (ec.value() == boost::asio::error::invalid_argument) 1259 { 1260 messages::actionParameterNotSupported( 1261 asyncResp->res, resetType, "Reset"); 1262 } 1263 else 1264 { 1265 messages::internalError(asyncResp->res); 1266 } 1267 return; 1268 } 1269 messages::success(asyncResp->res); 1270 }, 1271 "xyz.openbmc_project.State.Host", 1272 "/xyz/openbmc_project/state/host0", 1273 "org.freedesktop.DBus.Properties", "Set", 1274 "xyz.openbmc_project.State.Host", "RequestedHostTransition", 1275 std::variant<std::string>{command}); 1276 } 1277 else 1278 { 1279 crow::connections::systemBus->async_method_call( 1280 [asyncResp, resetType](const boost::system::error_code ec) { 1281 if (ec) 1282 { 1283 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; 1284 if (ec.value() == boost::asio::error::invalid_argument) 1285 { 1286 messages::actionParameterNotSupported( 1287 asyncResp->res, resetType, "Reset"); 1288 } 1289 else 1290 { 1291 messages::internalError(asyncResp->res); 1292 } 1293 return; 1294 } 1295 messages::success(asyncResp->res); 1296 }, 1297 "xyz.openbmc_project.State.Chassis", 1298 "/xyz/openbmc_project/state/chassis0", 1299 "org.freedesktop.DBus.Properties", "Set", 1300 "xyz.openbmc_project.State.Chassis", "RequestedPowerTransition", 1301 std::variant<std::string>{command}); 1302 } 1303 } 1304 /** 1305 * Function transceives data with dbus directly. 1306 */ 1307 void doNMI(const std::shared_ptr<AsyncResp> &asyncResp) 1308 { 1309 constexpr char const *serviceName = 1310 "xyz.openbmc_project.Control.Host.NMI"; 1311 constexpr char const *objectPath = 1312 "/xyz/openbmc_project/control/host0/nmi"; 1313 constexpr char const *interfaceName = 1314 "xyz.openbmc_project.Control.Host.NMI"; 1315 constexpr char const *method = "NMI"; 1316 1317 crow::connections::systemBus->async_method_call( 1318 [asyncResp](const boost::system::error_code ec) { 1319 if (ec) 1320 { 1321 BMCWEB_LOG_ERROR << " Bad D-Bus request error: " << ec; 1322 messages::internalError(asyncResp->res); 1323 return; 1324 } 1325 messages::success(asyncResp->res); 1326 }, 1327 serviceName, objectPath, interfaceName, method); 1328 } 1329 }; 1330 1331 /** 1332 * Systems derived class for delivering Computer Systems Schema. 1333 */ 1334 class Systems : public Node 1335 { 1336 public: 1337 /* 1338 * Default Constructor 1339 */ 1340 Systems(CrowApp &app) : Node(app, "/redfish/v1/Systems/system/") 1341 { 1342 entityPrivileges = { 1343 {boost::beast::http::verb::get, {{"Login"}}}, 1344 {boost::beast::http::verb::head, {{"Login"}}}, 1345 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 1346 {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 1347 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 1348 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 1349 } 1350 1351 private: 1352 /** 1353 * Functions triggers appropriate requests on DBus 1354 */ 1355 void doGet(crow::Response &res, const crow::Request &req, 1356 const std::vector<std::string> ¶ms) override 1357 { 1358 res.jsonValue["@odata.type"] = "#ComputerSystem.v1_6_0.ComputerSystem"; 1359 res.jsonValue["@odata.context"] = 1360 "/redfish/v1/$metadata#ComputerSystem.ComputerSystem"; 1361 res.jsonValue["Name"] = "Computer System"; 1362 res.jsonValue["Id"] = "system"; 1363 res.jsonValue["SystemType"] = "Physical"; 1364 res.jsonValue["Description"] = "Computer System"; 1365 res.jsonValue["ProcessorSummary"]["Count"] = 0; 1366 res.jsonValue["ProcessorSummary"]["Status"]["State"] = "Disabled"; 1367 res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] = int(0); 1368 res.jsonValue["MemorySummary"]["Status"]["State"] = "Disabled"; 1369 res.jsonValue["@odata.id"] = "/redfish/v1/Systems/system"; 1370 1371 res.jsonValue["Processors"] = { 1372 {"@odata.id", "/redfish/v1/Systems/system/Processors"}}; 1373 res.jsonValue["Memory"] = { 1374 {"@odata.id", "/redfish/v1/Systems/system/Memory"}}; 1375 1376 // TODO Need to support ForceRestart. 1377 res.jsonValue["Actions"]["#ComputerSystem.Reset"] = { 1378 {"target", 1379 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset"}, 1380 {"ResetType@Redfish.AllowableValues", 1381 {"On", "ForceOff", "ForceOn", "ForceRestart", "GracefulRestart", 1382 "GracefulShutdown", "PowerCycle", "Nmi"}}}; 1383 1384 res.jsonValue["LogServices"] = { 1385 {"@odata.id", "/redfish/v1/Systems/system/LogServices"}}; 1386 1387 res.jsonValue["Links"]["ManagedBy"] = { 1388 {{"@odata.id", "/redfish/v1/Managers/bmc"}}}; 1389 1390 res.jsonValue["Status"] = { 1391 {"Health", "OK"}, 1392 {"State", "Enabled"}, 1393 }; 1394 auto asyncResp = std::make_shared<AsyncResp>(res); 1395 1396 constexpr const std::array<const char *, 2> inventoryForSystems = { 1397 "xyz.openbmc_project.Inventory.Item.Dimm", 1398 "xyz.openbmc_project.Inventory.Item.Cpu"}; 1399 1400 auto health = std::make_shared<HealthPopulate>(asyncResp); 1401 crow::connections::systemBus->async_method_call( 1402 [health](const boost::system::error_code ec, 1403 std::vector<std::string> &resp) { 1404 if (ec) 1405 { 1406 // no inventory 1407 return; 1408 } 1409 1410 health->inventory = std::move(resp); 1411 }, 1412 "xyz.openbmc_project.ObjectMapper", 1413 "/xyz/openbmc_project/object_mapper", 1414 "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", "/", 1415 int32_t(0), inventoryForSystems); 1416 1417 health->populate(); 1418 1419 getMainChassisId(asyncResp, [](const std::string &chassisId, 1420 std::shared_ptr<AsyncResp> aRsp) { 1421 aRsp->res.jsonValue["Links"]["Chassis"] = { 1422 {{"@odata.id", "/redfish/v1/Chassis/" + chassisId}}}; 1423 }); 1424 getLedGroupIdentify( 1425 asyncResp, 1426 [](const bool &asserted, const std::shared_ptr<AsyncResp> aRsp) { 1427 if (asserted) 1428 { 1429 // If led group is asserted, then another call is needed to 1430 // get led status 1431 getLedIdentify( 1432 aRsp, [](const std::string &ledStatus, 1433 const std::shared_ptr<AsyncResp> aRsp) { 1434 if (!ledStatus.empty()) 1435 { 1436 aRsp->res.jsonValue["IndicatorLED"] = ledStatus; 1437 } 1438 }); 1439 } 1440 else 1441 { 1442 aRsp->res.jsonValue["IndicatorLED"] = "Off"; 1443 } 1444 }); 1445 getComputerSystem(asyncResp); 1446 getHostState(asyncResp); 1447 getBootProperties(asyncResp); 1448 getPCIeDeviceList(asyncResp); 1449 } 1450 1451 void doPatch(crow::Response &res, const crow::Request &req, 1452 const std::vector<std::string> ¶ms) override 1453 { 1454 std::optional<std::string> indicatorLed; 1455 std::optional<nlohmann::json> bootProps; 1456 if (!json_util::readJson(req, res, "IndicatorLED", indicatorLed, "Boot", 1457 bootProps)) 1458 { 1459 return; 1460 } 1461 1462 auto asyncResp = std::make_shared<AsyncResp>(res); 1463 asyncResp->res.result(boost::beast::http::status::no_content); 1464 1465 if (bootProps) 1466 { 1467 std::optional<std::string> bootSource; 1468 std::optional<std::string> bootEnable; 1469 1470 if (!json_util::readJson(*bootProps, asyncResp->res, 1471 "BootSourceOverrideTarget", bootSource, 1472 "BootSourceOverrideEnabled", bootEnable)) 1473 { 1474 return; 1475 } 1476 setBootProperties(asyncResp, std::move(bootSource), 1477 std::move(bootEnable)); 1478 } 1479 if (indicatorLed) 1480 { 1481 std::string dbusLedState; 1482 if (*indicatorLed == "Lit") 1483 { 1484 dbusLedState = "xyz.openbmc_project.Led.Physical.Action.On"; 1485 } 1486 else if (*indicatorLed == "Blinking") 1487 { 1488 dbusLedState = "xyz.openbmc_project.Led.Physical.Action.Blink"; 1489 } 1490 else if (*indicatorLed == "Off") 1491 { 1492 dbusLedState = "xyz.openbmc_project.Led.Physical.Action.Off"; 1493 } 1494 else 1495 { 1496 messages::propertyValueNotInList(res, *indicatorLed, 1497 "IndicatorLED"); 1498 return; 1499 } 1500 1501 // Update led group 1502 BMCWEB_LOG_DEBUG << "Update led group."; 1503 crow::connections::systemBus->async_method_call( 1504 [asyncResp](const boost::system::error_code ec) { 1505 if (ec) 1506 { 1507 BMCWEB_LOG_DEBUG << "DBUS response error " << ec; 1508 messages::internalError(asyncResp->res); 1509 return; 1510 } 1511 BMCWEB_LOG_DEBUG << "Led group update done."; 1512 }, 1513 "xyz.openbmc_project.LED.GroupManager", 1514 "/xyz/openbmc_project/led/groups/enclosure_identify", 1515 "org.freedesktop.DBus.Properties", "Set", 1516 "xyz.openbmc_project.Led.Group", "Asserted", 1517 std::variant<bool>( 1518 (dbusLedState == 1519 "xyz.openbmc_project.Led.Physical.Action.Off" 1520 ? false 1521 : true))); 1522 // Update identify led status 1523 BMCWEB_LOG_DEBUG << "Update led SoftwareInventoryCollection."; 1524 crow::connections::systemBus->async_method_call( 1525 [asyncResp{std::move(asyncResp)}, 1526 indicatorLed{std::move(*indicatorLed)}]( 1527 const boost::system::error_code ec) { 1528 if (ec) 1529 { 1530 BMCWEB_LOG_DEBUG << "DBUS response error " << ec; 1531 messages::internalError(asyncResp->res); 1532 return; 1533 } 1534 BMCWEB_LOG_DEBUG << "Led state update done."; 1535 }, 1536 "xyz.openbmc_project.LED.Controller.identify", 1537 "/xyz/openbmc_project/led/physical/identify", 1538 "org.freedesktop.DBus.Properties", "Set", 1539 "xyz.openbmc_project.Led.Physical", "State", 1540 std::variant<std::string>(dbusLedState)); 1541 } 1542 } 1543 }; 1544 } // namespace redfish 1545