xref: /openbmc/linux/tools/verification/rv/src/rv.c (revision 54a0dffa)
14bc4b131SDaniel Bristot de Oliveira // SPDX-License-Identifier: GPL-2.0
24bc4b131SDaniel Bristot de Oliveira /*
34bc4b131SDaniel Bristot de Oliveira  * rv tool, the interface for the Linux kernel RV subsystem and home of
44bc4b131SDaniel Bristot de Oliveira  * user-space controlled monitors.
54bc4b131SDaniel Bristot de Oliveira  *
64bc4b131SDaniel Bristot de Oliveira  * Copyright (C) 2022 Red Hat Inc, Daniel Bristot de Oliveira <bristot@kernel.org>
74bc4b131SDaniel Bristot de Oliveira  */
84bc4b131SDaniel Bristot de Oliveira 
94bc4b131SDaniel Bristot de Oliveira #include <stdlib.h>
104bc4b131SDaniel Bristot de Oliveira #include <signal.h>
114bc4b131SDaniel Bristot de Oliveira #include <unistd.h>
124bc4b131SDaniel Bristot de Oliveira 
134bc4b131SDaniel Bristot de Oliveira #include <trace.h>
144bc4b131SDaniel Bristot de Oliveira #include <utils.h>
156d60f896SDaniel Bristot de Oliveira #include <in_kernel.h>
164bc4b131SDaniel Bristot de Oliveira 
174bc4b131SDaniel Bristot de Oliveira static int stop_session;
184bc4b131SDaniel Bristot de Oliveira 
194bc4b131SDaniel Bristot de Oliveira /*
204bc4b131SDaniel Bristot de Oliveira  * stop_rv - tell monitors to stop
214bc4b131SDaniel Bristot de Oliveira  */
stop_rv(int sig)224bc4b131SDaniel Bristot de Oliveira static void stop_rv(int sig)
234bc4b131SDaniel Bristot de Oliveira {
244bc4b131SDaniel Bristot de Oliveira 	stop_session = 1;
254bc4b131SDaniel Bristot de Oliveira }
264bc4b131SDaniel Bristot de Oliveira 
274bc4b131SDaniel Bristot de Oliveira /**
284bc4b131SDaniel Bristot de Oliveira  * should_stop - check if the monitor should stop.
294bc4b131SDaniel Bristot de Oliveira  *
304bc4b131SDaniel Bristot de Oliveira  * Returns 1 if the monitor should stop, 0 otherwise.
314bc4b131SDaniel Bristot de Oliveira  */
should_stop(void)324bc4b131SDaniel Bristot de Oliveira int should_stop(void)
334bc4b131SDaniel Bristot de Oliveira {
344bc4b131SDaniel Bristot de Oliveira 	return stop_session;
354bc4b131SDaniel Bristot de Oliveira }
364bc4b131SDaniel Bristot de Oliveira 
374bc4b131SDaniel Bristot de Oliveira /*
384bc4b131SDaniel Bristot de Oliveira  * rv_list - list all available monitors
394bc4b131SDaniel Bristot de Oliveira  */
rv_list(int argc,char ** argv)404bc4b131SDaniel Bristot de Oliveira static void rv_list(int argc, char **argv)
414bc4b131SDaniel Bristot de Oliveira {
424bc4b131SDaniel Bristot de Oliveira 	static const char *const usage[] = {
434bc4b131SDaniel Bristot de Oliveira 		"",
444bc4b131SDaniel Bristot de Oliveira 		"  usage: rv list [-h]",
454bc4b131SDaniel Bristot de Oliveira 		"",
464bc4b131SDaniel Bristot de Oliveira 		"	list all available monitors",
474bc4b131SDaniel Bristot de Oliveira 		"",
484bc4b131SDaniel Bristot de Oliveira 		"	-h/--help: print this menu",
494bc4b131SDaniel Bristot de Oliveira 		NULL,
504bc4b131SDaniel Bristot de Oliveira 	};
514bc4b131SDaniel Bristot de Oliveira 	int i;
524bc4b131SDaniel Bristot de Oliveira 
534bc4b131SDaniel Bristot de Oliveira 	if (argc > 1) {
544bc4b131SDaniel Bristot de Oliveira 		fprintf(stderr, "rv version %s\n", VERSION);
554bc4b131SDaniel Bristot de Oliveira 
564bc4b131SDaniel Bristot de Oliveira 		/* more than 1 is always usage */
574bc4b131SDaniel Bristot de Oliveira 		for (i = 0; usage[i]; i++)
584bc4b131SDaniel Bristot de Oliveira 			fprintf(stderr, "%s\n", usage[i]);
594bc4b131SDaniel Bristot de Oliveira 
604bc4b131SDaniel Bristot de Oliveira 		/* but only -h is valid */
614bc4b131SDaniel Bristot de Oliveira 		if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))
624bc4b131SDaniel Bristot de Oliveira 			exit(0);
634bc4b131SDaniel Bristot de Oliveira 		else
644bc4b131SDaniel Bristot de Oliveira 			exit(1);
654bc4b131SDaniel Bristot de Oliveira 	}
664bc4b131SDaniel Bristot de Oliveira 
676d60f896SDaniel Bristot de Oliveira 	ikm_list_monitors();
684bc4b131SDaniel Bristot de Oliveira 	exit(0);
694bc4b131SDaniel Bristot de Oliveira }
704bc4b131SDaniel Bristot de Oliveira 
714bc4b131SDaniel Bristot de Oliveira /*
724bc4b131SDaniel Bristot de Oliveira  * rv_mon - try to run a monitor passed as argument
734bc4b131SDaniel Bristot de Oliveira  */
rv_mon(int argc,char ** argv)744bc4b131SDaniel Bristot de Oliveira static void rv_mon(int argc, char **argv)
754bc4b131SDaniel Bristot de Oliveira {
764bc4b131SDaniel Bristot de Oliveira 	char *monitor_name;
77*54a0dffaSColin Ian King 	int i, run = 0;
784bc4b131SDaniel Bristot de Oliveira 
794bc4b131SDaniel Bristot de Oliveira 	static const char *const usage[] = {
804bc4b131SDaniel Bristot de Oliveira 		"",
814bc4b131SDaniel Bristot de Oliveira 		"  usage: rv mon [-h] monitor [monitor options]",
824bc4b131SDaniel Bristot de Oliveira 		"",
834bc4b131SDaniel Bristot de Oliveira 		"	run a monitor",
844bc4b131SDaniel Bristot de Oliveira 		"",
854bc4b131SDaniel Bristot de Oliveira 		"	-h/--help: print this menu",
864bc4b131SDaniel Bristot de Oliveira 		"",
874bc4b131SDaniel Bristot de Oliveira 		"	monitor [monitor options]: the monitor, passing",
884bc4b131SDaniel Bristot de Oliveira 		"	the arguments to the [monitor options]",
894bc4b131SDaniel Bristot de Oliveira 		NULL,
904bc4b131SDaniel Bristot de Oliveira 	};
914bc4b131SDaniel Bristot de Oliveira 
924bc4b131SDaniel Bristot de Oliveira 	/* requires at least one argument */
934bc4b131SDaniel Bristot de Oliveira 	if (argc == 1) {
944bc4b131SDaniel Bristot de Oliveira 
954bc4b131SDaniel Bristot de Oliveira 		fprintf(stderr, "rv version %s\n", VERSION);
964bc4b131SDaniel Bristot de Oliveira 
974bc4b131SDaniel Bristot de Oliveira 		for (i = 0; usage[i]; i++)
984bc4b131SDaniel Bristot de Oliveira 			fprintf(stderr, "%s\n", usage[i]);
994bc4b131SDaniel Bristot de Oliveira 		exit(1);
1004bc4b131SDaniel Bristot de Oliveira 	} else if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
1014bc4b131SDaniel Bristot de Oliveira 
1024bc4b131SDaniel Bristot de Oliveira 		fprintf(stderr, "rv version %s\n", VERSION);
1034bc4b131SDaniel Bristot de Oliveira 
1044bc4b131SDaniel Bristot de Oliveira 		for (i = 0; usage[i]; i++)
1054bc4b131SDaniel Bristot de Oliveira 			fprintf(stderr, "%s\n", usage[i]);
1064bc4b131SDaniel Bristot de Oliveira 		exit(0);
1074bc4b131SDaniel Bristot de Oliveira 	}
1084bc4b131SDaniel Bristot de Oliveira 
1094bc4b131SDaniel Bristot de Oliveira 	monitor_name = argv[1];
1104bc4b131SDaniel Bristot de Oliveira 	/*
1114bc4b131SDaniel Bristot de Oliveira 	 * Call all possible monitor implementations, looking
1124bc4b131SDaniel Bristot de Oliveira 	 * for the [monitor].
1134bc4b131SDaniel Bristot de Oliveira 	 */
1146d60f896SDaniel Bristot de Oliveira 	run += ikm_run_monitor(monitor_name, argc-1, &argv[1]);
1154bc4b131SDaniel Bristot de Oliveira 
1164bc4b131SDaniel Bristot de Oliveira 	if (!run)
1174bc4b131SDaniel Bristot de Oliveira 		err_msg("rv: monitor %s does not exist\n", monitor_name);
1184bc4b131SDaniel Bristot de Oliveira 	exit(!run);
1194bc4b131SDaniel Bristot de Oliveira }
1204bc4b131SDaniel Bristot de Oliveira 
usage(int exit_val,const char * fmt,...)1214bc4b131SDaniel Bristot de Oliveira static void usage(int exit_val, const char *fmt, ...)
1224bc4b131SDaniel Bristot de Oliveira {
1234bc4b131SDaniel Bristot de Oliveira 	char message[1024];
1244bc4b131SDaniel Bristot de Oliveira 	va_list ap;
1254bc4b131SDaniel Bristot de Oliveira 	int i;
1264bc4b131SDaniel Bristot de Oliveira 
1274bc4b131SDaniel Bristot de Oliveira 	static const char *const usage[] = {
1284bc4b131SDaniel Bristot de Oliveira 		"",
1294bc4b131SDaniel Bristot de Oliveira 		"  usage: rv command [-h] [command_options]",
1304bc4b131SDaniel Bristot de Oliveira 		"",
1314bc4b131SDaniel Bristot de Oliveira 		"	-h/--help: print this menu",
1324bc4b131SDaniel Bristot de Oliveira 		"",
1334bc4b131SDaniel Bristot de Oliveira 		"	command: run one of the following command:",
1344bc4b131SDaniel Bristot de Oliveira 		"	  list: list all available monitors",
1354bc4b131SDaniel Bristot de Oliveira 		"	  mon:  run a monitor",
1364bc4b131SDaniel Bristot de Oliveira 		"",
1374bc4b131SDaniel Bristot de Oliveira 		"	[command options]: each command has its own set of options",
1384bc4b131SDaniel Bristot de Oliveira 		"		           run rv command -h for further information",
1394bc4b131SDaniel Bristot de Oliveira 		NULL,
1404bc4b131SDaniel Bristot de Oliveira 	};
1414bc4b131SDaniel Bristot de Oliveira 
1424bc4b131SDaniel Bristot de Oliveira 	va_start(ap, fmt);
1434bc4b131SDaniel Bristot de Oliveira 	vsnprintf(message, sizeof(message), fmt, ap);
1444bc4b131SDaniel Bristot de Oliveira 	va_end(ap);
1454bc4b131SDaniel Bristot de Oliveira 
1464bc4b131SDaniel Bristot de Oliveira 	fprintf(stderr, "rv version %s: %s\n", VERSION, message);
1474bc4b131SDaniel Bristot de Oliveira 
1484bc4b131SDaniel Bristot de Oliveira 	for (i = 0; usage[i]; i++)
1494bc4b131SDaniel Bristot de Oliveira 		fprintf(stderr, "%s\n", usage[i]);
1504bc4b131SDaniel Bristot de Oliveira 
1514bc4b131SDaniel Bristot de Oliveira 	exit(exit_val);
1524bc4b131SDaniel Bristot de Oliveira }
1534bc4b131SDaniel Bristot de Oliveira 
1544bc4b131SDaniel Bristot de Oliveira /*
1554bc4b131SDaniel Bristot de Oliveira  * main - select which main sending the command
1564bc4b131SDaniel Bristot de Oliveira  *
1574bc4b131SDaniel Bristot de Oliveira  * main itself redirects the arguments to the sub-commands
1584bc4b131SDaniel Bristot de Oliveira  * to handle the options.
1594bc4b131SDaniel Bristot de Oliveira  *
1604bc4b131SDaniel Bristot de Oliveira  * subcommands should exit.
1614bc4b131SDaniel Bristot de Oliveira  */
main(int argc,char ** argv)1624bc4b131SDaniel Bristot de Oliveira int main(int argc, char **argv)
1634bc4b131SDaniel Bristot de Oliveira {
1644bc4b131SDaniel Bristot de Oliveira 	if (geteuid())
1654bc4b131SDaniel Bristot de Oliveira 		usage(1, "%s needs root permission", argv[0]);
1664bc4b131SDaniel Bristot de Oliveira 
1674bc4b131SDaniel Bristot de Oliveira 	if (argc <= 1)
1684bc4b131SDaniel Bristot de Oliveira 		usage(1, "%s requires a command", argv[0]);
1694bc4b131SDaniel Bristot de Oliveira 
1704bc4b131SDaniel Bristot de Oliveira 	if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))
1714bc4b131SDaniel Bristot de Oliveira 		usage(0, "help");
1724bc4b131SDaniel Bristot de Oliveira 
1734bc4b131SDaniel Bristot de Oliveira 	if (!strcmp(argv[1], "list"))
1744bc4b131SDaniel Bristot de Oliveira 		rv_list(--argc, &argv[1]);
1754bc4b131SDaniel Bristot de Oliveira 
1764bc4b131SDaniel Bristot de Oliveira 	if (!strcmp(argv[1], "mon")) {
1774bc4b131SDaniel Bristot de Oliveira 		/*
1784bc4b131SDaniel Bristot de Oliveira 		 * monitor's main should monitor should_stop() function.
1794bc4b131SDaniel Bristot de Oliveira 		 * and exit.
1804bc4b131SDaniel Bristot de Oliveira 		 */
1814bc4b131SDaniel Bristot de Oliveira 		signal(SIGINT, stop_rv);
1824bc4b131SDaniel Bristot de Oliveira 
1834bc4b131SDaniel Bristot de Oliveira 		rv_mon(argc - 1, &argv[1]);
1844bc4b131SDaniel Bristot de Oliveira 	}
1854bc4b131SDaniel Bristot de Oliveira 
1864bc4b131SDaniel Bristot de Oliveira 	/* invalid sub-command */
1874bc4b131SDaniel Bristot de Oliveira 	usage(1, "%s does not know the %s command, old version?", argv[0], argv[1]);
1884bc4b131SDaniel Bristot de Oliveira }
189