xref: /openbmc/debug-trigger/main.c (revision 210ad636)
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 void process_debug(int sink)
18 {
19 	static const char action = 'c';
20 	ssize_t rc;
21 
22 	sync();
23 
24 	if ((rc = write(sink, &action, sizeof(action))) == sizeof(action))
25 		return;
26 
27 	if (rc == -1) {
28 		warn("Failed to execute debug command");
29 	} else {
30 		warnx("Failed to execute debug command: %zd", rc);
31 	}
32 }
33 
34 static void process_reboot(int sink __attribute__((unused)))
35 {
36 	ssize_t rc;
37 
38 	sync();
39 
40 	if ((rc = reboot(LINUX_REBOOT_CMD_RESTART))) {
41 		if (rc == -1)
42 			warn("Failed to reboot BMC");
43 		else
44 			warnx("Failed to reboot BMC: %zd", rc);
45 	}
46 }
47 
48 static int process(int source, int sink)
49 {
50 	ssize_t ingress;
51 	char command;
52 
53 	while ((ingress = read(source, &command, sizeof(command))) == sizeof(command)) {
54 		switch (command) {
55 		case 'D':
56 			process_debug(sink);
57 			break;
58 		case 'R':
59 			process_reboot(sink);
60 			break;
61 		default:
62 			warnx("Unexpected command: 0x%02x (%c)", command, command);
63 		}
64 	}
65 
66 	if (ingress == -1)
67 		warn("Failed to read from source");
68 
69 	return ingress;
70 }
71 
72 int main(int argc, char * const argv[])
73 {
74 	char devnode[PATH_MAX];
75 	char *devid;
76 	int source;
77 	int sink;
78 
79 	while (1) {
80 		static struct option long_options[] = {
81 			{0, 0, 0, 0},
82 		};
83 		int c;
84 
85 		c = getopt_long(argc, argv, "", long_options, NULL);
86 		if (c == -1)
87 			break;
88 	}
89 
90 	source = 0;
91 	sink = 1;
92 
93 	if (optind < argc) {
94 		char devpath[PATH_MAX];
95 
96 		strncpy(devpath, argv[optind], sizeof(devpath));
97 		devpath[PATH_MAX - 1] = '\0';
98 		devid = basename(devpath);
99 
100 		strncpy(devnode, "/dev/", sizeof(devnode));
101 		strncat(devnode, devid, sizeof(devnode));
102 		devnode[PATH_MAX - 1] = '\0';
103 
104 		if ((source = open(devnode, O_RDONLY)) == -1)
105 			err(EXIT_FAILURE, "Failed to open %s", devnode);
106 
107 		optind++;
108 	}
109 
110 	if (optind < argc) {
111 		if ((sink = open(argv[optind], O_WRONLY)) == -1)
112 			err(EXIT_FAILURE, "Failed to open %s", argv[optind]);
113 
114 		optind++;
115 	}
116 
117 	if (optind < argc)
118 		err(EXIT_FAILURE, "Found %d unexpected arguments", argc - optind);
119 
120 	if (process(source, sink) < 0)
121 		errx(EXIT_FAILURE, "Failure while processing command stream");
122 
123 	return 0;
124 }
125