2 * Jailhouse, a Linux-based partitioning hypervisor
4 * Copyright (c) Siemens AG, 2013
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 enum shutdown_load_mode {LOAD, SHUTDOWN};
31 char *cmd, *subcmd, *help;
34 static const struct extension extensions[] = {
35 { "cell", "list", "" },
36 { "cell", "stats", "{ ID | [--name] NAME }" },
40 static void __attribute__((noreturn)) help(char *prog, int exit_status)
42 const struct extension *ext;
44 printf("Usage: %s { COMMAND | --help }\n"
45 "\nAvailable commands:\n"
48 " cell create CELLCONFIG\n"
49 " cell load { ID | [--name] NAME } IMAGE "
50 "[ -a | --address ADDRESS] ...\n"
51 " cell start { ID | [--name] NAME }\n"
52 " cell shutdown { ID | [--name] NAME }\n"
53 " cell destroy { ID | [--name] NAME }\n",
55 for (ext = extensions; ext->cmd; ext++)
56 printf(" %s %s %s\n", ext->cmd, ext->subcmd, ext->help);
61 static void call_extension_script(const char *cmd, int argc, char *argv[])
63 const struct extension *ext;
64 char new_path[PATH_MAX];
70 for (ext = extensions; ext->cmd; ext++) {
71 if (strcmp(ext->cmd, cmd) != 0 ||
72 strcmp(ext->subcmd, argv[2]) != 0)
75 snprintf(new_path, sizeof(new_path), "PATH=%s:%s:%s",
76 dirname(argv[0]), "/usr/lib/jailhouse",
77 getenv("PATH") ? : "");
80 snprintf(script, sizeof(script), "jailhouse-%s-%s",
82 execvp(script, &argv[2]);
93 fd = open("/dev/jailhouse", O_RDWR);
95 perror("opening /dev/jailhouse");
101 static void *read_file(const char *name, size_t *size)
107 fd = open(name, O_RDONLY);
109 fprintf(stderr, "opening %s: %s\n", name, strerror(errno));
113 if (fstat(fd, &stat) < 0) {
118 buffer = malloc(stat.st_size);
120 fprintf(stderr, "insufficient memory\n");
124 if (read(fd, buffer, stat.st_size) < stat.st_size) {
125 fprintf(stderr, "reading %s: %s\n", name, strerror(errno));
132 *size = stat.st_size;
137 static int enable(int argc, char *argv[])
145 config = read_file(argv[2], NULL);
149 err = ioctl(fd, JAILHOUSE_ENABLE, config);
151 perror("JAILHOUSE_ENABLE");
159 static int cell_create(int argc, char *argv[])
161 struct jailhouse_cell_create cell_create;
168 cell_create.config_address = (unsigned long)read_file(argv[3], &size);
169 cell_create.config_size = size;
173 err = ioctl(fd, JAILHOUSE_CELL_CREATE, &cell_create);
175 perror("JAILHOUSE_CELL_CREATE");
182 static int parse_cell_id(struct jailhouse_cell_id *cell_id, int argc,
185 bool use_name = false;
192 if (strcmp(argv[0], "--name") == 0) {
199 cell_id->id = strtoll(argv[0], &endp, 0);
200 if (errno != 0 || *endp != 0 || cell_id->id < 0)
205 cell_id->id = JAILHOUSE_CELL_ID_UNUSED;
206 strncpy(cell_id->name, argv[arg_pos], sizeof(cell_id->name));
207 cell_id->name[sizeof(cell_id->name) - 1] = 0;
213 static bool match_opt(const char *argv, const char *short_opt,
214 const char *long_opt)
216 return strcmp(argv, short_opt) == 0 ||
217 strcmp(argv, long_opt) == 0;
220 static int cell_shutdown_load(int argc, char *argv[],
221 enum shutdown_load_mode mode)
223 unsigned int images, id_args, arg_num, n;
224 struct jailhouse_preload_image *image;
225 struct jailhouse_cell_load *cell_load;
226 struct jailhouse_cell_id cell_id;
231 id_args = parse_cell_id(&cell_id, argc - 3, &argv[3]);
232 arg_num = 3 + id_args;
233 if (id_args == 0 || (mode == SHUTDOWN && arg_num != argc) ||
234 (mode == LOAD && arg_num == argc))
238 while (arg_num < argc) {
242 if (arg_num < argc &&
243 match_opt(argv[arg_num], "-a", "--address")) {
244 if (arg_num + 1 >= argc)
250 cell_load = malloc(sizeof(*cell_load) + sizeof(*image) * images);
252 fprintf(stderr, "insufficient memory\n");
255 cell_load->cell_id = cell_id;
256 cell_load->num_preload_images = images;
258 arg_num = 3 + id_args;
260 for (n = 0, image = cell_load->image; n < images; n++, image++) {
261 image->source_address =
262 (unsigned long)read_file(argv[arg_num++], &size);
264 image->target_address = 0;
266 if (arg_num < argc &&
267 match_opt(argv[arg_num], "-a", "--address")) {
269 image->target_address =
270 strtoll(argv[arg_num + 1], &endp, 0);
271 if (errno != 0 || *endp != 0)
279 err = ioctl(fd, JAILHOUSE_CELL_LOAD, cell_load);
281 perror("JAILHOUSE_CELL_LOAD");
284 for (n = 0, image = cell_load->image; n < images; n++, image++)
285 free((void *)(unsigned long)image->source_address);
291 static int cell_simple_cmd(int argc, char *argv[], unsigned int command)
293 struct jailhouse_cell_id cell_id;
294 int id_args, err, fd;
296 id_args = parse_cell_id(&cell_id, argc - 3, &argv[3]);
297 if (id_args == 0 || 3 + id_args != argc)
302 err = ioctl(fd, command, &cell_id);
304 perror(command == JAILHOUSE_CELL_START ?
305 "JAILHOUSE_CELL_START" :
306 command == JAILHOUSE_CELL_DESTROY ?
307 "JAILHOUSE_CELL_DESTROY" :
308 "<unknown command>");
315 static int cell_management(int argc, char *argv[])
322 if (strcmp(argv[2], "create") == 0) {
323 err = cell_create(argc, argv);
324 } else if (strcmp(argv[2], "load") == 0) {
325 err = cell_shutdown_load(argc, argv, LOAD);
326 } else if (strcmp(argv[2], "start") == 0) {
327 err = cell_simple_cmd(argc, argv, JAILHOUSE_CELL_START);
328 } else if (strcmp(argv[2], "shutdown") == 0) {
329 err = cell_shutdown_load(argc, argv, SHUTDOWN);
330 } else if (strcmp(argv[2], "destroy") == 0) {
331 err = cell_simple_cmd(argc, argv, JAILHOUSE_CELL_DESTROY);
333 call_extension_script("cell", argc, argv);
340 int main(int argc, char *argv[])
348 if (strcmp(argv[1], "enable") == 0) {
349 err = enable(argc, argv);
350 } else if (strcmp(argv[1], "disable") == 0) {
352 err = ioctl(fd, JAILHOUSE_DISABLE);
354 perror("JAILHOUSE_DISABLE");
356 } else if (strcmp(argv[1], "cell") == 0) {
357 err = cell_management(argc, argv);
358 } else if (strcmp(argv[1], "--help") == 0) {