| John Wedig | dd9478d | 2023-12-08 14:44:53 -0800 | [diff] [blame] | 1 |  | 
 | 2 | #include <boost/asio/io_context.hpp> | 
 | 3 | #include <boost/asio/steady_timer.hpp> | 
 | 4 | #include <phosphor-logging/lg2.hpp> | 
 | 5 | #include <sdbusplus/asio/connection.hpp> | 
 | 6 | #include <sdbusplus/asio/property.hpp> | 
 | 7 | #include <sdbusplus/bus.hpp> | 
 | 8 | #include <sdbusplus/bus/match.hpp> | 
 | 9 |  | 
 | 10 | const constexpr char* OperatingSystemService = | 
 | 11 |     "xyz.openbmc_project.State.OperatingSystem"; | 
 | 12 | const constexpr char* OperatingSystemPath = "/xyz/openbmc_project/state/os"; | 
 | 13 | const constexpr char* OperatingSystemStatusInterface = | 
 | 14 |     "xyz.openbmc_project.State.OperatingSystem.Status"; | 
 | 15 | const constexpr char* OperatingSystemStateProperty = "OperatingSystemState"; | 
 | 16 | const constexpr char* OperatingSystemStateStandby = | 
 | 17 |     "xyz.openbmc_project.State.OperatingSystem.Status.OSStatus.Standby"; | 
 | 18 | const constexpr char* OperatingSystemStateInactive = | 
 | 19 |     "xyz.openbmc_project.State.OperatingSystem.Status.OSStatus.Inactive"; | 
 | 20 | const constexpr char* BareMetalActiveTarget = "gbmc-bare-metal-active.target"; | 
 | 21 |  | 
 | 22 | const constexpr char* SystemdService = "org.freedesktop.systemd1"; | 
 | 23 | const constexpr char* SystemdManagerObject = "/org/freedesktop/systemd1"; | 
 | 24 | const constexpr char* SystemdManagerInterface = | 
 | 25 |     "org.freedesktop.systemd1.Manager"; | 
 | 26 |  | 
 | 27 | void setUnitStatus(sdbusplus::asio::connection& bus, bool status) | 
 | 28 | { | 
 | 29 |     auto method = bus.new_method_call(SystemdService, SystemdManagerObject, | 
 | 30 |                                       SystemdManagerInterface, | 
 | 31 |                                       status ? "StartUnit" : "StopUnit"); | 
 | 32 |     method.append(BareMetalActiveTarget, "replace"); | 
 | 33 |  | 
 | 34 |     bus.call(method); | 
 | 35 | } | 
 | 36 |  | 
| John Wedig | dd9478d | 2023-12-08 14:44:53 -0800 | [diff] [blame] | 37 | void checkPostComplete(sdbusplus::asio::connection& bus, | 
 | 38 |                        const std::string& state, bool action) | 
 | 39 | { | 
 | 40 |     sdbusplus::asio::getProperty<std::string>( | 
 | 41 |         bus, OperatingSystemService, OperatingSystemPath, | 
 | 42 |         OperatingSystemStatusInterface, OperatingSystemStateProperty, | 
| Yuxiao Zhang | 8800984 | 2024-01-04 14:52:38 -0800 | [diff] [blame] | 43 |         [&, state, action](const boost::system::error_code& ec, | 
 | 44 |                            const std::string& postCompleteState) { | 
| Patrick Williams | c66ebc3 | 2024-08-16 15:21:56 -0400 | [diff] [blame] | 45 |             if (ec) | 
 | 46 |             { | 
 | 47 |                 lg2::error("Error when checking Post Complete GPIO state"); | 
 | 48 |                 return; | 
 | 49 |             } | 
| John Wedig | dd9478d | 2023-12-08 14:44:53 -0800 | [diff] [blame] | 50 |  | 
| Patrick Williams | c66ebc3 | 2024-08-16 15:21:56 -0400 | [diff] [blame] | 51 |             lg2::info("Post Complete state is {STATE}", "STATE", | 
 | 52 |                       postCompleteState); | 
| Yuxiao Zhang | 8800984 | 2024-01-04 14:52:38 -0800 | [diff] [blame] | 53 |  | 
| Patrick Williams | c66ebc3 | 2024-08-16 15:21:56 -0400 | [diff] [blame] | 54 |             /* | 
 | 55 |              * If state is Standby, enable the bare-metal-active systemd | 
 | 56 |              * target. | 
 | 57 |              * If state is Inactive, no-op cause IPMI is enabled by default. | 
 | 58 |              */ | 
 | 59 |             if (postCompleteState == state) | 
 | 60 |             { | 
 | 61 |                 setUnitStatus(bus, action); | 
 | 62 |             } | 
 | 63 |         }); | 
| John Wedig | dd9478d | 2023-12-08 14:44:53 -0800 | [diff] [blame] | 64 | } | 
 | 65 |  | 
 | 66 | /* This only gets called once on startup. */ | 
 | 67 | void checkPostCompleteStartup(sdbusplus::asio::connection& bus) | 
 | 68 | { | 
 | 69 |     checkPostComplete(bus, OperatingSystemStateStandby, true); | 
 | 70 | } | 
 | 71 |  | 
 | 72 | /* Gets called when a GPIO state change is detected. */ | 
 | 73 | void checkPostCompleteEvent(sdbusplus::asio::connection& bus) | 
 | 74 | { | 
 | 75 |     checkPostComplete(bus, OperatingSystemStateInactive, false); | 
 | 76 | } | 
 | 77 |  | 
 | 78 | int main() | 
 | 79 | { | 
 | 80 |     try | 
 | 81 |     { | 
 | 82 |         /* Setup connection to dbus. */ | 
 | 83 |         boost::asio::io_context io; | 
 | 84 |         auto conn = sdbusplus::asio::connection(io); | 
 | 85 |  | 
 | 86 |         /* check IPMI status at startup */ | 
 | 87 |         checkPostCompleteStartup(conn); | 
 | 88 |         /* | 
 | 89 |          * Set up an event handler to process Post Complete GPIO state changes. | 
 | 90 |          */ | 
 | 91 |         boost::asio::steady_timer filterTimer(io); | 
 | 92 |  | 
 | 93 |         auto match = std::make_unique<sdbusplus::bus::match_t>( | 
 | 94 |             static_cast<sdbusplus::bus_t&>(conn), | 
 | 95 |             std::format( | 
 | 96 |                 "type='signal',member='PropertiesChanged',path_namespace='" | 
 | 97 |                 "/xyz/openbmc_project/state/os',arg0namespace='{}'", | 
 | 98 |                 OperatingSystemStatusInterface), | 
 | 99 |             [&](sdbusplus::message_t& message) { | 
| Patrick Williams | c66ebc3 | 2024-08-16 15:21:56 -0400 | [diff] [blame] | 100 |                 if (message.is_method_error()) | 
| John Wedig | dd9478d | 2023-12-08 14:44:53 -0800 | [diff] [blame] | 101 |                 { | 
| Patrick Williams | c66ebc3 | 2024-08-16 15:21:56 -0400 | [diff] [blame] | 102 |                     lg2::error("eventHandler callback method error"); | 
| John Wedig | dd9478d | 2023-12-08 14:44:53 -0800 | [diff] [blame] | 103 |                     return; | 
 | 104 |                 } | 
 | 105 |  | 
 | 106 |                 /* | 
| Patrick Williams | c66ebc3 | 2024-08-16 15:21:56 -0400 | [diff] [blame] | 107 |                  * This implicitly cancels the timer, if it's already pending. | 
 | 108 |                  * If there's a burst of events within a short period, we want | 
 | 109 |                  * to handle them all at once. So, we will wait this long for no | 
 | 110 |                  * more events to occur, before processing them. | 
| John Wedig | dd9478d | 2023-12-08 14:44:53 -0800 | [diff] [blame] | 111 |                  */ | 
| Patrick Williams | c66ebc3 | 2024-08-16 15:21:56 -0400 | [diff] [blame] | 112 |                 filterTimer.expires_from_now(std::chrono::seconds(1)); | 
 | 113 |  | 
 | 114 |                 filterTimer.async_wait( | 
 | 115 |                     [&](const boost::system::error_code& ec) { | 
 | 116 |                         if (ec == boost::asio::error::operation_aborted) | 
 | 117 |                         { | 
 | 118 |                             /* we were canceled */ | 
 | 119 |                             return; | 
 | 120 |                         } | 
 | 121 |                         if (ec) | 
 | 122 |                         { | 
 | 123 |                             lg2::error("timer error"); | 
 | 124 |                             return; | 
 | 125 |                         } | 
 | 126 |  | 
 | 127 |                         /* | 
 | 128 |                          * Stop the bare metal active target if the post | 
 | 129 |                          * complete got deasserted. | 
 | 130 |                          */ | 
 | 131 |                         checkPostCompleteEvent(conn); | 
 | 132 |                     }); | 
| John Wedig | dd9478d | 2023-12-08 14:44:53 -0800 | [diff] [blame] | 133 |             }); | 
| John Wedig | dd9478d | 2023-12-08 14:44:53 -0800 | [diff] [blame] | 134 |  | 
 | 135 |         io.run(); | 
 | 136 |         return 0; | 
 | 137 |     } | 
 | 138 |     catch (const std::exception& e) | 
 | 139 |     { | 
 | 140 |         lg2::error(e.what(), "REDFISH_MESSAGE_ID", | 
 | 141 |                    std::string("OpenBMC.1.0.ServiceException")); | 
 | 142 |  | 
 | 143 |         return 2; | 
 | 144 |     } | 
 | 145 |     return 1; | 
 | 146 | } |