xref: /openbmc/debug-trigger/main.c (revision 11cd254b9bdd04788df12a062fdc873e9ec4e60a)
1 // SPDX-License-Identifier: Apache-2.0
2 // Copyright (C) 2021 IBM Corp.
3 
4 #include <err.h>
5 #include <fcntl.h>
6 #include <getopt.h>
7 #include <libgen.h>
8 #include <limits.h>
9 #include <linux/reboot.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <sys/reboot.h>
13 #include <sys/stat.h>
14 #include <sys/types.h>
15 #include <unistd.h>
16 
17 static int process(int source, int sink)
18 {
19 	ssize_t ingress;
20 	char command;
21 
22 	while ((ingress = read(source, &command, sizeof(command))) == sizeof(command)) {
23 		static const char action = 'c';
24 		ssize_t rc;
25 
26 		switch (command) {
27 		case 'D': /* Debug */
28 			sync();
29 
30 			if ((rc = write(sink, &action, sizeof(action))) == sizeof(action))
31 				continue;
32 
33 			if (rc == -1) {
34 				warn("Failed to execute command 0x%02x (%c)",
35 						command, command);
36 			} else {
37 				warnx("Failed to execute command 0x%02x (%c): %zd",
38 						command, command, rc);
39 			}
40 			break;
41 		case 'R':
42 			sync();
43 
44 			if ((rc = reboot(LINUX_REBOOT_CMD_RESTART))) {
45 				if (rc == -1)
46 					warn("Failed to reboot BMC");
47 				else
48 					warnx("Failed to reboot BMC: %zd", rc);
49 			}
50 			break;
51 		default:
52 			warnx("Unexpected command: 0x%02x (%c)", command, command);
53 		}
54 	}
55 
56 	if (ingress == -1)
57 		warn("Failed to read from source");
58 
59 	return ingress;
60 }
61 
62 int main(int argc, char * const argv[])
63 {
64 	char devnode[PATH_MAX];
65 	char *devid;
66 	int source;
67 	int sink;
68 
69 	while (1) {
70 		static struct option long_options[] = {
71 			{0, 0, 0, 0},
72 		};
73 		int c;
74 
75 		c = getopt_long(argc, argv, "", long_options, NULL);
76 		if (c == -1)
77 			break;
78 	}
79 
80 	source = 0;
81 	sink = 1;
82 
83 	if (optind < argc) {
84 		char devpath[PATH_MAX];
85 
86 		strncpy(devpath, argv[optind], sizeof(devpath));
87 		devpath[PATH_MAX - 1] = '\0';
88 		devid = basename(devpath);
89 
90 		strncpy(devnode, "/dev/", sizeof(devnode));
91 		strncat(devnode, devid, sizeof(devnode));
92 		devnode[PATH_MAX - 1] = '\0';
93 
94 		if ((source = open(devnode, O_RDONLY)) == -1)
95 			err(EXIT_FAILURE, "Failed to open %s", devnode);
96 
97 		optind++;
98 	}
99 
100 	if (optind < argc) {
101 		if ((sink = open(argv[optind], O_WRONLY)) == -1)
102 			err(EXIT_FAILURE, "Failed to open %s", argv[optind]);
103 
104 		optind++;
105 	}
106 
107 	if (optind < argc)
108 		err(EXIT_FAILURE, "Found %d unexpected arguments", argc - optind);
109 
110 	if (process(source, sink) < 0)
111 		errx(EXIT_FAILURE, "Failure while processing command stream");
112 
113 	return 0;
114 }
115