2 * Jailhouse, a Linux-based partitioning hypervisor
4 * Copyright (c) Siemens AG, 2013-2016
7 * Jan Kiszka <jan.kiszka@siemens.com>
9 * This work is licensed under the terms of the GNU GPL, version 2. See
10 * the COPYING file in the top-level directory.
22 #include <sys/types.h>
23 #include <sys/ioctl.h>
26 #include <jailhouse.h>
28 #define JAILHOUSE_EXEC_DIR LIBEXECDIR "/jailhouse"
30 enum shutdown_load_mode {LOAD, SHUTDOWN};
33 char *cmd, *subcmd, *help;
36 static const struct extension extensions[] = {
37 { "cell", "linux", "CELLCONFIG KERNEL [-i | --initrd FILE]\n"
38 " [-c | --cmdline \"STRING\"] "
39 "[-w | --write-params FILE]" },
40 { "cell", "list", "" },
41 { "cell", "stats", "{ ID | [--name] NAME }" },
42 { "config", "create", "[-h] [-g] [-r ROOT] "
43 "[--mem-inmates MEM_INMATES]\n"
44 " [--mem-hv MEM_HV] FILE" },
45 { "config", "collect", "FILE.TAR" },
46 { "hardware", "check", "SYSCONFIG" },
50 static void __attribute__((noreturn)) help(char *prog, int exit_status)
52 const struct extension *ext;
54 printf("Usage: %s { COMMAND | --help || --version }\n"
55 "\nAvailable commands:\n"
58 " cell create CELLCONFIG\n"
59 " cell load { ID | [--name] NAME } "
60 "{ IMAGE | { -s | --string } \"STRING\" }\n"
61 " [-a | --address ADDRESS] ...\n"
62 " cell start { ID | [--name] NAME }\n"
63 " cell shutdown { ID | [--name] NAME }\n"
64 " cell destroy { ID | [--name] NAME }\n",
66 for (ext = extensions; ext->cmd; ext++)
67 printf(" %s %s %s\n", ext->cmd, ext->subcmd, ext->help);
72 static void call_extension_script(const char *cmd, int argc, char *argv[])
74 const struct extension *ext;
75 char new_path[PATH_MAX];
81 for (ext = extensions; ext->cmd; ext++) {
82 if (strcmp(ext->cmd, cmd) != 0 ||
83 strcmp(ext->subcmd, argv[2]) != 0)
86 snprintf(new_path, sizeof(new_path), "PATH=%s:%s:%s",
87 dirname(argv[0]), JAILHOUSE_EXEC_DIR,
88 getenv("PATH") ? : "");
91 snprintf(script, sizeof(script), "jailhouse-%s-%s",
93 execvp(script, &argv[2]);
100 static int open_dev()
104 fd = open("/dev/jailhouse", O_RDWR);
106 perror("opening /dev/jailhouse");
112 static void *read_string(const char *string, size_t *size)
116 *size = strlen(string) + 1;
118 buffer = strdup(string);
120 fprintf(stderr, "insufficient memory\n");
127 static void *read_file(const char *name, size_t *size)
133 fd = open(name, O_RDONLY);
135 fprintf(stderr, "opening %s: %s\n", name, strerror(errno));
139 if (fstat(fd, &stat) < 0) {
144 buffer = malloc(stat.st_size);
146 fprintf(stderr, "insufficient memory\n");
150 if (read(fd, buffer, stat.st_size) < stat.st_size) {
151 fprintf(stderr, "reading %s: %s\n", name, strerror(errno));
158 *size = stat.st_size;
163 static int enable(int argc, char *argv[])
171 config = read_file(argv[2], NULL);
175 err = ioctl(fd, JAILHOUSE_ENABLE, config);
177 perror("JAILHOUSE_ENABLE");
185 static int cell_create(int argc, char *argv[])
187 struct jailhouse_cell_create cell_create;
194 cell_create.config_address = (unsigned long)read_file(argv[3], &size);
195 cell_create.config_size = size;
199 err = ioctl(fd, JAILHOUSE_CELL_CREATE, &cell_create);
201 perror("JAILHOUSE_CELL_CREATE");
204 free((void *)(unsigned long)cell_create.config_address);
209 static int parse_cell_id(struct jailhouse_cell_id *cell_id, int argc,
212 bool use_name = false;
216 memset(cell_id, 0, sizeof(*cell_id));
221 if (strcmp(argv[0], "--name") == 0) {
228 cell_id->id = strtoll(argv[0], &endp, 0);
229 if (errno != 0 || *endp != 0 || cell_id->id < 0)
234 cell_id->id = JAILHOUSE_CELL_ID_UNUSED;
235 /* cell_id is initialized with zeros, so leaving out the last
236 * byte ensures that the string is always terminated. */
237 strncpy(cell_id->name, argv[arg_pos],
238 sizeof(cell_id->name) - 1);
244 static bool match_opt(const char *argv, const char *short_opt,
245 const char *long_opt)
247 return strcmp(argv, short_opt) == 0 ||
248 strcmp(argv, long_opt) == 0;
251 static int cell_shutdown_load(int argc, char *argv[],
252 enum shutdown_load_mode mode)
254 struct jailhouse_preload_image *image;
255 struct jailhouse_cell_load *cell_load;
256 struct jailhouse_cell_id cell_id;
257 int err, fd, id_args, arg_num;
258 unsigned int images, n;
262 id_args = parse_cell_id(&cell_id, argc - 3, &argv[3]);
263 arg_num = 3 + id_args;
264 if (id_args == 0 || (mode == SHUTDOWN && arg_num != argc) ||
265 (mode == LOAD && arg_num == argc))
269 while (arg_num < argc) {
270 if (match_opt(argv[arg_num], "-s", "--string")) {
271 if (arg_num + 1 >= argc)
279 if (arg_num < argc &&
280 match_opt(argv[arg_num], "-a", "--address")) {
281 if (arg_num + 1 >= argc)
287 cell_load = malloc(sizeof(*cell_load) + sizeof(*image) * images);
289 fprintf(stderr, "insufficient memory\n");
292 cell_load->cell_id = cell_id;
293 cell_load->num_preload_images = images;
295 arg_num = 3 + id_args;
297 for (n = 0, image = cell_load->image; n < images; n++, image++) {
298 if (match_opt(argv[arg_num], "-s", "--string")) {
300 image->source_address =
301 (unsigned long)read_string(argv[arg_num++],
304 image->source_address =
305 (unsigned long)read_file(argv[arg_num++],
309 image->target_address = 0;
311 if (arg_num < argc &&
312 match_opt(argv[arg_num], "-a", "--address")) {
314 image->target_address =
315 strtoll(argv[arg_num + 1], &endp, 0);
316 if (errno != 0 || *endp != 0)
324 err = ioctl(fd, JAILHOUSE_CELL_LOAD, cell_load);
326 perror("JAILHOUSE_CELL_LOAD");
329 for (n = 0, image = cell_load->image; n < images; n++, image++)
330 free((void *)(unsigned long)image->source_address);
336 static int cell_simple_cmd(int argc, char *argv[], unsigned int command)
338 struct jailhouse_cell_id cell_id;
339 int id_args, err, fd;
341 id_args = parse_cell_id(&cell_id, argc - 3, &argv[3]);
342 if (id_args == 0 || 3 + id_args != argc)
347 err = ioctl(fd, command, &cell_id);
349 perror(command == JAILHOUSE_CELL_START ?
350 "JAILHOUSE_CELL_START" :
351 command == JAILHOUSE_CELL_DESTROY ?
352 "JAILHOUSE_CELL_DESTROY" :
353 "<unknown command>");
360 static int cell_management(int argc, char *argv[])
367 if (strcmp(argv[2], "create") == 0) {
368 err = cell_create(argc, argv);
369 } else if (strcmp(argv[2], "load") == 0) {
370 err = cell_shutdown_load(argc, argv, LOAD);
371 } else if (strcmp(argv[2], "start") == 0) {
372 err = cell_simple_cmd(argc, argv, JAILHOUSE_CELL_START);
373 } else if (strcmp(argv[2], "shutdown") == 0) {
374 err = cell_shutdown_load(argc, argv, SHUTDOWN);
375 } else if (strcmp(argv[2], "destroy") == 0) {
376 err = cell_simple_cmd(argc, argv, JAILHOUSE_CELL_DESTROY);
378 call_extension_script("cell", argc, argv);
385 int main(int argc, char *argv[])
393 if (strcmp(argv[1], "enable") == 0) {
394 err = enable(argc, argv);
395 } else if (strcmp(argv[1], "disable") == 0) {
397 err = ioctl(fd, JAILHOUSE_DISABLE);
399 perror("JAILHOUSE_DISABLE");
401 } else if (strcmp(argv[1], "cell") == 0) {
402 err = cell_management(argc, argv);
403 } else if (strcmp(argv[1], "config") == 0 ||
404 strcmp(argv[1], "hardware") == 0) {
405 call_extension_script(argv[1], argc, argv);
407 } else if (strcmp(argv[1], "--version") == 0) {
408 printf("Jailhouse management tool %s\n", JAILHOUSE_VERSION);
410 } else if (strcmp(argv[1], "--help") == 0) {