]> rtime.felk.cvut.cz Git - jailhouse.git/blob - tools/jailhouse.c
driver/tools: Break up cell creation
[jailhouse.git] / tools / jailhouse.c
1 /*
2  * Jailhouse, a Linux-based partitioning hypervisor
3  *
4  * Copyright (c) Siemens AG, 2013
5  *
6  * Authors:
7  *  Jan Kiszka <jan.kiszka@siemens.com>
8  *
9  * This work is licensed under the terms of the GNU GPL, version 2.  See
10  * the COPYING file in the top-level directory.
11  */
12
13 #include <stdbool.h>
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <unistd.h>
18 #include <fcntl.h>
19 #include <errno.h>
20 #include <sys/types.h>
21 #include <sys/ioctl.h>
22 #include <sys/stat.h>
23
24 #include <jailhouse.h>
25
26 static void __attribute__((noreturn))
27 help(const char *progname, int exit_status)
28 {
29         printf("%s { COMMAND | --help }\n"
30                "\nAvailable commands:\n"
31                "   enable SYSCONFIG\n"
32                "   disable\n"
33                "   cell create CELLCONFIG\n"
34                "   cell load { ID | [--name] NAME } IMAGE "
35                         "[ -a | --address ADDRESS] ...\n"
36                "   cell start { ID | [--name] NAME }\n"
37                "   cell destroy { ID | [--name] NAME }\n",
38                progname);
39         exit(exit_status);
40 }
41
42 static int open_dev()
43 {
44         int fd;
45
46         fd = open("/dev/jailhouse", O_RDWR);
47         if (fd < 0) {
48                 perror("opening /dev/jailhouse");
49                 exit(1);
50         }
51         return fd;
52 }
53
54 static void *read_file(const char *name, size_t *size)
55 {
56         struct stat stat;
57         void *buffer;
58         int fd;
59
60         fd = open(name, O_RDONLY);
61         if (fd < 0) {
62                 fprintf(stderr, "opening %s: %s\n", name, strerror(errno));
63                 exit(1);
64         }
65
66         if (fstat(fd, &stat) < 0) {
67                 perror("fstat");
68                 exit(1);
69         }
70
71         buffer = malloc(stat.st_size);
72         if (!buffer) {
73                 fprintf(stderr, "insufficient memory\n");
74                 exit(1);
75         }
76
77         if (read(fd, buffer, stat.st_size) < stat.st_size) {
78                 fprintf(stderr, "reading %s: %s\n", name, strerror(errno));
79                 exit(1);
80         }
81
82         close(fd);
83
84         if (size)
85                 *size = stat.st_size;
86
87         return buffer;
88 }
89
90 static int enable(int argc, char *argv[])
91 {
92         void *config;
93         int err, fd;
94
95         if (argc != 3)
96                 help(argv[0], 1);
97
98         config = read_file(argv[2], NULL);
99
100         fd = open_dev();
101
102         err = ioctl(fd, JAILHOUSE_ENABLE, config);
103         if (err)
104                 perror("JAILHOUSE_ENABLE");
105
106         close(fd);
107         free(config);
108
109         return err;
110 }
111
112 static int cell_create(int argc, char *argv[])
113 {
114         struct jailhouse_cell_create cell_create;
115         size_t size;
116         int err, fd;
117
118         if (argc != 4)
119                 help(argv[0], 1);
120
121         cell_create.config_address = (unsigned long)read_file(argv[3], &size);
122         cell_create.config_size = size;
123
124         fd = open_dev();
125
126         err = ioctl(fd, JAILHOUSE_CELL_CREATE, &cell_create);
127         if (err)
128                 perror("JAILHOUSE_CELL_CREATE");
129
130         close(fd);
131
132         return err;
133 }
134
135 static int parse_cell_id(struct jailhouse_cell_id *cell_id, int argc,
136                          char *argv[])
137 {
138         bool use_name = false;
139         int arg_pos = 0;
140         char *endp;
141
142         if (argc < 1)
143                 return 0;
144
145         if (strcmp(argv[0], "--name") == 0) {
146                 if (argc < 2)
147                         return 0;
148                 arg_pos++;
149                 use_name = true;
150         } else {
151                 errno = 0;
152                 cell_id->id = strtoll(argv[0], &endp, 0);
153                 if (errno != 0 || *endp != 0 || cell_id->id < 0)
154                         use_name = true;
155         }
156
157         if (use_name) {
158                 cell_id->id = JAILHOUSE_CELL_ID_UNUSED;
159                 strncpy(cell_id->name, argv[arg_pos], sizeof(cell_id->name));
160                 cell_id->name[sizeof(cell_id->name) - 1] = 0;
161         }
162
163         return arg_pos + 1;
164 }
165
166 static bool match_opt(const char *argv, const char *short_opt,
167                       const char *long_opt)
168 {
169         return strcmp(argv, short_opt) == 0 ||
170                 strcmp(argv, long_opt) == 0;
171 }
172
173 static int cell_load(int argc, char *argv[])
174 {
175         unsigned int images, id_args, arg_num, n;
176         struct jailhouse_preload_image *image;
177         struct jailhouse_cell_load *cell_load;
178         struct jailhouse_cell_id cell_id;
179         size_t size;
180         int err, fd;
181         char *endp;
182
183         id_args = parse_cell_id(&cell_id, argc - 3, &argv[3]);
184         arg_num = 3 + id_args;
185         if (id_args == 0 || arg_num == argc)
186                 help(argv[0], 1);
187
188         images = 0;
189         while (arg_num < argc) {
190                 images++;
191                 arg_num++;
192
193                 if (arg_num < argc &&
194                     match_opt(argv[arg_num], "-a", "--address")) {
195                         if (arg_num + 1 >= argc)
196                                 help(argv[0], 1);
197                         arg_num += 2;
198                 }
199         }
200
201         cell_load = malloc(sizeof(*cell_load) + sizeof(*image) * images);
202         if (!cell_load) {
203                 fprintf(stderr, "insufficient memory\n");
204                 exit(1);
205         }
206         cell_load->cell_id = cell_id;
207         cell_load->num_preload_images = images;
208
209         arg_num = 3 + id_args;
210
211         for (n = 0, image = cell_load->image; n < images; n++, image++) {
212                 image->source_address =
213                         (unsigned long)read_file(argv[arg_num++], &size);
214                 image->size = size;
215                 image->target_address = 0;
216
217                 if (arg_num < argc &&
218                     match_opt(argv[arg_num], "-a", "--address")) {
219                         errno = 0;
220                         image->target_address =
221                                 strtoll(argv[arg_num + 1], &endp, 0);
222                         if (errno != 0 || *endp != 0)
223                                 help(argv[0], 1);
224                         arg_num += 2;
225                 }
226                 image++;
227         }
228
229         fd = open_dev();
230
231         err = ioctl(fd, JAILHOUSE_CELL_LOAD, cell_load);
232         if (err)
233                 perror("JAILHOUSE_CELL_LOAD");
234
235         close(fd);
236         for (n = 0, image = cell_load->image; n < images; n++, image++)
237                 free((void *)(unsigned long)image->source_address);
238         free(cell_load);
239
240         return err;
241 }
242
243 static int cell_simple_cmd(int argc, char *argv[], unsigned int command)
244 {
245         struct jailhouse_cell_id cell_id;
246         int id_args, err, fd;
247
248         id_args = parse_cell_id(&cell_id, argc - 3, &argv[3]);
249         if (id_args == 0 || 3 + id_args != argc)
250                 help(argv[0], 1);
251
252         fd = open_dev();
253
254         err = ioctl(fd, command, &cell_id);
255         if (err)
256                 perror(command == JAILHOUSE_CELL_START ?
257                        "JAILHOUSE_CELL_START" :
258                        command == JAILHOUSE_CELL_DESTROY ?
259                        "JAILHOUSE_CELL_DESTROY" :
260                        "<unknown command>");
261
262         close(fd);
263
264         return err;
265 }
266
267 static int cell_management(int argc, char *argv[])
268 {
269         int err;
270
271         if (argc < 3)
272                 help(argv[0], 1);
273
274         if (strcmp(argv[2], "create") == 0)
275                 err = cell_create(argc, argv);
276         else if (strcmp(argv[2], "load") == 0)
277                 err = cell_load(argc, argv);
278         else if (strcmp(argv[2], "start") == 0)
279                 err = cell_simple_cmd(argc, argv, JAILHOUSE_CELL_START);
280         else if (strcmp(argv[2], "destroy") == 0)
281                 err = cell_simple_cmd(argc, argv, JAILHOUSE_CELL_DESTROY);
282         else
283                 help(argv[0], 1);
284
285         return err;
286 }
287
288 int main(int argc, char *argv[])
289 {
290         int fd;
291         int err;
292
293         if (argc < 2)
294                 help(argv[0], 1);
295
296         if (strcmp(argv[1], "enable") == 0) {
297                 err = enable(argc, argv);
298         } else if (strcmp(argv[1], "disable") == 0) {
299                 fd = open_dev();
300                 err = ioctl(fd, JAILHOUSE_DISABLE);
301                 if (err)
302                         perror("JAILHOUSE_DISABLE");
303                 close(fd);
304         } else if (strcmp(argv[1], "cell") == 0) {
305                 err = cell_management(argc, argv);
306         } else if (strcmp(argv[1], "--help") == 0) {
307                 help(argv[0], 0);
308         } else
309                 help(argv[0], 1);
310
311         return err ? 1 : 0;
312 }