1 #include <unistd.h> 2 3 #include <phosphor-logging/elog.hpp> 4 #include <phosphor-logging/log.hpp> 5 #include <sdbusplus/bus.hpp> 6 #include <sdbusplus/exception.hpp> 7 #include <xyz/openbmc_project/Logging/Create/server.hpp> 8 #include <xyz/openbmc_project/Logging/Entry/server.hpp> 9 10 #include <cstdlib> 11 #include <string> 12 13 constexpr auto HOST_STATE_SVC = "xyz.openbmc_project.State.Host"; 14 constexpr auto HOST_STATE_PATH = "/xyz/openbmc_project/state/host0"; 15 constexpr auto PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties"; 16 constexpr auto BOOT_STATE_INTF = "xyz.openbmc_project.State.Boot.Progress"; 17 constexpr auto BOOT_PROGRESS_PROP = "BootProgress"; 18 19 constexpr auto LOGGING_SVC = "xyz.openbmc_project.Logging"; 20 constexpr auto LOGGING_PATH = "/xyz/openbmc_project/logging"; 21 constexpr auto LOGGING_CREATE_INTF = "xyz.openbmc_project.Logging.Create"; 22 23 using namespace phosphor::logging; 24 25 bool wasHostBooting(sdbusplus::bus::bus& bus) 26 { 27 try 28 { 29 auto method = bus.new_method_call(HOST_STATE_SVC, HOST_STATE_PATH, 30 PROPERTY_INTERFACE, "Get"); 31 method.append(BOOT_STATE_INTF, BOOT_PROGRESS_PROP); 32 33 auto response = bus.call(method); 34 35 std::variant<std::string> bootProgress; 36 response.read(bootProgress); 37 38 if (std::get<std::string>(bootProgress) == 39 "xyz.openbmc_project.State.Boot.Progress.ProgressStages." 40 "Unspecified") 41 { 42 log<level::INFO>("Host was not booting before BMC reboot"); 43 return false; 44 } 45 46 log<level::INFO>("Host was booting before BMC reboot", 47 entry("BOOTPROGRESS=%s", 48 std::get<std::string>(bootProgress).c_str())); 49 } 50 catch (const sdbusplus::exception::exception& e) 51 { 52 log<level::ERR>("Error reading BootProgress", 53 entry("ERROR=%s", e.what()), 54 entry("SERVICE=%s", HOST_STATE_SVC), 55 entry("PATH=%s", HOST_STATE_PATH)); 56 57 throw; 58 } 59 60 return true; 61 } 62 63 void createErrorLog(sdbusplus::bus::bus& bus) 64 { 65 try 66 { 67 // Create interface requires something for additionalData 68 std::map<std::string, std::string> additionalData; 69 additionalData.emplace("_PID", std::to_string(getpid())); 70 71 static constexpr auto errorMessage = 72 "xyz.openbmc_project.State.Error.HostNotRunning"; 73 auto method = bus.new_method_call(LOGGING_SVC, LOGGING_PATH, 74 LOGGING_CREATE_INTF, "Create"); 75 auto level = 76 sdbusplus::xyz::openbmc_project::Logging::server::convertForMessage( 77 sdbusplus::xyz::openbmc_project::Logging::server::Entry::Level:: 78 Error); 79 method.append(errorMessage, level, additionalData); 80 auto resp = bus.call(method); 81 } 82 catch (const sdbusplus::exception::exception& e) 83 { 84 log<level::ERR>("sdbusplus D-Bus call exception", 85 entry("OBJPATH=%s", LOGGING_PATH), 86 entry("INTERFACE=%s", LOGGING_CREATE_INTF), 87 entry("EXCEPTION=%s", e.what())); 88 89 throw std::runtime_error( 90 "Error in invoking D-Bus logging create interface"); 91 } 92 catch (std::exception& e) 93 { 94 log<level::ERR>("D-bus call exception", 95 entry("EXCEPTION=%s", e.what())); 96 throw e; 97 } 98 } 99 100 int main() 101 { 102 103 auto bus = sdbusplus::bus::new_default(); 104 105 // This application will only be started if chassis power is on and the 106 // host is not responding after a BMC reboot. 107 // TODO Wait for chassis power on target to complete 108 109 // Check the last BootProgeress to see if the host was booting before 110 // the BMC reboot occurred 111 if (!wasHostBooting(bus)) 112 { 113 return 0; 114 } 115 116 // Host was booting before the BMC reboot so log an error and go to host 117 // quiesce target 118 createErrorLog(bus); 119 120 // TODO Move to Host Quiesce 121 122 return 0; 123 } 124