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