187eabc65SBen Tyner #include <libpdbg.h>
287eabc65SBen Tyner
30205f3b3SBen Tyner #include <analyzer/analyzer_main.hpp>
48c2f8b24SBen Tyner #include <boost/interprocess/ipc/message_queue.hpp>
57212d21dSBen Tyner #include <cli.hpp>
68c2f8b24SBen Tyner #include <listener.hpp>
70205f3b3SBen Tyner
80205f3b3SBen Tyner /**
90205f3b3SBen Tyner * @brief Attention handler application main()
100205f3b3SBen Tyner *
110205f3b3SBen Tyner * This is the main interface to the hardware diagnostics application. This
120205f3b3SBen Tyner * application will either be loaded as a daemon for monitoring the attention
130205f3b3SBen Tyner * gpio or it will be loaded as an application to analyze hardware and
14611b3442SZane Shelley * diagnose hardware error conditions.
150205f3b3SBen Tyner *
168c2f8b24SBen Tyner * Usage:
178c2f8b24SBen Tyner * --analyze: Analyze the hardware
188c2f8b24SBen Tyner * --start: Start the attention handler
198c2f8b24SBen Tyner * --stop: Stop the attention handler
208c2f8b24SBen Tyner * --all <on|off>: All attention handling
218c2f8b24SBen Tyner * --vital <on|off>: Vital attention handling
228c2f8b24SBen Tyner * --checkstop <on|off>: Checkstop attention handling
238c2f8b24SBen Tyner * --terminate <on|off>: Terminate Immiediately attention handling
248c2f8b24SBen Tyner * --breakpoints <on|off>: Breakpoint attention handling
250205f3b3SBen Tyner *
268c2f8b24SBen Tyner * Example: openpower-hw-diags --start --vital off
270205f3b3SBen Tyner *
280205f3b3SBen Tyner * @return 0 = success
290205f3b3SBen Tyner */
main(int argc,char * argv[])300205f3b3SBen Tyner int main(int argc, char* argv[])
310205f3b3SBen Tyner {
32b1ebfcb1SBen Tyner int rc = RC_SUCCESS; // assume success
330205f3b3SBen Tyner
348c2f8b24SBen Tyner using namespace boost::interprocess;
353fb52e53SBen Tyner
368c2f8b24SBen Tyner if (argc == 1)
370205f3b3SBen Tyner {
388c2f8b24SBen Tyner printf("openpower-hw-diags <options>\n");
398c2f8b24SBen Tyner printf("options:\n");
408c2f8b24SBen Tyner printf(" --analyze: Analyze the hardware\n");
418c2f8b24SBen Tyner printf(" --start: Start the attention handler\n");
428c2f8b24SBen Tyner printf(" --stop: Stop the attention handler\n");
438c2f8b24SBen Tyner printf(" --all <on|off>: All attention handling\n");
448c2f8b24SBen Tyner printf(" --vital <on|off>: Vital attention handling\n");
458c2f8b24SBen Tyner printf(" --checkstop <on|off>: Checkstop attention handling\n");
468c2f8b24SBen Tyner printf(" --terminate <on|off>: Terminate Immediately attention "
478c2f8b24SBen Tyner "handling\n");
488c2f8b24SBen Tyner printf(" --breakpoints <on|off>: Breakpoint attention handling\n");
490205f3b3SBen Tyner }
500205f3b3SBen Tyner else
510205f3b3SBen Tyner {
5287eabc65SBen Tyner // Pdbg targets should only be initialized once according to
5387eabc65SBen Tyner // libpdbg documentation. Initializing them here will make sure
5487eabc65SBen Tyner // they are initialized for the attention handler, invocation of
5587eabc65SBen Tyner // the analyzer via attention handler and direct invocation of
5687eabc65SBen Tyner // the analyzer via command line (--analyze).
5787eabc65SBen Tyner
5887eabc65SBen Tyner pdbg_targets_init(nullptr); // nullptr == use default fdt
598c2f8b24SBen Tyner
608c2f8b24SBen Tyner // Either analyze (application mode) or daemon mode
618c2f8b24SBen Tyner if (true == getCliOption(argv, argv + argc, "--analyze"))
620205f3b3SBen Tyner {
63*ebff0d37SZane Shelley // Analyze the host hardware.
64*ebff0d37SZane Shelley // TODO: At the moment, we'll only do MANUAL analysis (no service
65*ebff0d37SZane Shelley // actions). It may be possible in the future to allow command
66*ebff0d37SZane Shelley // line options to change the analysis type, if needed.
67*ebff0d37SZane Shelley
68611b3442SZane Shelley attn::DumpParameters dumpParameters;
69*ebff0d37SZane Shelley analyzer::analyzeHardware(analyzer::AnalysisType::MANUAL,
70*ebff0d37SZane Shelley dumpParameters);
710205f3b3SBen Tyner }
728c2f8b24SBen Tyner // daemon mode
738c2f8b24SBen Tyner else
748c2f8b24SBen Tyner {
75d70033a5SBen Tyner // Handle pending attentions
76d70033a5SBen Tyner attn::Config attnConfig;
77d70033a5SBen Tyner attn::attnHandler(&attnConfig);
78d70033a5SBen Tyner
798c2f8b24SBen Tyner // assume listener is not running
808c2f8b24SBen Tyner bool listenerStarted = false;
818c2f8b24SBen Tyner bool newListener = false;
828c2f8b24SBen Tyner
838c2f8b24SBen Tyner pthread_t ptidListener; // handle to listener thread
848c2f8b24SBen Tyner
858c2f8b24SBen Tyner // see if listener is already started
868c2f8b24SBen Tyner listenerStarted = listenerMqExists();
878c2f8b24SBen Tyner
888c2f8b24SBen Tyner // listener is not running so start it
898c2f8b24SBen Tyner if (false == listenerStarted)
908c2f8b24SBen Tyner {
918c2f8b24SBen Tyner // create listener thread
928c2f8b24SBen Tyner if (0 ==
938c2f8b24SBen Tyner pthread_create(&ptidListener, NULL, &threadListener, NULL))
948c2f8b24SBen Tyner {
958c2f8b24SBen Tyner listenerStarted = true;
968c2f8b24SBen Tyner newListener = true;
978c2f8b24SBen Tyner }
988c2f8b24SBen Tyner else
998c2f8b24SBen Tyner {
1008c2f8b24SBen Tyner rc = 1;
1018c2f8b24SBen Tyner }
1020205f3b3SBen Tyner }
1030205f3b3SBen Tyner
1048c2f8b24SBen Tyner // listener was running or just started
1058c2f8b24SBen Tyner if (true == listenerStarted)
1068c2f8b24SBen Tyner {
1078c2f8b24SBen Tyner // If we created a new listener this instance of
1088c2f8b24SBen Tyner // openpower-hw-diags will become our daemon (it will not exit
1098c2f8b24SBen Tyner // until stopped).
1108c2f8b24SBen Tyner if (true == newListener)
1118c2f8b24SBen Tyner {
1128c2f8b24SBen Tyner bool listenerReady = false;
1138c2f8b24SBen Tyner
1148c2f8b24SBen Tyner // It may take some time for the listener to become ready,
1158c2f8b24SBen Tyner // we will wait until the message queue has been created
1168c2f8b24SBen Tyner // before starting to communicate with our daemon.
1178c2f8b24SBen Tyner while (false == listenerReady)
1188c2f8b24SBen Tyner {
1198c2f8b24SBen Tyner usleep(500);
1208c2f8b24SBen Tyner listenerReady = listenerMqExists();
1218c2f8b24SBen Tyner }
1228c2f8b24SBen Tyner }
1238c2f8b24SBen Tyner
1248c2f8b24SBen Tyner // send cmd line to listener thread
1258c2f8b24SBen Tyner if (argc != sendCmdLine(argc, argv))
1268c2f8b24SBen Tyner {
1278c2f8b24SBen Tyner rc = 1;
1288c2f8b24SBen Tyner }
1298c2f8b24SBen Tyner
1308c2f8b24SBen Tyner // if this is a new listener let it run until "stopped"
1318c2f8b24SBen Tyner if (true == newListener)
1328c2f8b24SBen Tyner {
1338c2f8b24SBen Tyner pthread_join(ptidListener, NULL);
1348c2f8b24SBen Tyner }
1358c2f8b24SBen Tyner }
1368c2f8b24SBen Tyner }
1378c2f8b24SBen Tyner }
1380205f3b3SBen Tyner return rc;
1390205f3b3SBen Tyner }
140