📄 vl.c
字号:
qemu_chr_write(s, 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_read_handler(CharDriverState *s, IOCanRWHandler *fd_can_read, IOReadHandler *fd_read, void *opaque){ s->chr_add_read_handler(s, fd_can_read, fd_read, opaque);} void qemu_chr_add_event_handler(CharDriverState *s, IOEventHandler *chr_event){ s->chr_event = chr_event;}static int null_chr_write(CharDriverState *chr, const uint8_t *buf, int len){ return len;}static void null_chr_add_read_handler(CharDriverState *chr, IOCanRWHandler *fd_can_read, IOReadHandler *fd_read, void *opaque){}CharDriverState *qemu_chr_open_null(void){ CharDriverState *chr; chr = qemu_mallocz(sizeof(CharDriverState)); if (!chr) return NULL; chr->chr_write = null_chr_write; chr->chr_add_read_handler = null_chr_add_read_handler; 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; IOCanRWHandler *fd_can_read; IOReadHandler *fd_read; void *fd_opaque; int max_size;} FDCharDriver;#define STDIO_MAX_CLIENTS 2static int stdio_nb_clients;static CharDriverState *stdio_clients[STDIO_MAX_CLIENTS];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 = s->fd_can_read(s->fd_opaque); 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) { s->fd_read(s->fd_opaque, buf, size); }}static void fd_chr_add_read_handler(CharDriverState *chr, IOCanRWHandler *fd_can_read, IOReadHandler *fd_read, void *opaque){ FDCharDriver *s = chr->opaque; if (s->fd_in >= 0) { s->fd_can_read = fd_can_read; s->fd_read = fd_read; s->fd_opaque = opaque; 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 */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_add_read_handler = fd_chr_add_read_handler; return chr;}CharDriverState *qemu_chr_open_file_out(const char *file_out){ int fd_out; 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);}CharDriverState *qemu_chr_open_pipe(const char *filename){ int fd; fd = open(filename, O_RDWR | O_BINARY); if (fd < 0) return NULL; return qemu_chr_open_fd(fd, fd);}/* for STDIO, we handle the case where several clients use it (nographic mode) */#define TERM_ESCAPE 0x01 /* ctrl-a is used for escape */#define TERM_FIFO_MAX_SIZE 1static int term_got_escape, client_index;static uint8_t term_fifo[TERM_FIFO_MAX_SIZE];int term_fifo_size;void term_print_help(void){ printf("\n" "C-a h print this help\n" "C-a x exit emulator\n" "C-a s save disk data back to file (if -snapshot)\n" "C-a b send break (magic sysrq)\n" "C-a c switch between console and monitor\n" "C-a C-a send C-a\n" );}/* called when a char is received */static void stdio_received_byte(int ch){ if (term_got_escape) { term_got_escape = 0; switch(ch) { case 'h': term_print_help(); break; case 'x': exit(0); break; case 's': { int i; for (i = 0; i < MAX_DISKS; i++) { if (bs_table[i]) bdrv_commit(bs_table[i]); } } break; case 'b': if (client_index < stdio_nb_clients) { CharDriverState *chr; FDCharDriver *s; chr = stdio_clients[client_index]; s = chr->opaque; chr->chr_event(s->fd_opaque, CHR_EVENT_BREAK); } break; case 'c': client_index++; if (client_index >= stdio_nb_clients) client_index = 0; if (client_index == 0) { /* send a new line in the monitor to get the prompt */ ch = '\r'; goto send_char; } break; case TERM_ESCAPE: goto send_char; } } else if (ch == TERM_ESCAPE) { term_got_escape = 1; } else { send_char: if (client_index < stdio_nb_clients) { uint8_t buf[1]; CharDriverState *chr; FDCharDriver *s; chr = stdio_clients[client_index]; s = chr->opaque; if (s->fd_can_read(s->fd_opaque) > 0) { buf[0] = ch; s->fd_read(s->fd_opaque, buf, 1); } else if (term_fifo_size == 0) { term_fifo[term_fifo_size++] = ch; } } }}static int stdio_read_poll(void *opaque){ CharDriverState *chr; FDCharDriver *s; if (client_index < stdio_nb_clients) { chr = stdio_clients[client_index]; s = chr->opaque; /* try to flush the queue if needed */ if (term_fifo_size != 0 && s->fd_can_read(s->fd_opaque) > 0) { s->fd_read(s->fd_opaque, term_fifo, 1); term_fifo_size = 0; } /* see if we can absorb more chars */ if (term_fifo_size == 0) return 1; else return 0; } else { return 1; }}static void stdio_read(void *opaque){ int size; uint8_t buf[1]; size = read(0, buf, 1); if (size > 0) stdio_received_byte(buf[0]);}/* init terminal so that we can grab keys */static struct termios oldtty;static int old_fd0_flags;static void term_exit(void){ tcsetattr (0, TCSANOW, &oldtty); fcntl(0, F_SETFL, old_fd0_flags);}static void term_init(void){ struct termios tty; tcgetattr (0, &tty); oldtty = tty; old_fd0_flags = fcntl(0, F_GETFL); tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP |INLCR|IGNCR|ICRNL|IXON); tty.c_oflag |= OPOST; tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN); /* if graphical mode, we allow Ctrl-C handling */ if (nographic) tty.c_lflag &= ~ISIG; tty.c_cflag &= ~(CSIZE|PARENB); tty.c_cflag |= CS8; tty.c_cc[VMIN] = 1; tty.c_cc[VTIME] = 0; tcsetattr (0, TCSANOW, &tty); atexit(term_exit); fcntl(0, F_SETFL, O_NONBLOCK);}CharDriverState *qemu_chr_open_stdio(void){ CharDriverState *chr; if (nographic) { if (stdio_nb_clients >= STDIO_MAX_CLIENTS) return NULL; chr = qemu_chr_open_fd(0, 1); if (stdio_nb_clients == 0) qemu_set_fd_handler2(0, stdio_read_poll, stdio_read, NULL, NULL); client_index = stdio_nb_clients; } else { if (stdio_nb_clients != 0) return NULL; chr = qemu_chr_open_fd(0, 1); } stdio_clients[stdio_nb_clients++] = chr; if (stdio_nb_clients == 1) { /* set the terminal in raw mode */ term_init(); } return chr;}#if defined(__linux__)CharDriverState *qemu_chr_open_pty(void){ struct termios tty; char slave_name[1024]; int master_fd, slave_fd; /* Not satisfying */ if (openpty(&master_fd, &slave_fd, slave_name, NULL, NULL) < 0) { return NULL; } /* Disabling local echo and line-buffered output */ tcgetattr (master_fd, &tty); tty.c_lflag &= ~(ECHO|ICANON|ISIG); tty.c_cc[VMIN] = 1; tty.c_cc[VTIME] = 0; tcsetattr (master_fd, TCSAFLUSH, &tty); fprintf(stderr, "char device redirected to %s\n", slave_name); return qemu_chr_open_fd(master_fd, master_fd);}static void tty_serial_init(int fd, int speed, int parity, int data_bits, int stop_bits){ struct termios tty; speed_t spd;#if 0 printf("tty_serial_init: speed=%d parity=%c data=%d stop=%d\n", speed, parity, data_bits, stop_bits);#endif tcgetattr (fd, &tty); switch(speed) { case 50: spd = B50; break; case 75: spd = B75; break; case 300: spd = B300; break; case 600: spd = B600; break; case 1200: spd = B1200; break; case 2400: spd = B2400; break; case 4800: spd = B4800; break; case 9600: spd = B9600; break; case 19200: spd = B19200; break; case 38400: spd = B38400; break; case 57600: spd = B57600; break; default: case 115200: spd = B115200; break; } cfsetispeed(&tty, spd); cfsetospeed(&tty, spd); tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP |INLCR|IGNCR|ICRNL|IXON); tty.c_oflag |= OPOST; tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN|ISIG); tty.c_cflag &= ~(CSIZE|PARENB|PARODD|CRTSCTS); switch(data_bits) { default: case 8: tty.c_cflag |= CS8; break; case 7: tty.c_cflag |= CS7; break; case 6: tty.c_cflag |= CS6; break; case 5: tty.c_cflag |= CS5; break; } switch(parity) { default: case 'N': break; case 'E': tty.c_cflag |= PARENB; break; case 'O': tty.c_cflag |= PARENB | PARODD; break; } tcsetattr (fd, TCSANOW, &tty);}static int tty_serial_ioctl(CharDriverState *chr, int cmd, void *arg){ FDCharDriver *s = chr->opaque; switch(cmd) { case CHR_IOCTL_SERIAL_SET_PARAMS: { QEMUSerialSetParams *ssp = arg; tty_serial_init(s->fd_in, ssp->speed, ssp->parity, ssp->data_bits, ssp->stop_bits); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -