111cd254bSAndrew Jeffery // SPDX-License-Identifier: Apache-2.0 211cd254bSAndrew Jeffery // Copyright (C) 2021 IBM Corp. 311cd254bSAndrew Jeffery 411cd254bSAndrew Jeffery #include <err.h> 511cd254bSAndrew Jeffery #include <fcntl.h> 611cd254bSAndrew Jeffery #include <getopt.h> 711cd254bSAndrew Jeffery #include <libgen.h> 811cd254bSAndrew Jeffery #include <limits.h> 911cd254bSAndrew Jeffery #include <linux/reboot.h> 1011cd254bSAndrew Jeffery #include <stdlib.h> 1111cd254bSAndrew Jeffery #include <string.h> 1211cd254bSAndrew Jeffery #include <sys/reboot.h> 1311cd254bSAndrew Jeffery #include <sys/stat.h> 1411cd254bSAndrew Jeffery #include <sys/types.h> 1511cd254bSAndrew Jeffery #include <unistd.h> 1611cd254bSAndrew Jeffery 17db47cd7fSAndrew Jeffery static void process_debug(int sink) 18db47cd7fSAndrew Jeffery { 19db47cd7fSAndrew Jeffery static const char action = 'c'; 20db47cd7fSAndrew Jeffery ssize_t rc; 21db47cd7fSAndrew Jeffery 22db47cd7fSAndrew Jeffery sync(); 23db47cd7fSAndrew Jeffery 24db47cd7fSAndrew Jeffery if ((rc = write(sink, &action, sizeof(action))) == sizeof(action)) 25db47cd7fSAndrew Jeffery return; 26db47cd7fSAndrew Jeffery 27db47cd7fSAndrew Jeffery if (rc == -1) { 28db47cd7fSAndrew Jeffery warn("Failed to execute debug command"); 29db47cd7fSAndrew Jeffery } else { 30db47cd7fSAndrew Jeffery warnx("Failed to execute debug command: %zd", rc); 31db47cd7fSAndrew Jeffery } 32db47cd7fSAndrew Jeffery } 33db47cd7fSAndrew Jeffery 34*210ad636SAndrew Jeffery static void process_reboot(int sink __attribute__((unused))) 3511cd254bSAndrew Jeffery { 3611cd254bSAndrew Jeffery ssize_t rc; 3711cd254bSAndrew Jeffery 3811cd254bSAndrew Jeffery sync(); 3911cd254bSAndrew Jeffery 4011cd254bSAndrew Jeffery if ((rc = reboot(LINUX_REBOOT_CMD_RESTART))) { 4111cd254bSAndrew Jeffery if (rc == -1) 4211cd254bSAndrew Jeffery warn("Failed to reboot BMC"); 4311cd254bSAndrew Jeffery else 4411cd254bSAndrew Jeffery warnx("Failed to reboot BMC: %zd", rc); 4511cd254bSAndrew Jeffery } 46*210ad636SAndrew Jeffery } 47*210ad636SAndrew Jeffery 48*210ad636SAndrew Jeffery static int process(int source, int sink) 49*210ad636SAndrew Jeffery { 50*210ad636SAndrew Jeffery ssize_t ingress; 51*210ad636SAndrew Jeffery char command; 52*210ad636SAndrew Jeffery 53*210ad636SAndrew Jeffery while ((ingress = read(source, &command, sizeof(command))) == sizeof(command)) { 54*210ad636SAndrew Jeffery switch (command) { 55*210ad636SAndrew Jeffery case 'D': 56*210ad636SAndrew Jeffery process_debug(sink); 57*210ad636SAndrew Jeffery break; 58*210ad636SAndrew Jeffery case 'R': 59*210ad636SAndrew Jeffery process_reboot(sink); 6011cd254bSAndrew Jeffery break; 6111cd254bSAndrew Jeffery default: 6211cd254bSAndrew Jeffery warnx("Unexpected command: 0x%02x (%c)", command, command); 6311cd254bSAndrew Jeffery } 6411cd254bSAndrew Jeffery } 6511cd254bSAndrew Jeffery 6611cd254bSAndrew Jeffery if (ingress == -1) 6711cd254bSAndrew Jeffery warn("Failed to read from source"); 6811cd254bSAndrew Jeffery 6911cd254bSAndrew Jeffery return ingress; 7011cd254bSAndrew Jeffery } 7111cd254bSAndrew Jeffery 7211cd254bSAndrew Jeffery int main(int argc, char * const argv[]) 7311cd254bSAndrew Jeffery { 7411cd254bSAndrew Jeffery char devnode[PATH_MAX]; 7511cd254bSAndrew Jeffery char *devid; 7611cd254bSAndrew Jeffery int source; 7711cd254bSAndrew Jeffery int sink; 7811cd254bSAndrew Jeffery 7911cd254bSAndrew Jeffery while (1) { 8011cd254bSAndrew Jeffery static struct option long_options[] = { 8111cd254bSAndrew Jeffery {0, 0, 0, 0}, 8211cd254bSAndrew Jeffery }; 8311cd254bSAndrew Jeffery int c; 8411cd254bSAndrew Jeffery 8511cd254bSAndrew Jeffery c = getopt_long(argc, argv, "", long_options, NULL); 8611cd254bSAndrew Jeffery if (c == -1) 8711cd254bSAndrew Jeffery break; 8811cd254bSAndrew Jeffery } 8911cd254bSAndrew Jeffery 9011cd254bSAndrew Jeffery source = 0; 9111cd254bSAndrew Jeffery sink = 1; 9211cd254bSAndrew Jeffery 9311cd254bSAndrew Jeffery if (optind < argc) { 9411cd254bSAndrew Jeffery char devpath[PATH_MAX]; 9511cd254bSAndrew Jeffery 9611cd254bSAndrew Jeffery strncpy(devpath, argv[optind], sizeof(devpath)); 9711cd254bSAndrew Jeffery devpath[PATH_MAX - 1] = '\0'; 9811cd254bSAndrew Jeffery devid = basename(devpath); 9911cd254bSAndrew Jeffery 10011cd254bSAndrew Jeffery strncpy(devnode, "/dev/", sizeof(devnode)); 10111cd254bSAndrew Jeffery strncat(devnode, devid, sizeof(devnode)); 10211cd254bSAndrew Jeffery devnode[PATH_MAX - 1] = '\0'; 10311cd254bSAndrew Jeffery 10411cd254bSAndrew Jeffery if ((source = open(devnode, O_RDONLY)) == -1) 10511cd254bSAndrew Jeffery err(EXIT_FAILURE, "Failed to open %s", devnode); 10611cd254bSAndrew Jeffery 10711cd254bSAndrew Jeffery optind++; 10811cd254bSAndrew Jeffery } 10911cd254bSAndrew Jeffery 11011cd254bSAndrew Jeffery if (optind < argc) { 11111cd254bSAndrew Jeffery if ((sink = open(argv[optind], O_WRONLY)) == -1) 11211cd254bSAndrew Jeffery err(EXIT_FAILURE, "Failed to open %s", argv[optind]); 11311cd254bSAndrew Jeffery 11411cd254bSAndrew Jeffery optind++; 11511cd254bSAndrew Jeffery } 11611cd254bSAndrew Jeffery 11711cd254bSAndrew Jeffery if (optind < argc) 11811cd254bSAndrew Jeffery err(EXIT_FAILURE, "Found %d unexpected arguments", argc - optind); 11911cd254bSAndrew Jeffery 12011cd254bSAndrew Jeffery if (process(source, sink) < 0) 12111cd254bSAndrew Jeffery errx(EXIT_FAILURE, "Failure while processing command stream"); 12211cd254bSAndrew Jeffery 12311cd254bSAndrew Jeffery return 0; 12411cd254bSAndrew Jeffery } 125