4 * Copyright (c) 2003-2004 Fabrice Bellard
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:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
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
30 #define offsetof(type, field) ((size_t) &((type *)0)->field)
33 #define TERM_CMD_BUF_SIZE 4095
39 #define printf do_not_use_printf
41 static char term_cmd_buf[TERM_CMD_BUF_SIZE + 1];
42 static int term_cmd_buf_index;
43 static int term_cmd_buf_size;
44 static int term_esc_state;
45 static int term_esc_param;
51 * 's' string (accept optional quote)
53 * '/' optional gdb-like print format (like "/10x")
55 * '?' optional type (for 'F', 's' and 'i')
59 typedef struct term_cmd_t {
61 const char *args_type;
67 static term_cmd_t term_cmds[];
68 static term_cmd_t info_cmds[];
70 void term_printf(const char *fmt, ...)
83 static int compare_cmd(const char *name, const char *list)
85 const char *p, *pstart;
93 p = pstart + strlen(pstart);
94 if ((p - pstart) == len && !memcmp(pstart, name, len))
103 static void help_cmd1(term_cmd_t *cmds, const char *prefix, const char *name)
107 for(cmd = cmds; cmd->name != NULL; cmd++) {
108 if (!name || !strcmp(name, cmd->name))
109 term_printf("%s%s %s -- %s\n", prefix, cmd->name, cmd->params, cmd->help);
113 static void help_cmd(const char *name)
115 if (name && !strcmp(name, "info")) {
116 help_cmd1(info_cmds, "info ", NULL);
118 help_cmd1(term_cmds, "", name);
119 if (name && !strcmp(name, "log")) {
121 term_printf("Log items (comma separated):\n");
122 term_printf("%-10s %s\n", "none", "remove all logs");
123 for(item = cpu_log_items; item->mask != 0; item++) {
124 term_printf("%-10s %s\n", item->name, item->help);
130 static void do_help(const char *name)
135 static void do_commit(void)
139 for (i = 0; i < MAX_DISKS; i++) {
141 bdrv_commit(bs_table[i]);
145 static void do_info(const char *item)
151 for(cmd = info_cmds; cmd->name != NULL; cmd++) {
152 if (compare_cmd(item, cmd->name))
162 static void do_info_network(void)
167 for(i = 0; i < nb_nics; i++) {
169 term_printf("%d: ifname=%s macaddr=", i, nd->ifname);
170 for(j = 0; j < 6; j++) {
173 term_printf("%02x", nd->macaddr[j]);
179 static void do_info_block(void)
184 static void do_info_registers(void)
187 cpu_dump_state(cpu_single_env, stdout, X86_DUMP_FPU | X86_DUMP_CCOP);
189 cpu_dump_state(cpu_single_env, stdout, 0);
193 static void do_quit(void)
198 static int eject_device(BlockDriverState *bs, int force)
200 if (bdrv_is_inserted(bs)) {
202 if (!bdrv_is_removable(bs)) {
203 term_printf("device is not removable\n");
206 if (bdrv_is_locked(bs)) {
207 term_printf("device is locked\n");
216 static void do_eject(int force, const char *filename)
218 BlockDriverState *bs;
220 term_printf("%d %s\n", force, filename);
222 bs = bdrv_find(filename);
224 term_printf("device not found\n");
227 eject_device(bs, force);
230 static void do_change(const char *device, const char *filename)
232 BlockDriverState *bs;
234 bs = bdrv_find(device);
236 term_printf("device not found\n");
239 if (eject_device(bs, 0) < 0)
241 bdrv_open(bs, filename, 0);
244 static void do_screen_dump(const char *filename)
246 vga_screen_dump(filename);
249 static void do_log(const char *items)
253 if (!strcmp(items, "none")) {
256 mask = cpu_str_to_log_mask(items);
265 static void do_savevm(const char *filename)
267 if (qemu_savevm(filename) < 0)
268 term_printf("I/O error when saving VM to '%s'\n", filename);
271 static void do_loadvm(const char *filename)
273 if (qemu_loadvm(filename) < 0)
274 term_printf("I/O error when loading VM from '%s'\n", filename);
277 static void do_stop(void)
279 vm_stop(EXCP_INTERRUPT);
282 static void do_cont(void)
287 #ifdef CONFIG_GDBSTUB
288 static void do_gdbserver(int has_port, int port)
291 port = DEFAULT_GDBSTUB_PORT;
292 if (gdbserver_start(port) < 0) {
293 qemu_printf("Could not open gdbserver socket on port %d\n", port);
295 qemu_printf("Waiting gdb connection on port %d\n", port);
300 static void term_printc(int c)
317 if (c >= 32 && c <= 126) {
318 term_printf("%c", c);
320 term_printf("\\x%02x", c);
327 static void memory_dump(int count, int format, int wsize,
328 target_ulong addr, int is_physical)
330 int nb_per_line, l, line_size, i, max_digits, len;
338 /* we use the current CS size */
339 if (!(cpu_single_env->segs[R_CS].flags & DESC_B_MASK))
342 monitor_disas(addr, count, is_physical, flags);
351 nb_per_line = line_size / wsize;
356 max_digits = (wsize * 8 + 2) / 3;
360 max_digits = (wsize * 8) / 4;
364 max_digits = (wsize * 8 * 10 + 32) / 33;
372 term_printf("0x%08x:", addr);
377 cpu_physical_memory_rw(addr, buf, l, 0);
379 cpu_memory_rw_debug(cpu_single_env, addr, buf, l, 0);
386 v = ldub_raw(buf + i);
389 v = lduw_raw(buf + i);
392 v = ldl_raw(buf + i);
395 v = ldq_raw(buf + i);
401 term_printf("%#*llo", max_digits, v);
404 term_printf("0x%0*llx", max_digits, v);
407 term_printf("%*llu", max_digits, v);
410 term_printf("%*lld", max_digits, v);
424 static void do_memory_dump(int count, int format, int size, int addr)
426 memory_dump(count, format, size, addr, 0);
429 static void do_physical_memory_dump(int count, int format, int size, int addr)
431 memory_dump(count, format, size, addr, 1);
434 static void do_print(int count, int format, int size, int val)
438 term_printf("%#o", val);
441 term_printf("%#x", val);
444 term_printf("%u", val);
448 term_printf("%d", val);
457 static term_cmd_t term_cmds[] = {
458 { "help|?", "s?", do_help,
459 "[cmd]", "show the help" },
460 { "commit", "", do_commit,
461 "", "commit changes to the disk images (if -snapshot is used)" },
462 { "info", "s?", do_info,
463 "subcommand", "show various information about the system state" },
464 { "q|quit", "", do_quit,
465 "", "quit the emulator" },
466 { "eject", "-fs", do_eject,
467 "[-f] device", "eject a removable media (use -f to force it)" },
468 { "change", "sF", do_change,
469 "device filename", "change a removable media" },
470 { "screendump", "F", do_screen_dump,
471 "filename", "save screen into PPM image 'filename'" },
472 { "log", "s", do_log,
473 "item1[,...]", "activate logging of the specified items to '/tmp/qemu.log'" },
474 { "savevm", "F", do_savevm,
475 "filename", "save the whole virtual machine state to 'filename'" },
476 { "loadvm", "F", do_loadvm,
477 "filename", "restore the whole virtual machine state from 'filename'" },
478 { "stop", "", do_stop,
479 "", "stop emulation", },
480 { "c|cont", "", do_cont,
481 "", "resume emulation", },
482 #ifdef CONFIG_GDBSTUB
483 { "gdbserver", "i?", do_gdbserver,
484 "[port]", "start gdbserver session (default port=1234)", },
486 { "x", "/i", do_memory_dump,
487 "/fmt addr", "virtual memory dump starting at 'addr'", },
488 { "xp", "/i", do_physical_memory_dump,
489 "/fmt addr", "physical memory dump starting at 'addr'", },
490 { "p|print", "/i", do_print,
491 "/fmt expr", "print expression value (use $reg for CPU register access)", },
495 static term_cmd_t info_cmds[] = {
496 { "network", "", do_info_network,
497 "", "show the network state" },
498 { "block", "", do_info_block,
499 "", "show the block devices" },
500 { "registers", "", do_info_registers,
501 "", "show the cpu registers" },
505 /*******************************************************************/
507 static const char *pch;
508 static jmp_buf expr_env;
510 typedef struct MonitorDef {
513 int (*get_value)(struct MonitorDef *md);
516 static MonitorDef monitor_defs[] = {
518 { "eax", offsetof(CPUState, regs[0]) },
519 { "ecx", offsetof(CPUState, regs[1]) },
520 { "edx", offsetof(CPUState, regs[2]) },
521 { "ebx", offsetof(CPUState, regs[3]) },
522 { "esp|sp", offsetof(CPUState, regs[4]) },
523 { "ebp|fp", offsetof(CPUState, regs[5]) },
524 { "esi", offsetof(CPUState, regs[6]) },
525 { "esi", offsetof(CPUState, regs[7]) },
526 { "eflags", offsetof(CPUState, eflags) },
527 { "eip|pc", offsetof(CPUState, eip) },
532 static void expr_error(const char *fmt)
536 longjmp(expr_env, 1);
539 static int get_monitor_def(int *pval, const char *name)
542 for(md = monitor_defs; md->name != NULL; md++) {
543 if (compare_cmd(name, md->name)) {
545 *pval = md->get_value(md);
547 *pval = *(uint32_t *)((uint8_t *)cpu_single_env + md->offset);
555 static void next(void)
559 while (isspace(*pch))
564 static int expr_sum(void);
566 static int expr_unary(void)
588 expr_error("')' expected");
598 while ((*pch >= 'a' && *pch <= 'z') ||
599 (*pch >= 'A' && *pch <= 'Z') ||
600 (*pch >= '0' && *pch <= '9') ||
602 if ((q - buf) < sizeof(buf) - 1)
606 while (isspace(*pch))
609 if (get_monitor_def(&n, buf))
610 expr_error("unknown register");
614 expr_error("unexpected end of expression");
618 n = strtoul(pch, &p, 0);
620 expr_error("invalid char in expression");
623 while (isspace(*pch))
631 static int expr_prod(void)
638 if (op != '*' && op != '/' && op != '%')
650 expr_error("divison by zero");
661 static int expr_logic(void)
668 if (op != '&' && op != '|' && op != '^')
688 static int expr_sum(void)
695 if (op != '+' && op != '-')
707 static int get_expr(int *pval, const char **pp)
710 if (setjmp(expr_env)) {
714 while (isspace(*pch))
721 static int get_str(char *buf, int buf_size, const char **pp)
738 while (*p != '\0' && *p != '\"') {
754 qemu_printf("unsupported escape code: '\\%c'\n", c);
757 if ((q - buf) < buf_size - 1) {
761 if ((q - buf) < buf_size - 1) {
768 qemu_printf("untermintated string\n");
773 while (*p != '\0' && !isspace(*p)) {
774 if ((q - buf) < buf_size - 1) {
785 static int default_fmt_format = 'x';
786 static int default_fmt_size = 4;
790 static void term_handle_command(const char *cmdline)
792 const char *p, *pstart, *typestr;
794 int c, nb_args, len, i, has_arg;
798 void *str_allocated[MAX_ARGS];
799 void *args[MAX_ARGS];
802 term_printf("command='%s'\n", cmdline);
805 /* extract the command name */
813 while (*p != '\0' && *p != '/' && !isspace(*p))
816 if (len > sizeof(cmdname) - 1)
817 len = sizeof(cmdname) - 1;
818 memcpy(cmdname, pstart, len);
821 /* find the command */
822 for(cmd = term_cmds; cmd->name != NULL; cmd++) {
823 if (compare_cmd(cmdname, cmd->name))
826 term_printf("unknown command: '%s'\n", cmdname);
830 for(i = 0; i < MAX_ARGS; i++)
831 str_allocated[i] = NULL;
833 /* parse the parameters */
834 typestr = cmd->args_type;
850 if (*typestr == '?') {
853 /* no optional string: NULL argument */
858 ret = get_str(buf, sizeof(buf), &p);
861 term_printf("%s: filename expected\n", cmdname);
863 term_printf("%s: string expected\n", cmdname);
866 str = qemu_malloc(strlen(buf) + 1);
868 str_allocated[nb_args] = str;
870 if (nb_args >= MAX_ARGS) {
872 term_printf("%s: too many arguments\n", cmdname);
875 args[nb_args++] = str;
880 int count, format, size;
890 while (isdigit(*p)) {
891 count = count * 10 + (*p - '0');
929 if (*p != '\0' && !isspace(*p)) {
930 term_printf("invalid char in format: '%c'\n", *p);
934 size = default_fmt_size;
936 format = default_fmt_format;
937 default_fmt_size = size;
938 default_fmt_format = format;
941 format = default_fmt_format;
942 size = default_fmt_size;
944 if (nb_args + 3 > MAX_ARGS)
946 args[nb_args++] = (void*)count;
947 args[nb_args++] = (void*)format;
948 args[nb_args++] = (void*)size;
956 if (*typestr == '?') {
962 if (nb_args >= MAX_ARGS)
964 args[nb_args++] = (void *)has_arg;
966 if (nb_args >= MAX_ARGS)
972 if (get_expr(&val, &p))
975 if (nb_args >= MAX_ARGS)
977 args[nb_args++] = (void *)val;
994 term_printf("%s: unsupported option -%c\n",
1001 if (nb_args >= MAX_ARGS)
1003 args[nb_args++] = (void *)has_option;
1008 term_printf("%s: unknown type '%c'\n", cmdname, c);
1012 /* check that all arguments were parsed */
1016 term_printf("%s: extraneous characters at the end of line\n",
1026 cmd->handler(args[0]);
1029 cmd->handler(args[0], args[1]);
1032 cmd->handler(args[0], args[1], args[2]);
1035 cmd->handler(args[0], args[1], args[2], args[3]);
1038 cmd->handler(args[0], args[1], args[2], args[3], args[4]);
1041 term_printf("unsupported number of arguments: %d\n", nb_args);
1045 for(i = 0; i < MAX_ARGS; i++)
1046 qemu_free(str_allocated[i]);
1050 static void term_show_prompt(void)
1052 term_printf("(qemu) ");
1054 term_cmd_buf_index = 0;
1055 term_cmd_buf_size = 0;
1056 term_esc_state = IS_NORM;
1059 static void term_insert_char(int ch)
1061 if (term_cmd_buf_index < TERM_CMD_BUF_SIZE) {
1062 memmove(term_cmd_buf + term_cmd_buf_index + 1,
1063 term_cmd_buf + term_cmd_buf_index,
1064 term_cmd_buf_size - term_cmd_buf_index);
1065 term_cmd_buf[term_cmd_buf_index] = ch;
1066 term_cmd_buf_size++;
1067 term_printf("\033[@%c", ch);
1068 term_cmd_buf_index++;
1073 static void term_backward_char(void)
1075 if (term_cmd_buf_index > 0) {
1076 term_cmd_buf_index--;
1077 term_printf("\033[D");
1082 static void term_forward_char(void)
1084 if (term_cmd_buf_index < term_cmd_buf_size) {
1085 term_cmd_buf_index++;
1086 term_printf("\033[C");
1091 static void term_delete_char(void)
1093 if (term_cmd_buf_index < term_cmd_buf_size) {
1094 memmove(term_cmd_buf + term_cmd_buf_index,
1095 term_cmd_buf + term_cmd_buf_index + 1,
1096 term_cmd_buf_size - term_cmd_buf_index - 1);
1097 term_printf("\033[P");
1098 term_cmd_buf_size--;
1103 static void term_backspace(void)
1105 if (term_cmd_buf_index > 0) {
1106 term_backward_char();
1111 static void term_bol(void)
1113 while (term_cmd_buf_index > 0)
1114 term_backward_char();
1117 static void term_eol(void)
1119 while (term_cmd_buf_index < term_cmd_buf_size)
1120 term_forward_char();
1123 /* return true if command handled */
1124 static void term_handle_byte(int ch)
1126 switch(term_esc_state) {
1137 term_cmd_buf[term_cmd_buf_size] = '\0';
1139 term_handle_command(term_cmd_buf);
1143 term_esc_state = IS_ESC;
1151 term_insert_char(ch);
1158 term_esc_state = IS_CSI;
1161 term_esc_state = IS_NORM;
1167 term_backward_char();
1170 term_forward_char();
1173 term_esc_param = term_esc_param * 10 + (ch - '0');
1176 switch(term_esc_param) {
1191 term_esc_state = IS_NORM;
1197 /*************************************************************/
1198 /* serial console support */
1200 #define TERM_ESCAPE 0x01 /* ctrl-a is used for escape */
1202 static int term_got_escape, term_command;
1204 void term_print_help(void)
1207 "C-a h print this help\n"
1208 "C-a x exit emulatior\n"
1209 "C-a s save disk data back to file (if -snapshot)\n"
1210 "C-a b send break (magic sysrq)\n"
1211 "C-a c switch between console and monitor\n"
1212 "C-a C-a send C-a\n"
1216 /* called when a char is received */
1217 static void term_received_byte(int ch)
1219 if (!serial_console) {
1220 /* if no serial console, handle every command */
1221 term_handle_byte(ch);
1223 if (term_got_escape) {
1224 term_got_escape = 0;
1235 for (i = 0; i < MAX_DISKS; i++) {
1237 bdrv_commit(bs_table[i]);
1243 serial_receive_break(serial_console);
1246 if (!term_command) {
1256 } else if (ch == TERM_ESCAPE) {
1257 term_got_escape = 1;
1261 term_handle_byte(ch);
1264 serial_receive_byte(serial_console, ch);
1270 static int term_can_read(void *opaque)
1272 if (serial_console) {
1273 return serial_can_receive(serial_console);
1279 static void term_read(void *opaque, const uint8_t *buf, int size)
1282 for(i = 0; i < size; i++)
1283 term_received_byte(buf[i]);
1286 void monitor_init(void)
1288 if (!serial_console) {
1289 term_printf("QEMU %s monitor - type 'help' for more information\n",
1293 qemu_add_fd_read_handler(0, term_can_read, term_read, NULL);