- added new serial modes based on SF patch #1928848 by Eugene Toder

* "pipe-server" (win32 only): It makes bochs a named pipe server so other
     application can communicate with it using pipes API. Useful e.g. for remote
     kernel debugging.
  * "pipe-client" (win32 only)
  * "socket-server": for the use with gdb
This commit is contained in:
Volker Ruppert 2008-05-22 08:13:22 +00:00
parent 4e091f2a3a
commit 966f2c8133
5 changed files with 147 additions and 19 deletions

View File

@ -426,18 +426,29 @@ debugger_log: -
# Then do `sleep 1000000' in the com1 window to keep the shell from
# messing with things, and run bochs in the other window. Serial I/O to
# com1 (port 0x3f8) will all go to the other window.
# In socket* and pipe* (win32 only) modes Bochs becomes either socket/named pipe
# client or server. In client mode it connects to an already running server (if
# connection fails Bochs treats com port as not connected). In server mode it
# opens socket/named pipe and waits until a client application connects to it
# before starting simulation. This mode is useful for remote debugging (e.g.
# with gdb's "target remote host:port" command or windbg's command line option
# -k com:pipe,port=\\.\pipe\pipename). Note: 'socket' is a shorthand for
# 'socket-client' and 'pipe' for 'pipe-client'. Socket modes use simple TCP
# communication, pipe modes use duplex byte mode pipes.
# Other serial modes are 'null' (no input/output), 'file' (output to a file
# specified as the 'dev' parameter), 'raw' (use the real serial port - under
# construction for win32), 'mouse' (standard serial mouse - requires
# mouse option setting 'type=serial', 'type=serial_wheel' or 'type=serial_msys')
# and 'socket' (connect a networking socket).
# mouse option setting 'type=serial', 'type=serial_wheel' or 'type=serial_msys').
#
# Examples:
# com1: enabled=1, mode=null
# com1: enabled=1, mode=mouse
# com2: enabled=1, mode=file, dev=serial.out
# com3: enabled=1, mode=raw, dev=com1
# com3: enabled=1, mode=socket, dev=localhost:8888
# com3: enabled=1, mode=socket-client, dev=localhost:8888
# com3: enabled=1, mode=socket-server, dev=localhost:8888
# com4: enabled=1, mode=pipe-client, dev=\\.\pipe\mypipe
# com4: enabled=1, mode=pipe-server, dev=\\.\pipe\mypipe
#=======================================================================
#com1: enabled=1, mode=term, dev=/dev/ttyp9

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: config.cc,v 1.133 2008-03-30 14:32:13 sshwarts Exp $
// $Id: config.cc,v 1.134 2008-05-22 08:13:21 vruppert Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2002 MandrakeSoft S.A.
@ -1253,10 +1253,15 @@ void bx_init_options()
static const char *serial_mode_list[] = {
"null",
"file",
"pipe",
"pipe-client",
"pipe-server",
"term",
"raw",
"mouse",
"socket",
"socket-client",
"socket-server",
NULL
};
@ -1273,7 +1278,7 @@ void bx_init_options()
enabled = new bx_param_bool_c(menu, "enabled", label, descr,
(i==0)?1 : 0); // only enable the first by default
sprintf(label, "I/O mode of the serial device for COM%d", i+1);
sprintf(descr, "The mode can be one these: 'null', 'file', 'term', 'raw', 'mouse', 'socket'");
sprintf(descr, "The mode can be one these: 'null', 'file', 'pipe', 'term', 'raw', 'mouse', 'socket'");
mode = new bx_param_enum_c(menu, "mode", label, descr,
serial_mode_list, 0, 0);
mode->set_ask_format("Choose I/O mode of the serial device [%s] ");

View File

@ -1,7 +1,7 @@
<!--
================================================================
doc/docbook/user/user.dbk
$Id: user.dbk,v 1.238 2008-05-12 18:46:46 vruppert Exp $
$Id: user.dbk,v 1.239 2008-05-22 08:13:21 vruppert Exp $
This is the top level file for the Bochs Users Manual.
================================================================
@ -3646,7 +3646,10 @@ Examples:
com1: enabled=1, mode=term, dev=/dev/ttyp9
com2: enabled=1, mode=file, dev=serial.out
com3: enabled=1, mode=raw, dev=com1
com3: enabled=1, mode=socket, dev=localhost:8888
com3: enabled=1, mode=socket-client, dev=localhost:8888
com3: enabled=1, mode=socket-server, dev=localhost:8888
com4: enabled=1, mode=pipe-client, dev=\\.\pipe\mypipe
com4: enabled=1, mode=pipe-server, dev=\\.\pipe\mypipe
</screen>
This defines a serial port (UART type 16550A).
</para>
@ -3660,12 +3663,24 @@ Examples:
things, and run Bochs in the other window. Serial I/O to com1 (port 0x3f8)
will all go to the other window.
</para>
<para>
When using socket* and pipe* (win32 only) modes Bochs becomes either
socket/named pipe client or server. In client mode it connects to an already
running server (if connection fails Bochs treats com port as not connected).
In server mode it opens socket/named pipe and waits until a client application
connects to it before starting simulation. This mode is useful for remote
debugging (e.g. with gdb's "target remote host:port" command or windbg's command
line option -k com:pipe,port=\\.\pipe\pipename).
Note: 'socket' is a shorthand for 'socket-client', 'pipe' for 'pipe-client'.
Socket modes use simple TCP communication, pipe modes use duplex byte mode pipes.
</para>
<para>
Other serial modes are 'null' (no input/output), 'file' (output to a file
specified as the 'dev' parameter), 'raw' (use the real serial port - under
construction for win32), 'mouse' (standard serial mouse - requires
<link linkend="bochsopt-mouse">mouse option</link> setting 'type=serial'
or 'type=serial_wheel') and 'socket' (connect a networking socket).
or 'type=serial_wheel').
</para>
</section>

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: serial.cc,v 1.81 2008-02-15 22:05:43 sshwarts Exp $
// $Id: serial.cc,v 1.82 2008-05-22 08:13:22 vruppert Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2004 MandrakeSoft S.A.
@ -41,6 +41,11 @@
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define closesocket(s) close(s)
#else
#ifndef FILE_FLAG_FIRST_PIPE_INSTANCE
#define FILE_FLAG_FIRST_PIPE_INSTANCE 0
#endif
#endif
#if USE_RAW_SERIAL
@ -104,7 +109,13 @@ bx_serial_c::~bx_serial_c(void)
#endif
break;
case BX_SER_MODE_SOCKET:
if (BX_SER_THIS s[i].socket_id >= 0) ::close(BX_SER_THIS s[i].socket_id);
if (BX_SER_THIS s[i].socket_id >= 0) closesocket(BX_SER_THIS s[i].socket_id);
break;
case BX_SER_MODE_PIPE:
#ifdef WIN32
if (BX_SER_THIS s[i].pipe)
CloseHandle(BX_SER_THIS s[i].pipe);
#endif
break;
}
}
@ -295,16 +306,17 @@ bx_serial_c::init(void)
BX_SER_THIS s[i].io_mode = BX_SER_MODE_MOUSE;
BX_SER_THIS mouse_port = i;
BX_SER_THIS mouse_type = SIM->get_param_enum(BXPN_MOUSE_TYPE)->get();
} else if (!strcmp(mode, "socket")) {
} else if (!strncmp(mode, "socket", 6)) {
BX_SER_THIS s[i].io_mode = BX_SER_MODE_SOCKET;
struct sockaddr_in sin;
struct hostent *hp;
char host[BX_PATHNAME_LEN];
int port;
int socket;
bx_bool server = !strcmp(mode, "socket-server");
#if defined(WIN32)
static bool winsock_init = false;
static bx_bool winsock_init = false;
if (!winsock_init) {
WORD wVersionRequested;
WSADATA wsaData;
@ -339,19 +351,81 @@ bx_serial_c::init(void)
sin.sin_port = htons (port);
socket = ::socket (AF_INET, SOCK_STREAM, 0);
if (socket < 0) {
if (socket < 0)
BX_PANIC(("com%d: socket() failed",i+1));
}
if (::connect (socket, (sockaddr *) &sin, sizeof (sin)) < 0) {
// server mode
if (server) {
if (::bind (socket, (sockaddr *) &sin, sizeof (sin)) < 0 ||
::listen (socket, SOMAXCONN) < 0) {
closesocket(socket);
socket = -1;
BX_PANIC(("com%d: bind() or listen() failed (host:%s, port:%d)",i+1, host, port));
}
else {
BX_INFO(("com%d: waiting for client to connect (host:%s, port:%d)",i+1, host, port));
int client;
if ((client = ::accept (socket, NULL, 0)) < 0)
BX_PANIC(("com%d: accept() failed (host:%s, port:%d)",i+1, host, port));
closesocket(socket);
socket = client;
}
}
// client mode
else if (::connect (socket, (sockaddr *) &sin, sizeof (sin)) < 0) {
closesocket(socket);
socket = -1;
BX_INFO(("com%d: connect() failed (host:%s, port:%d)",i+1, host, port));
} else {
BX_INFO(("com%d - inet - socket_id: %d, ip:%s, port:%d", i+1, socket, host, port));
}
BX_SER_THIS s[i].socket_id = socket;
if (socket > 0)
BX_INFO(("com%d - inet %s - socket_id: %d, ip:%s, port:%d",
i+1, server ? "server" : "client", socket, host, port));
} else if (!strncmp(mode, "pipe", 4)) {
if (strlen(dev) > 0) {
bx_bool server = !strcmp(mode, "pipe-server");
#ifdef WIN32
HANDLE pipe;
BX_SER_THIS s[i].io_mode = BX_SER_MODE_PIPE;
// server mode
if (server) {
pipe = CreateNamedPipe( dev,
PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE,
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
1, 4096, 4096, 0, NULL);
if (pipe == INVALID_HANDLE_VALUE)
BX_PANIC(("com%d: CreateNamedPipe(%s) failed", i+1, dev));
BX_INFO(("com%d: waiting for client to connect to %s", i+1, dev));
if (!ConnectNamedPipe(pipe, NULL) && GetLastError() != ERROR_PIPE_CONNECTED)
{
CloseHandle(pipe);
pipe = INVALID_HANDLE_VALUE;
BX_PANIC(("com%d: ConnectNamedPipe(%s) failed", i+1, dev));
}
}
// client mode
else {
pipe = CreateFile( dev,
GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING, 0, NULL);
if (pipe == INVALID_HANDLE_VALUE)
BX_INFO(("com%d: failed to open pipe %s", i+1, dev));
}
if (pipe != INVALID_HANDLE_VALUE)
BX_SER_THIS s[i].pipe = pipe;
#else
BX_PANIC(("support for serial mode '%s' not available", mode));
#endif
}
} else if (strcmp(mode, "null")) {
BX_PANIC(("unknown serial i/o mode"));
BX_PANIC(("unknown serial i/o mode '%s'", mode));
}
// simulate device connected
if (BX_SER_THIS s[i].io_mode != BX_SER_MODE_RAW) {
@ -1230,6 +1304,14 @@ bx_serial_c::tx_timer(void)
(bx_ptr_t) & BX_SER_THIS s[port].tsrbuffer, 1);
#endif
}
case BX_SER_MODE_PIPE:
#ifdef WIN32
if (BX_SER_THIS s[port].pipe) {
DWORD written;
WriteFile(BX_SER_THIS s[port].pipe, (bx_ptr_t)& BX_SER_THIS s[port].tsrbuffer, 1, &written, NULL);
}
#endif
break;
}
}
@ -1388,6 +1470,17 @@ bx_serial_c::rx_timer(void)
data_ready = 1;
}
break;
case BX_SER_MODE_PIPE:
#ifdef WIN32
DWORD avail = 0;
if (BX_SER_THIS s[port].pipe &&
PeekNamedPipe(BX_SER_THIS s[port].pipe, NULL, 0, NULL, &avail, NULL) &&
avail > 0) {
ReadFile(BX_SER_THIS s[port].pipe, &chbuf, 1, &avail, NULL);
data_ready = 1;
}
#endif
break;
}
if (data_ready) {
if (!BX_SER_THIS s[port].modem_cntl.local_loopback) {

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: serial.h,v 1.33 2008-01-26 22:24:02 sshwarts Exp $
// $Id: serial.h,v 1.34 2008-05-22 08:13:22 vruppert Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2004 MandrakeSoft S.A.
@ -75,6 +75,7 @@ extern "C" {
#define BX_SER_MODE_RAW 3
#define BX_SER_MODE_MOUSE 4
#define BX_SER_MODE_SOCKET 5
#define BX_SER_MODE_PIPE 6
enum {
BX_SER_INT_IER,
@ -119,6 +120,9 @@ typedef struct {
int tty_id;
int socket_id;
FILE *output;
#ifdef WIN32
HANDLE pipe;
#endif
#if USE_RAW_SERIAL
serial_raw* raw;