ia64/xen-unstable

view tools/ioemu/monitor.c @ 9137:eb24eb6bc341

Fix some warnings when compiling tools.

Signed-off-by: Xin Li <xin.b.li@intel.com>
author kaf24@firebug.cl.cam.ac.uk
date Sat Mar 04 10:25:05 2006 +0100 (2006-03-04)
parents f1b361b05bf3
children a5a50f6fbc09
line source
1 /*
2 * QEMU monitor
3 *
4 * Copyright (c) 2003-2004 Fabrice Bellard
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24 #include "vl.h"
25 #include <dirent.h>
27 //#define DEBUG
28 //#define DEBUG_COMPLETION
30 #ifndef offsetof
31 #define offsetof(type, field) ((size_t) &((type *)0)->field)
32 #endif
34 /*
35 * Supported types:
36 *
37 * 'F' filename
38 * 'B' block device name
39 * 's' string (accept optional quote)
40 * 'i' integer
41 * '/' optional gdb-like print format (like "/10x")
42 *
43 * '?' optional type (for 'F', 's' and 'i')
44 *
45 */
47 typedef struct term_cmd_t {
48 const char *name;
49 const char *args_type;
50 void (*handler)();
51 const char *params;
52 const char *help;
53 } term_cmd_t;
55 static CharDriverState *monitor_hd;
57 static term_cmd_t term_cmds[];
58 static term_cmd_t info_cmds[];
60 static char term_outbuf[1024];
61 static int term_outbuf_index;
63 static void monitor_start_input(void);
65 void term_flush(void)
66 {
67 if (term_outbuf_index > 0) {
68 if(monitor_hd)
69 qemu_chr_write(monitor_hd, term_outbuf, term_outbuf_index);
70 else
71 fwrite(term_outbuf, term_outbuf_index, 1, stderr);
72 term_outbuf_index = 0;
73 }
74 }
76 /* flush at every end of line or if the buffer is full */
77 void term_puts(const char *str)
78 {
79 int c;
80 for(;;) {
81 c = *str++;
82 if (c == '\0')
83 break;
84 term_outbuf[term_outbuf_index++] = c;
85 if (term_outbuf_index >= sizeof(term_outbuf) ||
86 c == '\n')
87 term_flush();
88 }
89 }
91 void term_vprintf(const char *fmt, va_list ap)
92 {
93 char buf[4096];
94 vsnprintf(buf, sizeof(buf), fmt, ap);
95 term_puts(buf);
96 }
98 void term_printf(const char *fmt, ...)
99 {
100 va_list ap;
101 va_start(ap, fmt);
102 term_vprintf(fmt, ap);
103 va_end(ap);
104 }
106 static int compare_cmd(const char *name, const char *list)
107 {
108 const char *p, *pstart;
109 int len;
110 len = strlen(name);
111 p = list;
112 for(;;) {
113 pstart = p;
114 p = strchr(p, '|');
115 if (!p)
116 p = pstart + strlen(pstart);
117 if ((p - pstart) == len && !memcmp(pstart, name, len))
118 return 1;
119 if (*p == '\0')
120 break;
121 p++;
122 }
123 return 0;
124 }
126 static void help_cmd1(term_cmd_t *cmds, const char *prefix, const char *name)
127 {
128 term_cmd_t *cmd;
130 for(cmd = cmds; cmd->name != NULL; cmd++) {
131 if (!name || !strcmp(name, cmd->name))
132 term_printf("%s%s %s -- %s\n", prefix, cmd->name, cmd->params, cmd->help);
133 }
134 }
136 static void help_cmd(const char *name)
137 {
138 if (name && !strcmp(name, "info")) {
139 help_cmd1(info_cmds, "info ", NULL);
140 } else {
141 help_cmd1(term_cmds, "", name);
142 if (name && !strcmp(name, "log")) {
143 CPULogItem *item;
144 term_printf("Log items (comma separated):\n");
145 term_printf("%-10s %s\n", "none", "remove all logs");
146 for(item = cpu_log_items; item->mask != 0; item++) {
147 term_printf("%-10s %s\n", item->name, item->help);
148 }
149 }
150 }
151 }
153 static void do_help(const char *name)
154 {
155 help_cmd(name);
156 }
158 static void do_commit(void)
159 {
160 int i;
162 for (i = 0; i < MAX_DISKS; i++) {
163 if (bs_table[i]) {
164 bdrv_commit(bs_table[i]);
165 }
166 }
167 }
169 static void do_info(const char *item)
170 {
171 term_cmd_t *cmd;
173 if (!item)
174 goto help;
175 for(cmd = info_cmds; cmd->name != NULL; cmd++) {
176 if (compare_cmd(item, cmd->name))
177 goto found;
178 }
179 help:
180 help_cmd("info");
181 return;
182 found:
183 cmd->handler();
184 }
186 static void do_info_version(void)
187 {
188 term_printf("%s\n", QEMU_VERSION);
189 }
191 static void do_info_network(void)
192 {
193 int i, j;
194 NetDriverState *nd;
196 for(i = 0; i < nb_nics; i++) {
197 nd = &nd_table[i];
198 term_printf("%d: ifname=%s macaddr=", i, nd->ifname);
199 for(j = 0; j < 6; j++) {
200 if (j > 0)
201 term_printf(":");
202 term_printf("%02x", nd->macaddr[j]);
203 }
204 term_printf("\n");
205 }
206 }
208 static void do_info_block(void)
209 {
210 bdrv_info();
211 }
213 static void do_info_history (void)
214 {
215 int i;
216 const char *str;
218 i = 0;
219 for(;;) {
220 str = readline_get_history(i);
221 if (!str)
222 break;
223 term_printf("%d: '%s'\n", i, str);
224 i++;
225 }
226 }
228 extern void destroy_hvm_domain(void);
229 static void do_quit(void)
230 {
231 destroy_hvm_domain();
232 exit(0);
233 }
235 typedef struct {
236 int keycode;
237 const char *name;
238 } KeyDef;
240 static const KeyDef key_defs[] = {
241 { 0x2a, "shift" },
242 { 0x36, "shift_r" },
244 { 0x38, "alt" },
245 { 0xb8, "alt_r" },
246 { 0x1d, "ctrl" },
247 { 0x9d, "ctrl_r" },
249 { 0xdd, "menu" },
251 { 0x01, "esc" },
253 { 0x02, "1" },
254 { 0x03, "2" },
255 { 0x04, "3" },
256 { 0x05, "4" },
257 { 0x06, "5" },
258 { 0x07, "6" },
259 { 0x08, "7" },
260 { 0x09, "8" },
261 { 0x0a, "9" },
262 { 0x0b, "0" },
263 { 0x0e, "backspace" },
265 { 0x0f, "tab" },
266 { 0x10, "q" },
267 { 0x11, "w" },
268 { 0x12, "e" },
269 { 0x13, "r" },
270 { 0x14, "t" },
271 { 0x15, "y" },
272 { 0x16, "u" },
273 { 0x17, "i" },
274 { 0x18, "o" },
275 { 0x19, "p" },
277 { 0x1c, "ret" },
279 { 0x1e, "a" },
280 { 0x1f, "s" },
281 { 0x20, "d" },
282 { 0x21, "f" },
283 { 0x22, "g" },
284 { 0x23, "h" },
285 { 0x24, "j" },
286 { 0x25, "k" },
287 { 0x26, "l" },
289 { 0x2c, "z" },
290 { 0x2d, "x" },
291 { 0x2e, "c" },
292 { 0x2f, "v" },
293 { 0x30, "b" },
294 { 0x31, "n" },
295 { 0x32, "m" },
297 { 0x39, "spc" },
298 { 0x3a, "caps_lock" },
299 { 0x3b, "f1" },
300 { 0x3c, "f2" },
301 { 0x3d, "f3" },
302 { 0x3e, "f4" },
303 { 0x3f, "f5" },
304 { 0x40, "f6" },
305 { 0x41, "f7" },
306 { 0x42, "f8" },
307 { 0x43, "f9" },
308 { 0x44, "f10" },
309 { 0x45, "num_lock" },
310 { 0x46, "scroll_lock" },
312 { 0x56, "<" },
314 { 0x57, "f11" },
315 { 0x58, "f12" },
317 { 0xb7, "print" },
319 { 0xc7, "home" },
320 { 0xc9, "pgup" },
321 { 0xd1, "pgdn" },
322 { 0xcf, "end" },
324 { 0xcb, "left" },
325 { 0xc8, "up" },
326 { 0xd0, "down" },
327 { 0xcd, "right" },
329 { 0xd2, "insert" },
330 { 0xd3, "delete" },
331 { 0, NULL },
332 };
334 static int get_keycode(const char *key)
335 {
336 const KeyDef *p;
338 for(p = key_defs; p->name != NULL; p++) {
339 if (!strcmp(key, p->name))
340 return p->keycode;
341 }
342 return -1;
343 }
345 static void do_send_key(const char *string)
346 {
347 char keybuf[16], *q;
348 uint8_t keycodes[16];
349 const char *p;
350 int nb_keycodes, keycode, i;
352 nb_keycodes = 0;
353 p = string;
354 while (*p != '\0') {
355 q = keybuf;
356 while (*p != '\0' && *p != '-') {
357 if ((q - keybuf) < sizeof(keybuf) - 1) {
358 *q++ = *p;
359 }
360 p++;
361 }
362 *q = '\0';
363 keycode = get_keycode(keybuf);
364 if (keycode < 0) {
365 term_printf("unknown key: '%s'\n", keybuf);
366 return;
367 }
368 keycodes[nb_keycodes++] = keycode;
369 if (*p == '\0')
370 break;
371 p++;
372 }
373 /* key down events */
374 for(i = 0; i < nb_keycodes; i++) {
375 keycode = keycodes[i];
376 if (keycode & 0x80)
377 kbd_put_keycode(0xe0);
378 kbd_put_keycode(keycode & 0x7f);
379 }
380 /* key up events */
381 for(i = nb_keycodes - 1; i >= 0; i--) {
382 keycode = keycodes[i];
383 if (keycode & 0x80)
384 kbd_put_keycode(0xe0);
385 kbd_put_keycode(keycode | 0x80);
386 }
387 }
390 static int eject_device(BlockDriverState *bs, int force)
391 {
392 if (bdrv_is_inserted(bs)) {
393 if (!force) {
394 if (!bdrv_is_removable(bs)) {
395 term_printf("device is not removable\n");
396 return -1;
397 }
398 if (bdrv_is_locked(bs)) {
399 term_printf("device is locked\n");
400 return -1;
401 }
402 }
403 bdrv_close(bs);
404 }
405 return 0;
406 }
408 static void do_eject(int force, const char *filename)
409 {
410 BlockDriverState *bs;
412 bs = bdrv_find(filename);
413 if (!bs) {
414 term_printf("device not found\n");
415 return;
416 }
417 eject_device(bs, force);
418 }
420 static void do_change(const char *device, const char *filename)
421 {
422 BlockDriverState *bs;
423 #if 0
424 int i;
425 char password[256];
426 #endif
428 bs = bdrv_find(device);
429 if (!bs) {
430 term_printf("device not found\n");
431 return;
432 }
433 if (eject_device(bs, 0) < 0)
434 return;
435 bdrv_open(bs, filename, 0);
436 #if 0
437 if (bdrv_is_encrypted(bs)) {
438 term_printf("%s is encrypted.\n", device);
439 for(i = 0; i < 3; i++) {
440 monitor_readline("Password: ", 1, password, sizeof(password));
441 if (bdrv_set_key(bs, password) == 0)
442 break;
443 term_printf("invalid password\n");
444 }
445 }
446 #endif
447 }
449 static void do_screen_dump(const char *filename)
450 {
451 vga_screen_dump(filename);
452 }
454 static void do_log(const char *items)
455 {
456 int mask;
458 if (!strcmp(items, "none")) {
459 mask = 0;
460 } else {
461 mask = cpu_str_to_log_mask(items);
462 if (!mask) {
463 help_cmd("log");
464 return;
465 }
466 }
467 cpu_set_log(mask);
468 }
470 static term_cmd_t term_cmds[] = {
471 { "help|?", "s?", do_help,
472 "[cmd]", "show the help" },
473 { "commit", "", do_commit,
474 "", "commit changes to the disk images (if -snapshot is used)" },
475 { "info", "s?", do_info,
476 "subcommand", "show various information about the system state" },
477 { "q|quit", "", do_quit,
478 "", "quit the emulator" },
479 { "eject", "-fB", do_eject,
480 "[-f] device", "eject a removable media (use -f to force it)" },
481 { "change", "BF", do_change,
482 "device filename", "change a removable media" },
483 { "screendump", "F", do_screen_dump,
484 "filename", "save screen into PPM image 'filename'" },
485 { "log", "s", do_log,
486 "item1[,...]", "activate logging of the specified items to '/tmp/qemu.log'" },
487 { "q|quit", "", do_quit,
488 "", "quit the emulator" },
489 { "sendkey", "s", do_send_key,
490 "keys", "send keys to the VM (e.g. 'sendkey ctrl-alt-f1')" },
491 { NULL, NULL, },
492 };
494 static term_cmd_t info_cmds[] = {
495 { "version", "", do_info_version,
496 "", "show the version of qemu" },
497 { "network", "", do_info_network,
498 "", "show the network state" },
499 { "block", "", do_info_block,
500 "", "show the block devices" },
501 { "history", "", do_info_history,
502 "", "show the command line history", },
503 { "irq", "", irq_info,
504 "", "show the interrupts statistics (if available)", },
505 { "pic", "", pic_info,
506 "", "show i8259 (PIC) state", },
507 { "pci", "", pci_info,
508 "", "show PCI info", },
509 { "hvmiopage", "", sp_info,
510 "", "show HVM device model shared page info", },
511 { NULL, NULL, },
512 };
514 static int get_str(char *buf, int buf_size, const char **pp)
515 {
516 const char *p;
517 char *q;
518 int c;
520 q = buf;
521 p = *pp;
522 while (isspace(*p))
523 p++;
524 if (*p == '\0') {
525 fail:
526 *q = '\0';
527 *pp = p;
528 return -1;
529 }
530 if (*p == '\"') {
531 p++;
532 while (*p != '\0' && *p != '\"') {
533 if (*p == '\\') {
534 p++;
535 c = *p++;
536 switch(c) {
537 case 'n':
538 c = '\n';
539 break;
540 case 'r':
541 c = '\r';
542 break;
543 case '\\':
544 case '\'':
545 case '\"':
546 break;
547 default:
548 qemu_printf("unsupported escape code: '\\%c'\n", c);
549 goto fail;
550 }
551 if ((q - buf) < buf_size - 1) {
552 *q++ = c;
553 }
554 } else {
555 if ((q - buf) < buf_size - 1) {
556 *q++ = *p;
557 }
558 p++;
559 }
560 }
561 if (*p != '\"') {
562 qemu_printf("unterminated string\n");
563 goto fail;
564 }
565 p++;
566 } else {
567 while (*p != '\0' && !isspace(*p)) {
568 if ((q - buf) < buf_size - 1) {
569 *q++ = *p;
570 }
571 p++;
572 }
573 }
574 *q = '\0';
575 *pp = p;
576 return 0;
577 }
579 #define MAX_ARGS 16
581 static void monitor_handle_command(const char *cmdline)
582 {
583 const char *p, *pstart, *typestr;
584 char *q;
585 int c, nb_args, len, i;
586 term_cmd_t *cmd;
587 char cmdname[256];
588 char buf[1024];
589 void *str_allocated[MAX_ARGS];
590 void *args[MAX_ARGS];
592 #ifdef DEBUG
593 term_printf("command='%s'\n", cmdline);
594 #endif
596 /* extract the command name */
597 p = cmdline;
598 q = cmdname;
599 while (isspace(*p))
600 p++;
601 if (*p == '\0')
602 return;
603 pstart = p;
604 while (*p != '\0' && *p != '/' && !isspace(*p))
605 p++;
606 len = p - pstart;
607 if (len > sizeof(cmdname) - 1)
608 len = sizeof(cmdname) - 1;
609 memcpy(cmdname, pstart, len);
610 cmdname[len] = '\0';
612 /* find the command */
613 for(cmd = term_cmds; cmd->name != NULL; cmd++) {
614 if (compare_cmd(cmdname, cmd->name))
615 goto found;
616 }
617 term_printf("unknown command: '%s'\n", cmdname);
618 return;
619 found:
621 for(i = 0; i < MAX_ARGS; i++)
622 str_allocated[i] = NULL;
624 /* parse the parameters */
625 typestr = cmd->args_type;
626 nb_args = 0;
627 for(;;) {
628 c = *typestr;
629 if (c == '\0')
630 break;
631 typestr++;
632 switch(c) {
633 case 'F':
634 case 'B':
635 case 's':
636 {
637 int ret;
638 char *str;
640 while (isspace(*p))
641 p++;
642 if (*typestr == '?') {
643 typestr++;
644 if (*p == '\0') {
645 /* no optional string: NULL argument */
646 str = NULL;
647 goto add_str;
648 }
649 }
650 ret = get_str(buf, sizeof(buf), &p);
651 if (ret < 0) {
652 switch(c) {
653 case 'F':
654 term_printf("%s: filename expected\n", cmdname);
655 break;
656 case 'B':
657 term_printf("%s: block device name expected\n", cmdname);
658 break;
659 default:
660 term_printf("%s: string expected\n", cmdname);
661 break;
662 }
663 goto fail;
664 }
665 str = qemu_malloc(strlen(buf) + 1);
666 strcpy(str, buf);
667 str_allocated[nb_args] = str;
668 add_str:
669 if (nb_args >= MAX_ARGS) {
670 error_args:
671 term_printf("%s: too many arguments\n", cmdname);
672 goto fail;
673 }
674 args[nb_args++] = str;
675 }
676 break;
677 case '-':
678 {
679 long has_option;
680 /* option */
682 c = *typestr++;
683 if (c == '\0')
684 goto bad_type;
685 while (isspace(*p))
686 p++;
687 has_option = 0;
688 if (*p == '-') {
689 p++;
690 if (*p != c) {
691 term_printf("%s: unsupported option -%c\n",
692 cmdname, *p);
693 goto fail;
694 }
695 p++;
696 has_option = 1;
697 }
698 if (nb_args >= MAX_ARGS)
699 goto error_args;
700 args[nb_args++] = (void *)has_option;
701 }
702 break;
703 /* TODO: add more commands we need here to support hvm device model */
704 case '/':
705 case 'i':
706 default:
707 bad_type:
708 term_printf("%s: unknown type '%c',not support now.\n", cmdname, c);
709 goto fail;
710 }
711 }
712 /* check that all arguments were parsed */
713 while (isspace(*p))
714 p++;
715 if (*p != '\0') {
716 term_printf("%s: extraneous characters at the end of line\n",
717 cmdname);
718 goto fail;
719 }
721 switch(nb_args) {
722 case 0:
723 cmd->handler();
724 break;
725 case 1:
726 cmd->handler(args[0]);
727 break;
728 case 2:
729 cmd->handler(args[0], args[1]);
730 break;
731 case 3:
732 cmd->handler(args[0], args[1], args[2]);
733 break;
734 case 4:
735 cmd->handler(args[0], args[1], args[2], args[3]);
736 break;
737 case 5:
738 cmd->handler(args[0], args[1], args[2], args[3], args[4]);
739 break;
740 case 6:
741 cmd->handler(args[0], args[1], args[2], args[3], args[4], args[5]);
742 break;
743 default:
744 term_printf("unsupported number of arguments: %d\n", nb_args);
745 goto fail;
746 }
747 fail:
748 for(i = 0; i < MAX_ARGS; i++)
749 qemu_free(str_allocated[i]);
750 return;
751 }
753 static int term_can_read(void *opaque)
754 {
755 return 128;
756 }
758 static void term_read(void *opaque, const uint8_t *buf, int size)
759 {
760 int i;
761 for(i = 0; i < size; i++)
762 readline_handle_byte(buf[i]);
763 }
765 static void monitor_start_input(void);
767 static void monitor_handle_command1(void *opaque, const char *cmdline)
768 {
769 monitor_handle_command(cmdline);
770 monitor_start_input();
771 }
773 static void monitor_start_input(void)
774 {
775 readline_start("(HVMXen) ", 0, monitor_handle_command1, NULL);
776 }
778 void monitor_init(CharDriverState *hd, int show_banner)
779 {
780 monitor_hd = hd;
781 if (show_banner) {
782 term_printf("HVM device model. type 'q' to exit\n");
783 }
784 qemu_chr_add_read_handler(hd, term_can_read, term_read, NULL);
785 monitor_start_input();
786 }