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
47 #define TERM_CMD_BUF_SIZE 4095
54 #define printf do_not_use_printf
56 static char term_cmd_buf[TERM_CMD_BUF_SIZE + 1];
57 static int term_cmd_buf_index;
58 static int term_cmd_buf_size;
59 static int term_esc_state;
60 static int term_esc_param;
62 typedef struct term_cmd_t {
64 void (*handler)(int argc, const char **argv);
69 static term_cmd_t term_cmds[];
70 static term_cmd_t info_cmds[];
72 void term_printf(const char *fmt, ...)
85 static int compare_cmd(const char *name, const char *list)
87 const char *p, *pstart;
95 p = pstart + strlen(pstart);
96 if ((p - pstart) == len && !memcmp(pstart, name, len))
105 static void help_cmd1(term_cmd_t *cmds, const char *prefix, const char *name)
109 for(cmd = cmds; cmd->name != NULL; cmd++) {
110 if (!name || !strcmp(name, cmd->name))
111 term_printf("%s%s %s -- %s\n", prefix, cmd->name, cmd->params, cmd->help);
115 static void help_cmd(const char *name)
117 if (name && !strcmp(name, "info")) {
118 help_cmd1(info_cmds, "info ", NULL);
120 help_cmd1(term_cmds, "", name);
121 if (name && !strcmp(name, "log")) {
123 term_printf("Log items (comma separated):\n");
124 term_printf("%-10s %s\n", "none", "remove all logs");
125 for(item = cpu_log_items; item->mask != 0; item++) {
126 term_printf("%-10s %s\n", item->name, item->help);
132 static void do_help(int argc, const char **argv)
137 static void do_commit(int argc, const char **argv)
141 for (i = 0; i < MAX_DISKS; i++) {
143 bdrv_commit(bs_table[i]);
147 static void do_info(int argc, const char **argv)
155 for(cmd = info_cmds; cmd->name != NULL; cmd++) {
156 if (compare_cmd(argv[1], cmd->name))
163 cmd->handler(argc, argv);
166 static void do_info_network(int argc, const char **argv)
171 for(i = 0; i < nb_nics; i++) {
173 term_printf("%d: ifname=%s macaddr=", i, nd->ifname);
174 for(j = 0; j < 6; j++) {
177 term_printf("%02x", nd->macaddr[j]);
183 static void do_info_block(int argc, const char **argv)
188 static void do_quit(int argc, const char **argv)
193 static int eject_device(BlockDriverState *bs, int force)
195 if (bdrv_is_inserted(bs)) {
197 if (!bdrv_is_removable(bs)) {
198 term_printf("device is not removable\n");
201 if (bdrv_is_locked(bs)) {
202 term_printf("device is locked\n");
211 static void do_eject(int argc, const char **argv)
213 BlockDriverState *bs;
224 if (!strcmp(*parg, "-f")) {
230 bs = bdrv_find(*parg);
232 term_printf("device not found\n");
235 eject_device(bs, force);
238 static void do_change(int argc, const char **argv)
240 BlockDriverState *bs;
246 bs = bdrv_find(argv[1]);
248 term_printf("device not found\n");
251 if (eject_device(bs, 0) < 0)
253 bdrv_open(bs, argv[2], 0);
256 static void do_screen_dump(int argc, const char **argv)
262 vga_screen_dump(argv[1]);
265 static void do_log(int argc, const char **argv)
271 if (!strcmp(argv[1], "none")) {
274 mask = cpu_str_to_log_mask(argv[1]);
284 static term_cmd_t term_cmds[] = {
286 "[cmd]", "show the help" },
287 { "commit", do_commit,
288 "", "commit changes to the disk images (if -snapshot is used)" },
290 "subcommand", "show various information about the system state" },
292 "", "quit the emulator" },
294 "[-f] device", "eject a removable media (use -f to force it)" },
295 { "change", do_change,
296 "device filename", "change a removable media" },
297 { "screendump", do_screen_dump,
298 "filename", "save screen into PPM image 'filename'" },
300 "item1[,...]", "activate logging of the specified items to '/tmp/qemu.log'" },
304 static term_cmd_t info_cmds[] = {
305 { "network", do_info_network,
306 "", "show the network state" },
307 { "block", do_info_block,
308 "", "show the block devices" },
312 static void term_handle_command(char *cmdline)
316 const char *args[MAX_ARGS + 1];
320 term_printf("command='%s'\n", cmdline);
323 /* split command in words */
332 while (*p != '\0' && !isspace(*p))
336 if (argc >= MAX_ARGS)
344 for(i=0;i<argc;i++) {
345 term_printf(" '%s'", args[i]);
351 for(cmd = term_cmds; cmd->name != NULL; cmd++) {
352 if (compare_cmd(args[0], cmd->name))
355 term_printf("unknown command: '%s'\n", args[0]);
358 cmd->handler(argc, args);
361 static void term_show_prompt(void)
363 term_printf("(qemu) ");
365 term_cmd_buf_index = 0;
366 term_cmd_buf_size = 0;
367 term_esc_state = IS_NORM;
370 static void term_insert_char(int ch)
372 if (term_cmd_buf_index < TERM_CMD_BUF_SIZE) {
373 memmove(term_cmd_buf + term_cmd_buf_index + 1,
374 term_cmd_buf + term_cmd_buf_index,
375 term_cmd_buf_size - term_cmd_buf_index);
376 term_cmd_buf[term_cmd_buf_index] = ch;
378 term_printf("\033[@%c", ch);
379 term_cmd_buf_index++;
384 static void term_backward_char(void)
386 if (term_cmd_buf_index > 0) {
387 term_cmd_buf_index--;
388 term_printf("\033[D");
393 static void term_forward_char(void)
395 if (term_cmd_buf_index < term_cmd_buf_size) {
396 term_cmd_buf_index++;
397 term_printf("\033[C");
402 static void term_delete_char(void)
404 if (term_cmd_buf_index < term_cmd_buf_size) {
405 memmove(term_cmd_buf + term_cmd_buf_index,
406 term_cmd_buf + term_cmd_buf_index + 1,
407 term_cmd_buf_size - term_cmd_buf_index - 1);
408 term_printf("\033[P");
414 static void term_backspace(void)
416 if (term_cmd_buf_index > 0) {
417 term_backward_char();
422 static void term_bol(void)
424 while (term_cmd_buf_index > 0)
425 term_backward_char();
428 static void term_eol(void)
430 while (term_cmd_buf_index < term_cmd_buf_size)
434 /* return true if command handled */
435 static void term_handle_byte(int ch)
437 switch(term_esc_state) {
448 term_cmd_buf[term_cmd_buf_size] = '\0';
450 term_handle_command(term_cmd_buf);
454 term_esc_state = IS_ESC;
462 term_insert_char(ch);
469 term_esc_state = IS_CSI;
472 term_esc_state = IS_NORM;
478 term_backward_char();
484 term_esc_param = term_esc_param * 10 + (ch - '0');
487 switch(term_esc_param) {
502 term_esc_state = IS_NORM;
508 /*************************************************************/
509 /* serial console support */
511 #define TERM_ESCAPE 0x01 /* ctrl-a is used for escape */
513 static int term_got_escape, term_command;
515 void term_print_help(void)
518 "C-a h print this help\n"
519 "C-a x exit emulatior\n"
520 "C-a s save disk data back to file (if -snapshot)\n"
521 "C-a b send break (magic sysrq)\n"
522 "C-a c switch between console and monitor\n"
527 /* called when a char is received */
528 static void term_received_byte(int ch)
530 if (!serial_console) {
531 /* if no serial console, handle every command */
532 term_handle_byte(ch);
534 if (term_got_escape) {
546 for (i = 0; i < MAX_DISKS; i++) {
548 bdrv_commit(bs_table[i]);
554 serial_receive_break(serial_console);
567 } else if (ch == TERM_ESCAPE) {
572 term_handle_byte(ch);
575 serial_receive_byte(serial_console, ch);
581 static int term_can_read(void *opaque)
583 if (serial_console) {
584 return serial_can_receive(serial_console);
590 static void term_read(void *opaque, const uint8_t *buf, int size)
593 for(i = 0; i < size; i++)
594 term_received_byte(buf[i]);
597 void monitor_init(void)
599 if (!serial_console) {
600 term_printf("QEMU %s monitor - type 'help' for more information\n",
604 add_fd_read_handler(0, term_can_read, term_read, NULL);