root / monitor.c @ 9dc39cba
History | View | Annotate | Download (13.2 kB)
1 | 9dc39cba | bellard | /*
|
---|---|---|---|
2 | 9dc39cba | bellard | * QEMU monitor
|
3 | 9dc39cba | bellard | *
|
4 | 9dc39cba | bellard | * Copyright (c) 2003-2004 Fabrice Bellard
|
5 | 9dc39cba | bellard | *
|
6 | 9dc39cba | bellard | * Permission is hereby granted, free of charge, to any person obtaining a copy
|
7 | 9dc39cba | bellard | * of this software and associated documentation files (the "Software"), to deal
|
8 | 9dc39cba | bellard | * in the Software without restriction, including without limitation the rights
|
9 | 9dc39cba | bellard | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10 | 9dc39cba | bellard | * copies of the Software, and to permit persons to whom the Software is
|
11 | 9dc39cba | bellard | * furnished to do so, subject to the following conditions:
|
12 | 9dc39cba | bellard | *
|
13 | 9dc39cba | bellard | * The above copyright notice and this permission notice shall be included in
|
14 | 9dc39cba | bellard | * all copies or substantial portions of the Software.
|
15 | 9dc39cba | bellard | *
|
16 | 9dc39cba | bellard | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17 | 9dc39cba | bellard | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18 | 9dc39cba | bellard | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
19 | 9dc39cba | bellard | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20 | 9dc39cba | bellard | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
21 | 9dc39cba | bellard | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
22 | 9dc39cba | bellard | * THE SOFTWARE.
|
23 | 9dc39cba | bellard | */
|
24 | 9dc39cba | bellard | #include <stdlib.h> |
25 | 9dc39cba | bellard | #include <stdio.h> |
26 | 9dc39cba | bellard | #include <stdarg.h> |
27 | 9dc39cba | bellard | #include <string.h> |
28 | 9dc39cba | bellard | #include <getopt.h> |
29 | 9dc39cba | bellard | #include <inttypes.h> |
30 | 9dc39cba | bellard | #include <unistd.h> |
31 | 9dc39cba | bellard | #include <sys/mman.h> |
32 | 9dc39cba | bellard | #include <fcntl.h> |
33 | 9dc39cba | bellard | #include <signal.h> |
34 | 9dc39cba | bellard | #include <time.h> |
35 | 9dc39cba | bellard | #include <sys/time.h> |
36 | 9dc39cba | bellard | #include <malloc.h> |
37 | 9dc39cba | bellard | #include <termios.h> |
38 | 9dc39cba | bellard | #include <sys/poll.h> |
39 | 9dc39cba | bellard | #include <errno.h> |
40 | 9dc39cba | bellard | #include <ctype.h> |
41 | 9dc39cba | bellard | |
42 | 9dc39cba | bellard | #include "cpu.h" |
43 | 9dc39cba | bellard | #include "vl.h" |
44 | 9dc39cba | bellard | |
45 | 9dc39cba | bellard | //#define DEBUG
|
46 | 9dc39cba | bellard | |
47 | 9dc39cba | bellard | #define TERM_CMD_BUF_SIZE 4095 |
48 | 9dc39cba | bellard | #define MAX_ARGS 64 |
49 | 9dc39cba | bellard | |
50 | 9dc39cba | bellard | #define IS_NORM 0 |
51 | 9dc39cba | bellard | #define IS_ESC 1 |
52 | 9dc39cba | bellard | #define IS_CSI 2 |
53 | 9dc39cba | bellard | |
54 | 9dc39cba | bellard | #define printf do_not_use_printf
|
55 | 9dc39cba | bellard | |
56 | 9dc39cba | bellard | static char term_cmd_buf[TERM_CMD_BUF_SIZE + 1]; |
57 | 9dc39cba | bellard | static int term_cmd_buf_index; |
58 | 9dc39cba | bellard | static int term_cmd_buf_size; |
59 | 9dc39cba | bellard | static int term_esc_state; |
60 | 9dc39cba | bellard | static int term_esc_param; |
61 | 9dc39cba | bellard | |
62 | 9dc39cba | bellard | typedef struct term_cmd_t { |
63 | 9dc39cba | bellard | const char *name; |
64 | 9dc39cba | bellard | void (*handler)(int argc, const char **argv); |
65 | 9dc39cba | bellard | const char *params; |
66 | 9dc39cba | bellard | const char *help; |
67 | 9dc39cba | bellard | } term_cmd_t; |
68 | 9dc39cba | bellard | |
69 | 9dc39cba | bellard | static term_cmd_t term_cmds[];
|
70 | 9dc39cba | bellard | static term_cmd_t info_cmds[];
|
71 | 9dc39cba | bellard | |
72 | 9dc39cba | bellard | void term_printf(const char *fmt, ...) |
73 | 9dc39cba | bellard | { |
74 | 9dc39cba | bellard | va_list ap; |
75 | 9dc39cba | bellard | va_start(ap, fmt); |
76 | 9dc39cba | bellard | vprintf(fmt, ap); |
77 | 9dc39cba | bellard | va_end(ap); |
78 | 9dc39cba | bellard | } |
79 | 9dc39cba | bellard | |
80 | 9dc39cba | bellard | void term_flush(void) |
81 | 9dc39cba | bellard | { |
82 | 9dc39cba | bellard | fflush(stdout); |
83 | 9dc39cba | bellard | } |
84 | 9dc39cba | bellard | |
85 | 9dc39cba | bellard | static int compare_cmd(const char *name, const char *list) |
86 | 9dc39cba | bellard | { |
87 | 9dc39cba | bellard | const char *p, *pstart; |
88 | 9dc39cba | bellard | int len;
|
89 | 9dc39cba | bellard | len = strlen(name); |
90 | 9dc39cba | bellard | p = list; |
91 | 9dc39cba | bellard | for(;;) {
|
92 | 9dc39cba | bellard | pstart = p; |
93 | 9dc39cba | bellard | p = strchr(p, '|');
|
94 | 9dc39cba | bellard | if (!p)
|
95 | 9dc39cba | bellard | p = pstart + strlen(pstart); |
96 | 9dc39cba | bellard | if ((p - pstart) == len && !memcmp(pstart, name, len))
|
97 | 9dc39cba | bellard | return 1; |
98 | 9dc39cba | bellard | if (*p == '\0') |
99 | 9dc39cba | bellard | break;
|
100 | 9dc39cba | bellard | p++; |
101 | 9dc39cba | bellard | } |
102 | 9dc39cba | bellard | return 0; |
103 | 9dc39cba | bellard | } |
104 | 9dc39cba | bellard | |
105 | 9dc39cba | bellard | static void help_cmd1(term_cmd_t *cmds, const char *prefix, const char *name) |
106 | 9dc39cba | bellard | { |
107 | 9dc39cba | bellard | term_cmd_t *cmd; |
108 | 9dc39cba | bellard | |
109 | 9dc39cba | bellard | for(cmd = cmds; cmd->name != NULL; cmd++) { |
110 | 9dc39cba | bellard | if (!name || !strcmp(name, cmd->name))
|
111 | 9dc39cba | bellard | term_printf("%s%s %s -- %s\n", prefix, cmd->name, cmd->params, cmd->help);
|
112 | 9dc39cba | bellard | } |
113 | 9dc39cba | bellard | } |
114 | 9dc39cba | bellard | |
115 | 9dc39cba | bellard | static void help_cmd(const char *name) |
116 | 9dc39cba | bellard | { |
117 | 9dc39cba | bellard | if (name && !strcmp(name, "info")) { |
118 | 9dc39cba | bellard | help_cmd1(info_cmds, "info ", NULL); |
119 | 9dc39cba | bellard | } else {
|
120 | 9dc39cba | bellard | help_cmd1(term_cmds, "", name);
|
121 | 9dc39cba | bellard | } |
122 | 9dc39cba | bellard | } |
123 | 9dc39cba | bellard | |
124 | 9dc39cba | bellard | static void do_help(int argc, const char **argv) |
125 | 9dc39cba | bellard | { |
126 | 9dc39cba | bellard | help_cmd(argv[1]);
|
127 | 9dc39cba | bellard | } |
128 | 9dc39cba | bellard | |
129 | 9dc39cba | bellard | static void do_commit(int argc, const char **argv) |
130 | 9dc39cba | bellard | { |
131 | 9dc39cba | bellard | int i;
|
132 | 9dc39cba | bellard | |
133 | 9dc39cba | bellard | for (i = 0; i < MAX_DISKS; i++) { |
134 | 9dc39cba | bellard | if (bs_table[i])
|
135 | 9dc39cba | bellard | bdrv_commit(bs_table[i]); |
136 | 9dc39cba | bellard | } |
137 | 9dc39cba | bellard | } |
138 | 9dc39cba | bellard | |
139 | 9dc39cba | bellard | static void do_info(int argc, const char **argv) |
140 | 9dc39cba | bellard | { |
141 | 9dc39cba | bellard | term_cmd_t *cmd; |
142 | 9dc39cba | bellard | const char *item; |
143 | 9dc39cba | bellard | |
144 | 9dc39cba | bellard | if (argc < 2) |
145 | 9dc39cba | bellard | goto help;
|
146 | 9dc39cba | bellard | item = argv[1];
|
147 | 9dc39cba | bellard | for(cmd = info_cmds; cmd->name != NULL; cmd++) { |
148 | 9dc39cba | bellard | if (compare_cmd(argv[1], cmd->name)) |
149 | 9dc39cba | bellard | goto found;
|
150 | 9dc39cba | bellard | } |
151 | 9dc39cba | bellard | help:
|
152 | 9dc39cba | bellard | help_cmd(argv[0]);
|
153 | 9dc39cba | bellard | return;
|
154 | 9dc39cba | bellard | found:
|
155 | 9dc39cba | bellard | cmd->handler(argc, argv); |
156 | 9dc39cba | bellard | } |
157 | 9dc39cba | bellard | |
158 | 9dc39cba | bellard | static void do_info_network(int argc, const char **argv) |
159 | 9dc39cba | bellard | { |
160 | 9dc39cba | bellard | int i, j;
|
161 | 9dc39cba | bellard | NetDriverState *nd; |
162 | 9dc39cba | bellard | |
163 | 9dc39cba | bellard | for(i = 0; i < nb_nics; i++) { |
164 | 9dc39cba | bellard | nd = &nd_table[i]; |
165 | 9dc39cba | bellard | term_printf("%d: ifname=%s macaddr=", i, nd->ifname);
|
166 | 9dc39cba | bellard | for(j = 0; j < 6; j++) { |
167 | 9dc39cba | bellard | if (j > 0) |
168 | 9dc39cba | bellard | term_printf(":");
|
169 | 9dc39cba | bellard | term_printf("%02x", nd->macaddr[j]);
|
170 | 9dc39cba | bellard | } |
171 | 9dc39cba | bellard | term_printf("\n");
|
172 | 9dc39cba | bellard | } |
173 | 9dc39cba | bellard | } |
174 | 9dc39cba | bellard | |
175 | 9dc39cba | bellard | static void do_info_block(int argc, const char **argv) |
176 | 9dc39cba | bellard | { |
177 | 9dc39cba | bellard | bdrv_info(); |
178 | 9dc39cba | bellard | } |
179 | 9dc39cba | bellard | |
180 | 9dc39cba | bellard | static void do_quit(int argc, const char **argv) |
181 | 9dc39cba | bellard | { |
182 | 9dc39cba | bellard | exit(0);
|
183 | 9dc39cba | bellard | } |
184 | 9dc39cba | bellard | |
185 | 9dc39cba | bellard | static int eject_device(BlockDriverState *bs, int force) |
186 | 9dc39cba | bellard | { |
187 | 9dc39cba | bellard | if (bdrv_is_inserted(bs)) {
|
188 | 9dc39cba | bellard | if (!force) {
|
189 | 9dc39cba | bellard | if (!bdrv_is_removable(bs)) {
|
190 | 9dc39cba | bellard | term_printf("device is not removable\n");
|
191 | 9dc39cba | bellard | return -1; |
192 | 9dc39cba | bellard | } |
193 | 9dc39cba | bellard | if (bdrv_is_locked(bs)) {
|
194 | 9dc39cba | bellard | term_printf("device is locked\n");
|
195 | 9dc39cba | bellard | return -1; |
196 | 9dc39cba | bellard | } |
197 | 9dc39cba | bellard | } |
198 | 9dc39cba | bellard | bdrv_close(bs); |
199 | 9dc39cba | bellard | } |
200 | 9dc39cba | bellard | return 0; |
201 | 9dc39cba | bellard | } |
202 | 9dc39cba | bellard | |
203 | 9dc39cba | bellard | static void do_eject(int argc, const char **argv) |
204 | 9dc39cba | bellard | { |
205 | 9dc39cba | bellard | BlockDriverState *bs; |
206 | 9dc39cba | bellard | const char **parg; |
207 | 9dc39cba | bellard | int force;
|
208 | 9dc39cba | bellard | |
209 | 9dc39cba | bellard | parg = argv + 1;
|
210 | 9dc39cba | bellard | if (!*parg) {
|
211 | 9dc39cba | bellard | fail:
|
212 | 9dc39cba | bellard | help_cmd(argv[0]);
|
213 | 9dc39cba | bellard | return;
|
214 | 9dc39cba | bellard | } |
215 | 9dc39cba | bellard | force = 0;
|
216 | 9dc39cba | bellard | if (!strcmp(*parg, "-f")) { |
217 | 9dc39cba | bellard | force = 1;
|
218 | 9dc39cba | bellard | parg++; |
219 | 9dc39cba | bellard | } |
220 | 9dc39cba | bellard | if (!*parg)
|
221 | 9dc39cba | bellard | goto fail;
|
222 | 9dc39cba | bellard | bs = bdrv_find(*parg); |
223 | 9dc39cba | bellard | if (!bs) {
|
224 | 9dc39cba | bellard | term_printf("device not found\n");
|
225 | 9dc39cba | bellard | return;
|
226 | 9dc39cba | bellard | } |
227 | 9dc39cba | bellard | eject_device(bs, force); |
228 | 9dc39cba | bellard | } |
229 | 9dc39cba | bellard | |
230 | 9dc39cba | bellard | static void do_change(int argc, const char **argv) |
231 | 9dc39cba | bellard | { |
232 | 9dc39cba | bellard | BlockDriverState *bs; |
233 | 9dc39cba | bellard | |
234 | 9dc39cba | bellard | if (argc != 3) { |
235 | 9dc39cba | bellard | help_cmd(argv[0]);
|
236 | 9dc39cba | bellard | return;
|
237 | 9dc39cba | bellard | } |
238 | 9dc39cba | bellard | bs = bdrv_find(argv[1]);
|
239 | 9dc39cba | bellard | if (!bs) {
|
240 | 9dc39cba | bellard | term_printf("device not found\n");
|
241 | 9dc39cba | bellard | return;
|
242 | 9dc39cba | bellard | } |
243 | 9dc39cba | bellard | if (eject_device(bs, 0) < 0) |
244 | 9dc39cba | bellard | return;
|
245 | 9dc39cba | bellard | bdrv_open(bs, argv[2], 0); |
246 | 9dc39cba | bellard | } |
247 | 9dc39cba | bellard | |
248 | 9dc39cba | bellard | static term_cmd_t term_cmds[] = {
|
249 | 9dc39cba | bellard | { "help|?", do_help,
|
250 | 9dc39cba | bellard | "[cmd]", "show the help" }, |
251 | 9dc39cba | bellard | { "commit", do_commit,
|
252 | 9dc39cba | bellard | "", "commit changes to the disk images (if -snapshot is used)" }, |
253 | 9dc39cba | bellard | { "info", do_info,
|
254 | 9dc39cba | bellard | "subcommand", "show various information about the system state" }, |
255 | 9dc39cba | bellard | { "q|quit", do_quit,
|
256 | 9dc39cba | bellard | "", "quit the emulator" }, |
257 | 9dc39cba | bellard | { "eject", do_eject,
|
258 | 9dc39cba | bellard | "[-f] device", "eject a removable media (use -f to force it)" }, |
259 | 9dc39cba | bellard | { "change", do_change,
|
260 | 9dc39cba | bellard | "device filename", "change a removable media" }, |
261 | 9dc39cba | bellard | { NULL, NULL, }, |
262 | 9dc39cba | bellard | }; |
263 | 9dc39cba | bellard | |
264 | 9dc39cba | bellard | static term_cmd_t info_cmds[] = {
|
265 | 9dc39cba | bellard | { "network", do_info_network,
|
266 | 9dc39cba | bellard | "", "show the network state" }, |
267 | 9dc39cba | bellard | { "block", do_info_block,
|
268 | 9dc39cba | bellard | "", "show the block devices" }, |
269 | 9dc39cba | bellard | { NULL, NULL, }, |
270 | 9dc39cba | bellard | }; |
271 | 9dc39cba | bellard | |
272 | 9dc39cba | bellard | static void term_handle_command(char *cmdline) |
273 | 9dc39cba | bellard | { |
274 | 9dc39cba | bellard | char *p, *pstart;
|
275 | 9dc39cba | bellard | int argc;
|
276 | 9dc39cba | bellard | const char *args[MAX_ARGS + 1]; |
277 | 9dc39cba | bellard | term_cmd_t *cmd; |
278 | 9dc39cba | bellard | |
279 | 9dc39cba | bellard | #ifdef DEBUG
|
280 | 9dc39cba | bellard | term_printf("command='%s'\n", cmdline);
|
281 | 9dc39cba | bellard | #endif
|
282 | 9dc39cba | bellard | |
283 | 9dc39cba | bellard | /* split command in words */
|
284 | 9dc39cba | bellard | argc = 0;
|
285 | 9dc39cba | bellard | p = cmdline; |
286 | 9dc39cba | bellard | for(;;) {
|
287 | 9dc39cba | bellard | while (isspace(*p))
|
288 | 9dc39cba | bellard | p++; |
289 | 9dc39cba | bellard | if (*p == '\0') |
290 | 9dc39cba | bellard | break;
|
291 | 9dc39cba | bellard | pstart = p; |
292 | 9dc39cba | bellard | while (*p != '\0' && !isspace(*p)) |
293 | 9dc39cba | bellard | p++; |
294 | 9dc39cba | bellard | args[argc] = pstart; |
295 | 9dc39cba | bellard | argc++; |
296 | 9dc39cba | bellard | if (argc >= MAX_ARGS)
|
297 | 9dc39cba | bellard | break;
|
298 | 9dc39cba | bellard | if (*p == '\0') |
299 | 9dc39cba | bellard | break;
|
300 | 9dc39cba | bellard | *p++ = '\0';
|
301 | 9dc39cba | bellard | } |
302 | 9dc39cba | bellard | args[argc] = NULL;
|
303 | 9dc39cba | bellard | #ifdef DEBUG
|
304 | 9dc39cba | bellard | for(i=0;i<argc;i++) { |
305 | 9dc39cba | bellard | term_printf(" '%s'", args[i]);
|
306 | 9dc39cba | bellard | } |
307 | 9dc39cba | bellard | term_printf("\n");
|
308 | 9dc39cba | bellard | #endif
|
309 | 9dc39cba | bellard | if (argc <= 0) |
310 | 9dc39cba | bellard | return;
|
311 | 9dc39cba | bellard | for(cmd = term_cmds; cmd->name != NULL; cmd++) { |
312 | 9dc39cba | bellard | if (compare_cmd(args[0], cmd->name)) |
313 | 9dc39cba | bellard | goto found;
|
314 | 9dc39cba | bellard | } |
315 | 9dc39cba | bellard | term_printf("unknown command: '%s'\n", args[0]); |
316 | 9dc39cba | bellard | return;
|
317 | 9dc39cba | bellard | found:
|
318 | 9dc39cba | bellard | cmd->handler(argc, args); |
319 | 9dc39cba | bellard | } |
320 | 9dc39cba | bellard | |
321 | 9dc39cba | bellard | static void term_show_prompt(void) |
322 | 9dc39cba | bellard | { |
323 | 9dc39cba | bellard | term_printf("(qemu) ");
|
324 | 9dc39cba | bellard | fflush(stdout); |
325 | 9dc39cba | bellard | term_cmd_buf_index = 0;
|
326 | 9dc39cba | bellard | term_cmd_buf_size = 0;
|
327 | 9dc39cba | bellard | term_esc_state = IS_NORM; |
328 | 9dc39cba | bellard | } |
329 | 9dc39cba | bellard | |
330 | 9dc39cba | bellard | static void term_insert_char(int ch) |
331 | 9dc39cba | bellard | { |
332 | 9dc39cba | bellard | if (term_cmd_buf_index < TERM_CMD_BUF_SIZE) {
|
333 | 9dc39cba | bellard | memmove(term_cmd_buf + term_cmd_buf_index + 1,
|
334 | 9dc39cba | bellard | term_cmd_buf + term_cmd_buf_index, |
335 | 9dc39cba | bellard | term_cmd_buf_size - term_cmd_buf_index); |
336 | 9dc39cba | bellard | term_cmd_buf[term_cmd_buf_index] = ch; |
337 | 9dc39cba | bellard | term_cmd_buf_size++; |
338 | 9dc39cba | bellard | term_printf("\033[@%c", ch);
|
339 | 9dc39cba | bellard | term_cmd_buf_index++; |
340 | 9dc39cba | bellard | term_flush(); |
341 | 9dc39cba | bellard | } |
342 | 9dc39cba | bellard | } |
343 | 9dc39cba | bellard | |
344 | 9dc39cba | bellard | static void term_backward_char(void) |
345 | 9dc39cba | bellard | { |
346 | 9dc39cba | bellard | if (term_cmd_buf_index > 0) { |
347 | 9dc39cba | bellard | term_cmd_buf_index--; |
348 | 9dc39cba | bellard | term_printf("\033[D");
|
349 | 9dc39cba | bellard | term_flush(); |
350 | 9dc39cba | bellard | } |
351 | 9dc39cba | bellard | } |
352 | 9dc39cba | bellard | |
353 | 9dc39cba | bellard | static void term_forward_char(void) |
354 | 9dc39cba | bellard | { |
355 | 9dc39cba | bellard | if (term_cmd_buf_index < term_cmd_buf_size) {
|
356 | 9dc39cba | bellard | term_cmd_buf_index++; |
357 | 9dc39cba | bellard | term_printf("\033[C");
|
358 | 9dc39cba | bellard | term_flush(); |
359 | 9dc39cba | bellard | } |
360 | 9dc39cba | bellard | } |
361 | 9dc39cba | bellard | |
362 | 9dc39cba | bellard | static void term_delete_char(void) |
363 | 9dc39cba | bellard | { |
364 | 9dc39cba | bellard | if (term_cmd_buf_index < term_cmd_buf_size) {
|
365 | 9dc39cba | bellard | memmove(term_cmd_buf + term_cmd_buf_index, |
366 | 9dc39cba | bellard | term_cmd_buf + term_cmd_buf_index + 1,
|
367 | 9dc39cba | bellard | term_cmd_buf_size - term_cmd_buf_index - 1);
|
368 | 9dc39cba | bellard | term_printf("\033[P");
|
369 | 9dc39cba | bellard | term_cmd_buf_size--; |
370 | 9dc39cba | bellard | term_flush(); |
371 | 9dc39cba | bellard | } |
372 | 9dc39cba | bellard | } |
373 | 9dc39cba | bellard | |
374 | 9dc39cba | bellard | static void term_backspace(void) |
375 | 9dc39cba | bellard | { |
376 | 9dc39cba | bellard | if (term_cmd_buf_index > 0) { |
377 | 9dc39cba | bellard | term_backward_char(); |
378 | 9dc39cba | bellard | term_delete_char(); |
379 | 9dc39cba | bellard | } |
380 | 9dc39cba | bellard | } |
381 | 9dc39cba | bellard | |
382 | 9dc39cba | bellard | static void term_bol(void) |
383 | 9dc39cba | bellard | { |
384 | 9dc39cba | bellard | while (term_cmd_buf_index > 0) |
385 | 9dc39cba | bellard | term_backward_char(); |
386 | 9dc39cba | bellard | } |
387 | 9dc39cba | bellard | |
388 | 9dc39cba | bellard | static void term_eol(void) |
389 | 9dc39cba | bellard | { |
390 | 9dc39cba | bellard | while (term_cmd_buf_index < term_cmd_buf_size)
|
391 | 9dc39cba | bellard | term_forward_char(); |
392 | 9dc39cba | bellard | } |
393 | 9dc39cba | bellard | |
394 | 9dc39cba | bellard | /* return true if command handled */
|
395 | 9dc39cba | bellard | static void term_handle_byte(int ch) |
396 | 9dc39cba | bellard | { |
397 | 9dc39cba | bellard | switch(term_esc_state) {
|
398 | 9dc39cba | bellard | case IS_NORM:
|
399 | 9dc39cba | bellard | switch(ch) {
|
400 | 9dc39cba | bellard | case 1: |
401 | 9dc39cba | bellard | term_bol(); |
402 | 9dc39cba | bellard | break;
|
403 | 9dc39cba | bellard | case 5: |
404 | 9dc39cba | bellard | term_eol(); |
405 | 9dc39cba | bellard | break;
|
406 | 9dc39cba | bellard | case 10: |
407 | 9dc39cba | bellard | case 13: |
408 | 9dc39cba | bellard | term_cmd_buf[term_cmd_buf_size] = '\0';
|
409 | 9dc39cba | bellard | term_printf("\n");
|
410 | 9dc39cba | bellard | term_handle_command(term_cmd_buf); |
411 | 9dc39cba | bellard | term_show_prompt(); |
412 | 9dc39cba | bellard | break;
|
413 | 9dc39cba | bellard | case 27: |
414 | 9dc39cba | bellard | term_esc_state = IS_ESC; |
415 | 9dc39cba | bellard | break;
|
416 | 9dc39cba | bellard | case 127: |
417 | 9dc39cba | bellard | case 8: |
418 | 9dc39cba | bellard | term_backspace(); |
419 | 9dc39cba | bellard | break;
|
420 | 9dc39cba | bellard | default:
|
421 | 9dc39cba | bellard | if (ch >= 32) { |
422 | 9dc39cba | bellard | term_insert_char(ch); |
423 | 9dc39cba | bellard | } |
424 | 9dc39cba | bellard | break;
|
425 | 9dc39cba | bellard | } |
426 | 9dc39cba | bellard | break;
|
427 | 9dc39cba | bellard | case IS_ESC:
|
428 | 9dc39cba | bellard | if (ch == '[') { |
429 | 9dc39cba | bellard | term_esc_state = IS_CSI; |
430 | 9dc39cba | bellard | term_esc_param = 0;
|
431 | 9dc39cba | bellard | } else {
|
432 | 9dc39cba | bellard | term_esc_state = IS_NORM; |
433 | 9dc39cba | bellard | } |
434 | 9dc39cba | bellard | break;
|
435 | 9dc39cba | bellard | case IS_CSI:
|
436 | 9dc39cba | bellard | switch(ch) {
|
437 | 9dc39cba | bellard | case 'D': |
438 | 9dc39cba | bellard | term_backward_char(); |
439 | 9dc39cba | bellard | break;
|
440 | 9dc39cba | bellard | case 'C': |
441 | 9dc39cba | bellard | term_forward_char(); |
442 | 9dc39cba | bellard | break;
|
443 | 9dc39cba | bellard | case '0' ... '9': |
444 | 9dc39cba | bellard | term_esc_param = term_esc_param * 10 + (ch - '0'); |
445 | 9dc39cba | bellard | goto the_end;
|
446 | 9dc39cba | bellard | case '~': |
447 | 9dc39cba | bellard | switch(term_esc_param) {
|
448 | 9dc39cba | bellard | case 1: |
449 | 9dc39cba | bellard | term_bol(); |
450 | 9dc39cba | bellard | break;
|
451 | 9dc39cba | bellard | case 3: |
452 | 9dc39cba | bellard | term_delete_char(); |
453 | 9dc39cba | bellard | break;
|
454 | 9dc39cba | bellard | case 4: |
455 | 9dc39cba | bellard | term_eol(); |
456 | 9dc39cba | bellard | break;
|
457 | 9dc39cba | bellard | } |
458 | 9dc39cba | bellard | break;
|
459 | 9dc39cba | bellard | default:
|
460 | 9dc39cba | bellard | break;
|
461 | 9dc39cba | bellard | } |
462 | 9dc39cba | bellard | term_esc_state = IS_NORM; |
463 | 9dc39cba | bellard | the_end:
|
464 | 9dc39cba | bellard | break;
|
465 | 9dc39cba | bellard | } |
466 | 9dc39cba | bellard | } |
467 | 9dc39cba | bellard | |
468 | 9dc39cba | bellard | /*************************************************************/
|
469 | 9dc39cba | bellard | /* serial console support */
|
470 | 9dc39cba | bellard | |
471 | 9dc39cba | bellard | #define TERM_ESCAPE 0x01 /* ctrl-a is used for escape */ |
472 | 9dc39cba | bellard | |
473 | 9dc39cba | bellard | static int term_got_escape, term_command; |
474 | 9dc39cba | bellard | |
475 | 9dc39cba | bellard | void term_print_help(void) |
476 | 9dc39cba | bellard | { |
477 | 9dc39cba | bellard | term_printf("\n"
|
478 | 9dc39cba | bellard | "C-a h print this help\n"
|
479 | 9dc39cba | bellard | "C-a x exit emulatior\n"
|
480 | 9dc39cba | bellard | "C-a d switch on/off debug log\n"
|
481 | 9dc39cba | bellard | "C-a s save disk data back to file (if -snapshot)\n"
|
482 | 9dc39cba | bellard | "C-a b send break (magic sysrq)\n"
|
483 | 9dc39cba | bellard | "C-a c switch between console and monitor\n"
|
484 | 9dc39cba | bellard | "C-a C-a send C-a\n"
|
485 | 9dc39cba | bellard | ); |
486 | 9dc39cba | bellard | } |
487 | 9dc39cba | bellard | |
488 | 9dc39cba | bellard | /* called when a char is received */
|
489 | 9dc39cba | bellard | static void term_received_byte(int ch) |
490 | 9dc39cba | bellard | { |
491 | 9dc39cba | bellard | if (!serial_console) {
|
492 | 9dc39cba | bellard | /* if no serial console, handle every command */
|
493 | 9dc39cba | bellard | term_handle_byte(ch); |
494 | 9dc39cba | bellard | } else {
|
495 | 9dc39cba | bellard | if (term_got_escape) {
|
496 | 9dc39cba | bellard | term_got_escape = 0;
|
497 | 9dc39cba | bellard | switch(ch) {
|
498 | 9dc39cba | bellard | case 'h': |
499 | 9dc39cba | bellard | term_print_help(); |
500 | 9dc39cba | bellard | break;
|
501 | 9dc39cba | bellard | case 'x': |
502 | 9dc39cba | bellard | exit(0);
|
503 | 9dc39cba | bellard | break;
|
504 | 9dc39cba | bellard | case 's': |
505 | 9dc39cba | bellard | { |
506 | 9dc39cba | bellard | int i;
|
507 | 9dc39cba | bellard | for (i = 0; i < MAX_DISKS; i++) { |
508 | 9dc39cba | bellard | if (bs_table[i])
|
509 | 9dc39cba | bellard | bdrv_commit(bs_table[i]); |
510 | 9dc39cba | bellard | } |
511 | 9dc39cba | bellard | } |
512 | 9dc39cba | bellard | break;
|
513 | 9dc39cba | bellard | case 'b': |
514 | 9dc39cba | bellard | if (serial_console)
|
515 | 9dc39cba | bellard | serial_receive_break(serial_console); |
516 | 9dc39cba | bellard | break;
|
517 | 9dc39cba | bellard | case 'c': |
518 | 9dc39cba | bellard | if (!term_command) {
|
519 | 9dc39cba | bellard | term_show_prompt(); |
520 | 9dc39cba | bellard | term_command = 1;
|
521 | 9dc39cba | bellard | } else {
|
522 | 9dc39cba | bellard | term_command = 0;
|
523 | 9dc39cba | bellard | } |
524 | 9dc39cba | bellard | break;
|
525 | 9dc39cba | bellard | case 'd': |
526 | 9dc39cba | bellard | cpu_set_log(CPU_LOG_ALL); |
527 | 9dc39cba | bellard | break;
|
528 | 9dc39cba | bellard | case TERM_ESCAPE:
|
529 | 9dc39cba | bellard | goto send_char;
|
530 | 9dc39cba | bellard | } |
531 | 9dc39cba | bellard | } else if (ch == TERM_ESCAPE) { |
532 | 9dc39cba | bellard | term_got_escape = 1;
|
533 | 9dc39cba | bellard | } else {
|
534 | 9dc39cba | bellard | send_char:
|
535 | 9dc39cba | bellard | if (term_command) {
|
536 | 9dc39cba | bellard | term_handle_byte(ch); |
537 | 9dc39cba | bellard | } else {
|
538 | 9dc39cba | bellard | if (serial_console)
|
539 | 9dc39cba | bellard | serial_receive_byte(serial_console, ch); |
540 | 9dc39cba | bellard | } |
541 | 9dc39cba | bellard | } |
542 | 9dc39cba | bellard | } |
543 | 9dc39cba | bellard | } |
544 | 9dc39cba | bellard | |
545 | 9dc39cba | bellard | static int term_can_read(void *opaque) |
546 | 9dc39cba | bellard | { |
547 | 9dc39cba | bellard | if (serial_console) {
|
548 | 9dc39cba | bellard | return serial_can_receive(serial_console);
|
549 | 9dc39cba | bellard | } else {
|
550 | 9dc39cba | bellard | return 1; |
551 | 9dc39cba | bellard | } |
552 | 9dc39cba | bellard | } |
553 | 9dc39cba | bellard | |
554 | 9dc39cba | bellard | static void term_read(void *opaque, const uint8_t *buf, int size) |
555 | 9dc39cba | bellard | { |
556 | 9dc39cba | bellard | int i;
|
557 | 9dc39cba | bellard | for(i = 0; i < size; i++) |
558 | 9dc39cba | bellard | term_received_byte(buf[i]); |
559 | 9dc39cba | bellard | } |
560 | 9dc39cba | bellard | |
561 | 9dc39cba | bellard | void monitor_init(void) |
562 | 9dc39cba | bellard | { |
563 | 9dc39cba | bellard | if (!serial_console) {
|
564 | 9dc39cba | bellard | term_printf("QEMU %s monitor - type 'help' for more information\n",
|
565 | 9dc39cba | bellard | QEMU_VERSION); |
566 | 9dc39cba | bellard | term_show_prompt(); |
567 | 9dc39cba | bellard | } |
568 | 9dc39cba | bellard | add_fd_read_handler(0, term_can_read, term_read, NULL); |
569 | 9dc39cba | bellard | } |