xref: /openbmc/pldm/oem/meta/libpldmresponder/file_io_type_power_control.cpp (revision 71aa71376792340ebc5a5722c08213c6792e08de)
1 #include "file_io_type_power_control.hpp"
2 
3 #include <phosphor-logging/lg2.hpp>
4 #include <xyz/openbmc_project/State/Host/client.hpp>
5 
6 PHOSPHOR_LOG2_USING;
7 
8 using HostState = sdbusplus::common::xyz::openbmc_project::state::Host;
9 
10 namespace pldm::responder::oem_meta
11 {
12 
13 uint8_t power_control_len = 1;
14 enum class POWER_CONTROL_OPTION
15 {
16     SLED_CYCLE = 0x00,
17     SLOT_12V_CYCLE = 0x01,
18     SLOT_DC_CYCLE = 0x02,
19     NIC0_POWER_CYCLE = 0x03,
20     NIC1_POWER_CYCLE = 0x04,
21     NIC2_POWER_CYCLE = 0x05,
22     NIC3_POWER_CYCLE = 0x06,
23 };
24 
write(const message & data)25 int PowerControlHandler::write(const message& data)
26 {
27     if (data.size() != power_control_len)
28     {
29         error(
30             "Invalid incoming data for controlling power, data size {SIZE} bytes",
31             "SIZE", data.size());
32         return PLDM_ERROR;
33     }
34 
35     std::string slotNum = pldm::oem_meta::getSlotNumberStringByTID(tid);
36     uint8_t option = data[0];
37     pldm::utils::DBusMapping dbusMapping;
38     dbusMapping.propertyType = "string";
39     std::string property{};
40     switch (option)
41     {
42         case static_cast<uint8_t>(POWER_CONTROL_OPTION::SLED_CYCLE):
43             dbusMapping.objectPath =
44                 std::string("/xyz/openbmc_project/state/chassis0");
45             dbusMapping.interface = "xyz.openbmc_project.State.Chassis";
46             dbusMapping.propertyName = "RequestedPowerTransition";
47             property =
48                 "xyz.openbmc_project.State.Chassis.Transition.PowerCycle";
49             break;
50         case static_cast<uint8_t>(POWER_CONTROL_OPTION::SLOT_12V_CYCLE):
51             dbusMapping.objectPath =
52                 std::string("/xyz/openbmc_project/state/chassis") + slotNum;
53             dbusMapping.interface = "xyz.openbmc_project.State.Chassis";
54             dbusMapping.propertyName = "RequestedPowerTransition";
55             property =
56                 "xyz.openbmc_project.State.Chassis.Transition.PowerCycle";
57             break;
58         case static_cast<uint8_t>(POWER_CONTROL_OPTION::SLOT_DC_CYCLE):
59             dbusMapping.objectPath =
60                 std::format("{}/{}{}", HostState::namespace_path::value,
61                             HostState::namespace_path::host, slotNum);
62             dbusMapping.interface = HostState::interface;
63             dbusMapping.propertyName =
64                 HostState::property_names::requested_host_transition;
65             property = "xyz.openbmc_project.State.Host.Transition.Reboot";
66             break;
67         case static_cast<uint8_t>(POWER_CONTROL_OPTION::NIC0_POWER_CYCLE):
68         case static_cast<uint8_t>(POWER_CONTROL_OPTION::NIC1_POWER_CYCLE):
69         case static_cast<uint8_t>(POWER_CONTROL_OPTION::NIC2_POWER_CYCLE):
70         case static_cast<uint8_t>(POWER_CONTROL_OPTION::NIC3_POWER_CYCLE):
71         {
72             static constexpr auto systemd_busname = "org.freedesktop.systemd1";
73             static constexpr auto systemd_path = "/org/freedesktop/systemd1";
74             static constexpr auto systemd_interface =
75                 "org.freedesktop.systemd1.Manager";
76             uint8_t nic_index =
77                 option -
78                 static_cast<uint8_t>(POWER_CONTROL_OPTION::NIC0_POWER_CYCLE);
79             try
80             {
81                 auto& bus = pldm::utils::DBusHandler::getBus();
82                 auto method =
83                     bus.new_method_call(systemd_busname, systemd_path,
84                                         systemd_interface, "StartUnit");
85                 method.append("nic-powercycle@" + std::to_string(nic_index) +
86                                   ".service",
87                               "replace");
88                 bus.call_noreply(method);
89             }
90             catch (const std::exception& e)
91             {
92                 error("Control NIC{NUM} power fail. ERROR={ERROR}", "NUM",
93                       nic_index, "ERROR", e);
94                 return PLDM_ERROR;
95             }
96             return PLDM_SUCCESS;
97         }
98         default:
99             error("Get invalid power control option, option={OPTION}", "OPTION",
100                   option);
101             return PLDM_ERROR;
102     }
103 
104     try
105     {
106         dBusIntf->setDbusProperty(dbusMapping, property);
107     }
108     catch (const sdbusplus::exception_t& e)
109     {
110         error("Failed to execute Dbus call with error code {ERROR}", "ERROR",
111               e);
112         return PLDM_ERROR;
113     }
114     catch (const std::exception& e)
115     {
116         error("Failed to control power with error code {ERROR}", "ERROR", e);
117         return PLDM_ERROR;
118     }
119 
120     return PLDM_SUCCESS;
121 }
122 
123 } // namespace pldm::responder::oem_meta
124