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 17*db47cd7fSAndrew Jeffery static void process_debug(int sink) 18*db47cd7fSAndrew Jeffery { 19*db47cd7fSAndrew Jeffery static const char action = 'c'; 20*db47cd7fSAndrew Jeffery ssize_t rc; 21*db47cd7fSAndrew Jeffery 22*db47cd7fSAndrew Jeffery sync(); 23*db47cd7fSAndrew Jeffery 24*db47cd7fSAndrew Jeffery if ((rc = write(sink, &action, sizeof(action))) == sizeof(action)) 25*db47cd7fSAndrew Jeffery return; 26*db47cd7fSAndrew Jeffery 27*db47cd7fSAndrew Jeffery if (rc == -1) { 28*db47cd7fSAndrew Jeffery warn("Failed to execute debug command"); 29*db47cd7fSAndrew Jeffery } else { 30*db47cd7fSAndrew Jeffery warnx("Failed to execute debug command: %zd", rc); 31*db47cd7fSAndrew Jeffery } 32*db47cd7fSAndrew Jeffery } 33*db47cd7fSAndrew Jeffery 3411cd254bSAndrew Jeffery static int process(int source, int sink) 3511cd254bSAndrew Jeffery { 3611cd254bSAndrew Jeffery ssize_t ingress; 3711cd254bSAndrew Jeffery char command; 3811cd254bSAndrew Jeffery 3911cd254bSAndrew Jeffery while ((ingress = read(source, &command, sizeof(command))) == sizeof(command)) { 4011cd254bSAndrew Jeffery ssize_t rc; 4111cd254bSAndrew Jeffery 4211cd254bSAndrew Jeffery switch (command) { 43*db47cd7fSAndrew Jeffery case 'D': 44*db47cd7fSAndrew Jeffery process_debug(sink); 4511cd254bSAndrew Jeffery break; 4611cd254bSAndrew Jeffery case 'R': 4711cd254bSAndrew Jeffery sync(); 4811cd254bSAndrew Jeffery 4911cd254bSAndrew Jeffery if ((rc = reboot(LINUX_REBOOT_CMD_RESTART))) { 5011cd254bSAndrew Jeffery if (rc == -1) 5111cd254bSAndrew Jeffery warn("Failed to reboot BMC"); 5211cd254bSAndrew Jeffery else 5311cd254bSAndrew Jeffery warnx("Failed to reboot BMC: %zd", rc); 5411cd254bSAndrew Jeffery } 5511cd254bSAndrew Jeffery break; 5611cd254bSAndrew Jeffery default: 5711cd254bSAndrew Jeffery warnx("Unexpected command: 0x%02x (%c)", command, command); 5811cd254bSAndrew Jeffery } 5911cd254bSAndrew Jeffery } 6011cd254bSAndrew Jeffery 6111cd254bSAndrew Jeffery if (ingress == -1) 6211cd254bSAndrew Jeffery warn("Failed to read from source"); 6311cd254bSAndrew Jeffery 6411cd254bSAndrew Jeffery return ingress; 6511cd254bSAndrew Jeffery } 6611cd254bSAndrew Jeffery 6711cd254bSAndrew Jeffery int main(int argc, char * const argv[]) 6811cd254bSAndrew Jeffery { 6911cd254bSAndrew Jeffery char devnode[PATH_MAX]; 7011cd254bSAndrew Jeffery char *devid; 7111cd254bSAndrew Jeffery int source; 7211cd254bSAndrew Jeffery int sink; 7311cd254bSAndrew Jeffery 7411cd254bSAndrew Jeffery while (1) { 7511cd254bSAndrew Jeffery static struct option long_options[] = { 7611cd254bSAndrew Jeffery {0, 0, 0, 0}, 7711cd254bSAndrew Jeffery }; 7811cd254bSAndrew Jeffery int c; 7911cd254bSAndrew Jeffery 8011cd254bSAndrew Jeffery c = getopt_long(argc, argv, "", long_options, NULL); 8111cd254bSAndrew Jeffery if (c == -1) 8211cd254bSAndrew Jeffery break; 8311cd254bSAndrew Jeffery } 8411cd254bSAndrew Jeffery 8511cd254bSAndrew Jeffery source = 0; 8611cd254bSAndrew Jeffery sink = 1; 8711cd254bSAndrew Jeffery 8811cd254bSAndrew Jeffery if (optind < argc) { 8911cd254bSAndrew Jeffery char devpath[PATH_MAX]; 9011cd254bSAndrew Jeffery 9111cd254bSAndrew Jeffery strncpy(devpath, argv[optind], sizeof(devpath)); 9211cd254bSAndrew Jeffery devpath[PATH_MAX - 1] = '\0'; 9311cd254bSAndrew Jeffery devid = basename(devpath); 9411cd254bSAndrew Jeffery 9511cd254bSAndrew Jeffery strncpy(devnode, "/dev/", sizeof(devnode)); 9611cd254bSAndrew Jeffery strncat(devnode, devid, sizeof(devnode)); 9711cd254bSAndrew Jeffery devnode[PATH_MAX - 1] = '\0'; 9811cd254bSAndrew Jeffery 9911cd254bSAndrew Jeffery if ((source = open(devnode, O_RDONLY)) == -1) 10011cd254bSAndrew Jeffery err(EXIT_FAILURE, "Failed to open %s", devnode); 10111cd254bSAndrew Jeffery 10211cd254bSAndrew Jeffery optind++; 10311cd254bSAndrew Jeffery } 10411cd254bSAndrew Jeffery 10511cd254bSAndrew Jeffery if (optind < argc) { 10611cd254bSAndrew Jeffery if ((sink = open(argv[optind], O_WRONLY)) == -1) 10711cd254bSAndrew Jeffery err(EXIT_FAILURE, "Failed to open %s", argv[optind]); 10811cd254bSAndrew Jeffery 10911cd254bSAndrew Jeffery optind++; 11011cd254bSAndrew Jeffery } 11111cd254bSAndrew Jeffery 11211cd254bSAndrew Jeffery if (optind < argc) 11311cd254bSAndrew Jeffery err(EXIT_FAILURE, "Found %d unexpected arguments", argc - optind); 11411cd254bSAndrew Jeffery 11511cd254bSAndrew Jeffery if (process(source, sink) < 0) 11611cd254bSAndrew Jeffery errx(EXIT_FAILURE, "Failure while processing command stream"); 11711cd254bSAndrew Jeffery 11811cd254bSAndrew Jeffery return 0; 11911cd254bSAndrew Jeffery } 120