xref: /openbmc/linux/arch/um/drivers/harddog_user.c (revision 73a23d77)
1dbddf429SAlex Dewar // SPDX-License-Identifier: GPL-2.0
21da177e4SLinus Torvalds /*
38ca842c4SJeff Dike  * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
41da177e4SLinus Torvalds  */
51da177e4SLinus Torvalds 
61da177e4SLinus Torvalds #include <stdio.h>
71da177e4SLinus Torvalds #include <unistd.h>
81da177e4SLinus Torvalds #include <errno.h>
937185b33SAl Viro #include <os.h>
10*73a23d77SJohannes Berg #include "harddog.h"
111da177e4SLinus Torvalds 
121da177e4SLinus Torvalds struct dog_data {
13f9bb3b59SHans-Werner Hilse 	int stdin_fd;
14f9bb3b59SHans-Werner Hilse 	int stdout_fd;
151da177e4SLinus Torvalds 	int close_me[2];
161da177e4SLinus Torvalds };
171da177e4SLinus Torvalds 
pre_exec(void * d)181da177e4SLinus Torvalds static void pre_exec(void *d)
191da177e4SLinus Torvalds {
201da177e4SLinus Torvalds 	struct dog_data *data = d;
211da177e4SLinus Torvalds 
22f9bb3b59SHans-Werner Hilse 	dup2(data->stdin_fd, 0);
23f9bb3b59SHans-Werner Hilse 	dup2(data->stdout_fd, 1);
24f9bb3b59SHans-Werner Hilse 	dup2(data->stdout_fd, 2);
25f9bb3b59SHans-Werner Hilse 	close(data->stdin_fd);
26f9bb3b59SHans-Werner Hilse 	close(data->stdout_fd);
278ca842c4SJeff Dike 	close(data->close_me[0]);
288ca842c4SJeff Dike 	close(data->close_me[1]);
291da177e4SLinus Torvalds }
301da177e4SLinus Torvalds 
start_watchdog(int * in_fd_ret,int * out_fd_ret,char * sock)311da177e4SLinus Torvalds int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock)
321da177e4SLinus Torvalds {
331da177e4SLinus Torvalds 	struct dog_data data;
341da177e4SLinus Torvalds 	int in_fds[2], out_fds[2], pid, n, err;
3539073db1SRichard Weinberger 	char pid_buf[sizeof("nnnnnnn\0")], c;
361da177e4SLinus Torvalds 	char *pid_args[] = { "/usr/bin/uml_watchdog", "-pid", pid_buf, NULL };
371da177e4SLinus Torvalds 	char *mconsole_args[] = { "/usr/bin/uml_watchdog", "-mconsole", NULL,
381da177e4SLinus Torvalds 				  NULL };
391da177e4SLinus Torvalds 	char **args = NULL;
401da177e4SLinus Torvalds 
411da177e4SLinus Torvalds 	err = os_pipe(in_fds, 1, 0);
421da177e4SLinus Torvalds 	if (err < 0) {
431da177e4SLinus Torvalds 		printk("harddog_open - os_pipe failed, err = %d\n", -err);
441da177e4SLinus Torvalds 		goto out;
451da177e4SLinus Torvalds 	}
461da177e4SLinus Torvalds 
471da177e4SLinus Torvalds 	err = os_pipe(out_fds, 1, 0);
481da177e4SLinus Torvalds 	if (err < 0) {
491da177e4SLinus Torvalds 		printk("harddog_open - os_pipe failed, err = %d\n", -err);
501da177e4SLinus Torvalds 		goto out_close_in;
511da177e4SLinus Torvalds 	}
521da177e4SLinus Torvalds 
53f9bb3b59SHans-Werner Hilse 	data.stdin_fd = out_fds[0];
54f9bb3b59SHans-Werner Hilse 	data.stdout_fd = in_fds[1];
551da177e4SLinus Torvalds 	data.close_me[0] = out_fds[1];
561da177e4SLinus Torvalds 	data.close_me[1] = in_fds[0];
571da177e4SLinus Torvalds 
581da177e4SLinus Torvalds 	if (sock != NULL) {
591da177e4SLinus Torvalds 		mconsole_args[2] = sock;
601da177e4SLinus Torvalds 		args = mconsole_args;
611da177e4SLinus Torvalds 	}
621da177e4SLinus Torvalds 	else {
631da177e4SLinus Torvalds 		/* XXX The os_getpid() is not SMP correct */
646aa802ceSJeff Dike 		sprintf(pid_buf, "%d", os_getpid());
651da177e4SLinus Torvalds 		args = pid_args;
661da177e4SLinus Torvalds 	}
671da177e4SLinus Torvalds 
68c4399016SJeff Dike 	pid = run_helper(pre_exec, &data, args);
691da177e4SLinus Torvalds 
708ca842c4SJeff Dike 	close(out_fds[0]);
718ca842c4SJeff Dike 	close(in_fds[1]);
721da177e4SLinus Torvalds 
731da177e4SLinus Torvalds 	if (pid < 0) {
741da177e4SLinus Torvalds 		err = -pid;
751da177e4SLinus Torvalds 		printk("harddog_open - run_helper failed, errno = %d\n", -err);
761da177e4SLinus Torvalds 		goto out_close_out;
771da177e4SLinus Torvalds 	}
781da177e4SLinus Torvalds 
798ca842c4SJeff Dike 	n = read(in_fds[0], &c, sizeof(c));
801da177e4SLinus Torvalds 	if (n == 0) {
811da177e4SLinus Torvalds 		printk("harddog_open - EOF on watchdog pipe\n");
82e4d06b3fSJohann Felix Soden 		helper_wait(pid);
831da177e4SLinus Torvalds 		err = -EIO;
841da177e4SLinus Torvalds 		goto out_close_out;
851da177e4SLinus Torvalds 	}
861da177e4SLinus Torvalds 	else if (n < 0) {
871da177e4SLinus Torvalds 		printk("harddog_open - read of watchdog pipe failed, "
888ca842c4SJeff Dike 		       "err = %d\n", errno);
89e4d06b3fSJohann Felix Soden 		helper_wait(pid);
901da177e4SLinus Torvalds 		err = n;
911da177e4SLinus Torvalds 		goto out_close_out;
921da177e4SLinus Torvalds 	}
931da177e4SLinus Torvalds 	*in_fd_ret = in_fds[0];
941da177e4SLinus Torvalds 	*out_fd_ret = out_fds[1];
955bbcbecaSJeff Dike 	return 0;
961da177e4SLinus Torvalds 
971da177e4SLinus Torvalds  out_close_in:
988ca842c4SJeff Dike 	close(in_fds[0]);
998ca842c4SJeff Dike 	close(in_fds[1]);
1001da177e4SLinus Torvalds  out_close_out:
1018ca842c4SJeff Dike 	close(out_fds[0]);
1028ca842c4SJeff Dike 	close(out_fds[1]);
1031da177e4SLinus Torvalds  out:
1045bbcbecaSJeff Dike 	return err;
1051da177e4SLinus Torvalds }
1061da177e4SLinus Torvalds 
stop_watchdog(int in_fd,int out_fd)1071da177e4SLinus Torvalds void stop_watchdog(int in_fd, int out_fd)
1081da177e4SLinus Torvalds {
1098ca842c4SJeff Dike 	close(in_fd);
1108ca842c4SJeff Dike 	close(out_fd);
1111da177e4SLinus Torvalds }
1121da177e4SLinus Torvalds 
ping_watchdog(int fd)1131da177e4SLinus Torvalds int ping_watchdog(int fd)
1141da177e4SLinus Torvalds {
1151da177e4SLinus Torvalds 	int n;
1161da177e4SLinus Torvalds 	char c = '\n';
1171da177e4SLinus Torvalds 
1188ca842c4SJeff Dike 	n = write(fd, &c, sizeof(c));
1191da177e4SLinus Torvalds 	if (n != sizeof(c)) {
1208ca842c4SJeff Dike 		printk("ping_watchdog - write failed, ret = %d, err = %d\n",
1218ca842c4SJeff Dike 		       n, errno);
1221da177e4SLinus Torvalds 		if (n < 0)
1235bbcbecaSJeff Dike 			return n;
1245bbcbecaSJeff Dike 		return -EIO;
1251da177e4SLinus Torvalds 	}
1261da177e4SLinus Torvalds 	return 1;
1271da177e4SLinus Torvalds 
1281da177e4SLinus Torvalds }
129