Patrick Rudolph (siro@das-labor.org) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/14512
-gerrit
commit f4ac7545c289c59c307e297258bfc56db8585930 Author: Patrick Rudolph siro@das-labor.org Date: Mon Apr 25 12:26:12 2016 +0200
qemu-0.15.x/serialice-com: Implement TCP serialice connection
Pass tcp:hostname:port instead of tty device path. Example: ./qemu -M serialice -serialice tcp:10.1.0.1:8888
Connects to the target using TCP socket (unix only). Useful to connect to BeagleBone Black in EHCI Debug mode using ser2net daemon on port 8888.
Change-Id: Iee264dfd11375e11c02ea25b6887d32f3db887c5 Signed-off-by: Patrick Rudolph siro@das-labor.org --- qemu-0.15.x/serialice-com.c | 128 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 100 insertions(+), 28 deletions(-)
diff --git a/qemu-0.15.x/serialice-com.c b/qemu-0.15.x/serialice-com.c index 25ccaf5..1fa95c2 100644 --- a/qemu-0.15.x/serialice-com.c +++ b/qemu-0.15.x/serialice-com.c @@ -34,6 +34,9 @@ #include <fcntl.h> #include <termios.h> #include <sys/ioctl.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <netdb.h> #endif
#include <serialice.h> @@ -47,6 +50,7 @@ typedef struct { #else int fd; #endif + int tcp; char *buffer; char *command; } SerialICEState; @@ -113,6 +117,7 @@ static int serialice_write(SerialICEState * state, const void *buf, char *buffer = (char *)buf; char c; int i; + int err;
for (i = 0; i < (int)nbyte; i++) { #ifdef WIN32 @@ -125,8 +130,14 @@ static int serialice_write(SerialICEState * state, const void *buf, ReadFile(state->fd, &c, 1, &ret, NULL); } #else - while (write(state->fd, buffer + i, 1) != 1) ; - while (read(state->fd, &c, 1) != 1) ; + while ((err = write(state->fd, buffer + i, 1)) != 1) { + if (err == -1) + return -1; + } + while ((err = read(state->fd, &c, 1)) != 1) { + if (err == -1) + return -1; + } #endif if (c != buffer[i] && !handshake_mode) { printf("Readback error! %x/%x\n", c, buffer[i]); @@ -193,6 +204,10 @@ static int serialice_wait_prompt(void)
const SerialICE_target *serialice_serial_init(void) { + int len = 0; + int port = 0; + char *hostname = NULL; + s = mallocz(sizeof(SerialICEState));
if (!s) { @@ -203,6 +218,24 @@ const SerialICE_target *serialice_serial_init(void) printf("You need to specify a serial device to use SerialICE.\n"); exit(1); } + len = strlen(serialice_device); + if (len > 5) { + char *tmp = strstr(serialice_device, "tcp:"); + if (tmp) { + hostname = mallocz(len - 4 + 1); + /* copy hostname and port */ + memcpy(hostname, tmp + 4, len - 4); + /* search for port */ + tmp = strstr(hostname, ":"); + if (tmp) { + /* cut of port */ + *tmp = 0; + /* read port */ + port = atoi(tmp + 1); + s->tcp = !!port; + } + } + } #ifdef WIN32 s->fd = CreateFile(serialice_device, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); @@ -228,44 +261,83 @@ const SerialICE_target *serialice_serial_init(void) exit(1); } #else - s->fd = open(serialice_device, O_RDWR | O_NOCTTY | O_NONBLOCK); - + if (s->tcp) { + s->fd = socket(AF_INET, SOCK_STREAM, 0); + } else { + s->fd = open(serialice_device, O_RDWR | O_NOCTTY | O_NONBLOCK); + } if (s->fd == -1) { perror("SerialICE: Could not connect to target TTY"); exit(1); }
- if (ioctl(s->fd, TIOCEXCL) == -1) { - perror("SerialICE: TTY not exclusively available"); - exit(1); - } + if (s->tcp) { + struct timeval tv; + struct hostent *server; + struct sockaddr_in serv_addr;
- if (fcntl(s->fd, F_SETFL, 0) == -1) { - perror("SerialICE: Could not switch to blocking I/O"); - exit(1); - } + server = gethostbyname(hostname); + if (server == NULL) { + perror("No such host.\n"); + exit(1); + }
- if (tcgetattr(s->fd, &options) == -1) { - perror("SerialICE: Could not get TTY attributes"); - exit(1); - } + bzero((char *) &serv_addr, sizeof(serv_addr)); + serv_addr.sin_family = AF_INET; + bcopy((char *)server->h_addr, + (char *)&serv_addr.sin_addr.s_addr, + server->h_length); + serv_addr.sin_port = htons(port);
- cfsetispeed(&options, B115200); - cfsetospeed(&options, B115200); + printf("Connecting to tcp://%s:%d ...\n", hostname, port);
- /* set raw input, 1 second timeout */ - options.c_cflag |= (CLOCAL | CREAD); - options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); - options.c_oflag &= ~OPOST; - options.c_iflag |= IGNCR; - options.c_cc[VMIN] = 0; - options.c_cc[VTIME] = 100; + if (connect(s->fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { + perror("ERROR connecting"); + exit(1); + } + printf("Connected to tcp://%s:%d .\n", hostname, port);
- tcsetattr(s->fd, TCSANOW, &options); + if (fcntl(s->fd, F_SETFL, 0) == -1) { + perror("SerialICE: Could not switch to blocking I/O"); + exit(1); + }
- tcflush(s->fd, TCIOFLUSH); -#endif + tv.tv_sec = 3; /* 1 Secs Timeout */ + tv.tv_usec = 0; + + setsockopt(s->fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(struct timeval)); + } else { + if (ioctl(s->fd, TIOCEXCL) == -1) { + perror("SerialICE: TTY not exclusively available"); + exit(1); + } + + if (fcntl(s->fd, F_SETFL, 0) == -1) { + perror("SerialICE: Could not switch to blocking I/O"); + exit(1); + } + + if (tcgetattr(s->fd, &options) == -1) { + perror("SerialICE: Could not get TTY attributes"); + exit(1); + } + + cfsetispeed(&options, B115200); + cfsetospeed(&options, B115200);
+ /* set raw input, 1 second timeout */ + options.c_cflag |= (CLOCAL | CREAD); + options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); + options.c_oflag &= ~OPOST; + options.c_iflag |= IGNCR; + options.c_cc[VMIN] = 0; + options.c_cc[VTIME] = 100; + + tcsetattr(s->fd, TCSANOW, &options); + + tcflush(s->fd, TCIOFLUSH); + } +#endif s->buffer = mallocz(BUFFER_SIZE); s->command = mallocz(BUFFER_SIZE); if (!s->buffer || !s->command) {