?? vl.c
字號:
{ s->chr_read(s->handler_opaque, buf, len);}void qemu_chr_accept_input(CharDriverState *s){ if (s->chr_accept_input) s->chr_accept_input(s);}void qemu_chr_printf(CharDriverState *s, const char *fmt, ...){ char buf[4096]; va_list ap; va_start(ap, fmt); vsnprintf(buf, sizeof(buf), fmt, ap); qemu_chr_write(s, (uint8_t *)buf, strlen(buf)); va_end(ap);}void qemu_chr_send_event(CharDriverState *s, int event){ if (s->chr_send_event) s->chr_send_event(s, event);}void qemu_chr_add_handlers(CharDriverState *s, IOCanRWHandler *fd_can_read, IOReadHandler *fd_read, IOEventHandler *fd_event, void *opaque){ s->chr_can_read = fd_can_read; s->chr_read = fd_read; s->chr_event = fd_event; s->handler_opaque = opaque; if (s->chr_update_read_handler) s->chr_update_read_handler(s);}static int null_chr_write(CharDriverState *chr, const uint8_t *buf, int len){ return len;}static CharDriverState *qemu_chr_open_null(void){ CharDriverState *chr; chr = qemu_mallocz(sizeof(CharDriverState)); if (!chr) return NULL; chr->chr_write = null_chr_write; return chr;}/* MUX driver for serial I/O splitting */static int term_timestamps;static int64_t term_timestamps_start;#define MAX_MUX 4#define MUX_BUFFER_SIZE 32 /* Must be a power of 2. */#define MUX_BUFFER_MASK (MUX_BUFFER_SIZE - 1)typedef struct { IOCanRWHandler *chr_can_read[MAX_MUX]; IOReadHandler *chr_read[MAX_MUX]; IOEventHandler *chr_event[MAX_MUX]; void *ext_opaque[MAX_MUX]; CharDriverState *drv; unsigned char buffer[MUX_BUFFER_SIZE]; int prod; int cons; int mux_cnt; int term_got_escape; int max_size;} MuxDriver;static int mux_chr_write(CharDriverState *chr, const uint8_t *buf, int len){ MuxDriver *d = chr->opaque; int ret; if (!term_timestamps) { ret = d->drv->chr_write(d->drv, buf, len); } else { int i; ret = 0; for(i = 0; i < len; i++) { ret += d->drv->chr_write(d->drv, buf+i, 1); if (buf[i] == '\n') { char buf1[64]; int64_t ti; int secs; ti = get_clock(); if (term_timestamps_start == -1) term_timestamps_start = ti; ti -= term_timestamps_start; secs = ti / 1000000000; snprintf(buf1, sizeof(buf1), "[%02d:%02d:%02d.%03d] ", secs / 3600, (secs / 60) % 60, secs % 60, (int)((ti / 1000000) % 1000)); d->drv->chr_write(d->drv, (uint8_t *)buf1, strlen(buf1)); } } } return ret;}static char *mux_help[] = { "% h print this help\n\r", "% x exit emulator\n\r", "% s save disk data back to file (if -snapshot)\n\r", "% t toggle console timestamps\n\r" "% b send break (magic sysrq)\n\r", "% c switch between console and monitor\n\r", "% % sends %\n\r", NULL};static int term_escape_char = 0x01; /* ctrl-a is used for escape */static void mux_print_help(CharDriverState *chr){ int i, j; char ebuf[15] = "Escape-Char"; char cbuf[50] = "\n\r"; if (term_escape_char > 0 && term_escape_char < 26) { sprintf(cbuf,"\n\r"); sprintf(ebuf,"C-%c", term_escape_char - 1 + 'a'); } else { sprintf(cbuf,"\n\rEscape-Char set to Ascii: 0x%02x\n\r\n\r", term_escape_char); } chr->chr_write(chr, (uint8_t *)cbuf, strlen(cbuf)); for (i = 0; mux_help[i] != NULL; i++) { for (j=0; mux_help[i][j] != '\0'; j++) { if (mux_help[i][j] == '%') chr->chr_write(chr, (uint8_t *)ebuf, strlen(ebuf)); else chr->chr_write(chr, (uint8_t *)&mux_help[i][j], 1); } }}static int mux_proc_byte(CharDriverState *chr, MuxDriver *d, int ch){ if (d->term_got_escape) { d->term_got_escape = 0; if (ch == term_escape_char) goto send_char; switch(ch) { case '?': case 'h': mux_print_help(chr); break; case 'x': { char *term = "QEMU: Terminated\n\r"; chr->chr_write(chr,(uint8_t *)term,strlen(term)); exit(0); break; } case 's': { int i; for (i = 0; i < nb_drives; i++) { bdrv_commit(drives_table[i].bdrv); } } break; case 'b': qemu_chr_event(chr, CHR_EVENT_BREAK); break; case 'c': /* Switch to the next registered device */ chr->focus++; if (chr->focus >= d->mux_cnt) chr->focus = 0; break; case 't': term_timestamps = !term_timestamps; term_timestamps_start = -1; break; } } else if (ch == term_escape_char) { d->term_got_escape = 1; } else { send_char: return 1; } return 0;}static void mux_chr_accept_input(CharDriverState *chr){ int m = chr->focus; MuxDriver *d = chr->opaque; while (d->prod != d->cons && d->chr_can_read[m] && d->chr_can_read[m](d->ext_opaque[m])) { d->chr_read[m](d->ext_opaque[m], &d->buffer[d->cons++ & MUX_BUFFER_MASK], 1); }}static int mux_chr_can_read(void *opaque){ CharDriverState *chr = opaque; MuxDriver *d = chr->opaque; if ((d->prod - d->cons) < MUX_BUFFER_SIZE) return 1; if (d->chr_can_read[chr->focus]) return d->chr_can_read[chr->focus](d->ext_opaque[chr->focus]); return 0;}static void mux_chr_read(void *opaque, const uint8_t *buf, int size){ CharDriverState *chr = opaque; MuxDriver *d = chr->opaque; int m = chr->focus; int i; mux_chr_accept_input (opaque); for(i = 0; i < size; i++) if (mux_proc_byte(chr, d, buf[i])) { if (d->prod == d->cons && d->chr_can_read[m] && d->chr_can_read[m](d->ext_opaque[m])) d->chr_read[m](d->ext_opaque[m], &buf[i], 1); else d->buffer[d->prod++ & MUX_BUFFER_MASK] = buf[i]; }}static void mux_chr_event(void *opaque, int event){ CharDriverState *chr = opaque; MuxDriver *d = chr->opaque; int i; /* Send the event to all registered listeners */ for (i = 0; i < d->mux_cnt; i++) if (d->chr_event[i]) d->chr_event[i](d->ext_opaque[i], event);}static void mux_chr_update_read_handler(CharDriverState *chr){ MuxDriver *d = chr->opaque; if (d->mux_cnt >= MAX_MUX) { fprintf(stderr, "Cannot add I/O handlers, MUX array is full\n"); return; } d->ext_opaque[d->mux_cnt] = chr->handler_opaque; d->chr_can_read[d->mux_cnt] = chr->chr_can_read; d->chr_read[d->mux_cnt] = chr->chr_read; d->chr_event[d->mux_cnt] = chr->chr_event; /* Fix up the real driver with mux routines */ if (d->mux_cnt == 0) { qemu_chr_add_handlers(d->drv, mux_chr_can_read, mux_chr_read, mux_chr_event, chr); } chr->focus = d->mux_cnt; d->mux_cnt++;}static CharDriverState *qemu_chr_open_mux(CharDriverState *drv){ CharDriverState *chr; MuxDriver *d; chr = qemu_mallocz(sizeof(CharDriverState)); if (!chr) return NULL; d = qemu_mallocz(sizeof(MuxDriver)); if (!d) { free(chr); return NULL; } chr->opaque = d; d->drv = drv; chr->focus = -1; chr->chr_write = mux_chr_write; chr->chr_update_read_handler = mux_chr_update_read_handler; chr->chr_accept_input = mux_chr_accept_input; return chr;}#ifdef _WIN32static void socket_cleanup(void){ WSACleanup();}static int socket_init(void){ WSADATA Data; int ret, err; ret = WSAStartup(MAKEWORD(2,2), &Data); if (ret != 0) { err = WSAGetLastError(); fprintf(stderr, "WSAStartup: %d\n", err); return -1; } atexit(socket_cleanup); return 0;}static int send_all(int fd, const uint8_t *buf, int len1){ int ret, len; len = len1; while (len > 0) { ret = send(fd, buf, len, 0); if (ret < 0) { int errno; errno = WSAGetLastError(); if (errno != WSAEWOULDBLOCK) { return -1; } } else if (ret == 0) { break; } else { buf += ret; len -= ret; } } return len1 - len;}void socket_set_nonblock(int fd){ unsigned long opt = 1; ioctlsocket(fd, FIONBIO, &opt);}#elsestatic int unix_write(int fd, const uint8_t *buf, int len1){ int ret, len; len = len1; while (len > 0) { ret = write(fd, buf, len); if (ret < 0) { if (errno != EINTR && errno != EAGAIN) return -1; } else if (ret == 0) { break; } else { buf += ret; len -= ret; } } return len1 - len;}static inline int send_all(int fd, const uint8_t *buf, int len1){ return unix_write(fd, buf, len1);}void socket_set_nonblock(int fd){ fcntl(fd, F_SETFL, O_NONBLOCK);}#endif /* !_WIN32 */#ifndef _WIN32typedef struct { int fd_in, fd_out; int max_size;} FDCharDriver;#define STDIO_MAX_CLIENTS 1static int stdio_nb_clients = 0;static int fd_chr_write(CharDriverState *chr, const uint8_t *buf, int len){ FDCharDriver *s = chr->opaque; return unix_write(s->fd_out, buf, len);}static int fd_chr_read_poll(void *opaque){ CharDriverState *chr = opaque; FDCharDriver *s = chr->opaque; s->max_size = qemu_chr_can_read(chr); return s->max_size;}static void fd_chr_read(void *opaque){ CharDriverState *chr = opaque; FDCharDriver *s = chr->opaque; int size, len; uint8_t buf[1024]; len = sizeof(buf); if (len > s->max_size) len = s->max_size; if (len == 0) return; size = read(s->fd_in, buf, len); if (size == 0) { /* FD has been closed. Remove it from the active list. */ qemu_set_fd_handler2(s->fd_in, NULL, NULL, NULL, NULL); return; } if (size > 0) { qemu_chr_read(chr, buf, size); }}static void fd_chr_update_read_handler(CharDriverState *chr){ FDCharDriver *s = chr->opaque; if (s->fd_in >= 0) { if (nographic && s->fd_in == 0) { } else { qemu_set_fd_handler2(s->fd_in, fd_chr_read_poll, fd_chr_read, NULL, chr); } }}/* open a character device to a unix fd */static CharDriverState *qemu_chr_open_fd(int fd_in, int fd_out){ CharDriverState *chr; FDCharDriver *s; chr = qemu_mallocz(sizeof(CharDriverState)); if (!chr) return NULL; s = qemu_mallocz(sizeof(FDCharDriver)); if (!s) { free(chr); return NULL; } s->fd_in = fd_in; s->fd_out = fd_out; chr->opaque = s; chr->chr_write = fd_chr_write; chr->chr_update_read_handler = fd_chr_update_read_handler; qemu_chr_reset(chr); return chr;}static CharDriverState *qemu_chr_open_file_out(const char *file_out){ int fd_out; TFR(fd_out = open(file_out, O_WRONLY | O_TRUNC | O_CREAT | O_BINARY, 0666)); if (fd_out < 0) return NULL; return qemu_chr_open_fd(-1, fd_out);}static CharDriverState *qemu_chr_open_pipe(const char *filename){ int fd_in, fd_out; char filename_in[256], filename_out[256]; snprintf(filename_in, 256, "%s.in", filename); snprintf(filename_out, 256, "%s.out", filename); TFR(fd_in = open(filename_in, O_RDWR | O_BINARY)); TFR(fd_out = open(filename_out, O_RDWR | O_BINARY)); if (fd_in < 0 || fd_out < 0) { if (fd_in >= 0) close(fd_in); if (fd_out >= 0) close(fd_out); TFR(fd_in = fd_out = open(filename, O_RDWR | O_BINARY)); if (fd_in < 0) return NULL; } return qemu_chr_open_fd(fd_in, fd_out);}/* for STDIO, we handle the case where several clients use it (nographic mode) */#define TERM_FIFO_MAX_SIZE 1static uint8_t term_fifo[TERM_FIFO_MAX_SIZE];static int term_fifo_size;static int stdio_read_poll(void *opaque){ CharDriverState *chr = opaque; /* try to flush the queue if needed */ if (term_fifo_size != 0 && qemu_chr_can_read(chr) > 0) { qemu_chr_read(chr, term_fifo, 1); term_fifo_size = 0; } /* see if we can absorb more chars */ if (term_fifo_size == 0) return 1; else return 0;}static void stdio_read(void *opaque){ int size; uint8_t buf[1]; CharDriverState *chr = opaque; size = read(0, buf, 1); if (size == 0) { /* stdin has been closed. Remove it from the active list. */ qemu_set_fd_handler2(0, NULL, NULL, NULL, NULL);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -