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