/*
* QEMU System Emulator
*
- * Copyright (c) 2003-2006 Fabrice Bellard
+ * Copyright (c) 2003-2007 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
#include "exec-all.h"
#define DEFAULT_NETWORK_SCRIPT "/etc/qemu-ifup"
+#ifdef __sun__
+#define SMBD_COMMAND "/usr/sfw/sbin/smbd"
+#else
+#define SMBD_COMMAND "/usr/sbin/smbd"
+#endif
//#define DEBUG_UNUSED_IOPORT
//#define DEBUG_IOPORT
/* point to the block driver where the snapshots are managed */
BlockDriverState *bs_snapshots;
int vga_ram_size;
-int bios_size;
static DisplayState display_state;
int nographic;
const char* keyboard_layout = NULL;
int fd_bootchk = 1;
int no_reboot = 0;
int daemonize = 0;
+const char *option_rom[MAX_OPTION_ROMS];
+int nb_option_roms;
+int semihosting_enabled = 0;
+int autostart = 1;
/***********************************************************/
/* x86 ISA bus support */
for(i = start; i < start + length; i += size) {
ioport_write_table[bsize][i] = func;
if (ioport_opaque[i] != NULL && ioport_opaque[i] != opaque)
- hw_error("register_ioport_read: invalid opaque");
+ hw_error("register_ioport_write: invalid opaque");
ioport_opaque[i] = opaque;
}
return 0;
/***********************************************************/
-void pstrcpy(char *buf, int buf_size, const char *str)
-{
- int c;
- char *q = buf;
-
- if (buf_size <= 0)
- return;
-
- for(;;) {
- c = *str++;
- if (c == 0 || q >= buf + buf_size - 1)
- break;
- *q++ = c;
- }
- *q = '\0';
-}
-
-/* strcat and truncate. */
-char *pstrcat(char *buf, int buf_size, const char *s)
-{
- int len;
- len = strlen(buf);
- if (len < buf_size)
- pstrcpy(buf + len, buf_size - len, s);
- return buf;
-}
-
-int strstart(const char *str, const char *val, const char **ptr)
-{
- const char *p, *q;
- p = str;
- q = val;
- while (*q != '\0') {
- if (*p != *q)
- return 0;
- p++;
- q++;
- }
- if (ptr)
- *ptr = p;
- return 1;
-}
-
void cpu_outb(CPUState *env, int addr, int val)
{
#ifdef DEBUG_IOPORT
static QEMUPutKBDEvent *qemu_put_kbd_event;
static void *qemu_put_kbd_event_opaque;
-static QEMUPutMouseEvent *qemu_put_mouse_event;
-static void *qemu_put_mouse_event_opaque;
-static int qemu_put_mouse_event_absolute;
+static QEMUPutMouseEntry *qemu_put_mouse_event_head;
+static QEMUPutMouseEntry *qemu_put_mouse_event_current;
void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque)
{
qemu_put_kbd_event = func;
}
-void qemu_add_mouse_event_handler(QEMUPutMouseEvent *func, void *opaque, int absolute)
+QEMUPutMouseEntry *qemu_add_mouse_event_handler(QEMUPutMouseEvent *func,
+ void *opaque, int absolute,
+ const char *name)
{
- qemu_put_mouse_event_opaque = opaque;
- qemu_put_mouse_event = func;
- qemu_put_mouse_event_absolute = absolute;
+ QEMUPutMouseEntry *s, *cursor;
+
+ s = qemu_mallocz(sizeof(QEMUPutMouseEntry));
+ if (!s)
+ return NULL;
+
+ s->qemu_put_mouse_event = func;
+ s->qemu_put_mouse_event_opaque = opaque;
+ s->qemu_put_mouse_event_absolute = absolute;
+ s->qemu_put_mouse_event_name = qemu_strdup(name);
+ s->next = NULL;
+
+ if (!qemu_put_mouse_event_head) {
+ qemu_put_mouse_event_head = qemu_put_mouse_event_current = s;
+ return s;
+ }
+
+ cursor = qemu_put_mouse_event_head;
+ while (cursor->next != NULL)
+ cursor = cursor->next;
+
+ cursor->next = s;
+ qemu_put_mouse_event_current = s;
+
+ return s;
+}
+
+void qemu_remove_mouse_event_handler(QEMUPutMouseEntry *entry)
+{
+ QEMUPutMouseEntry *prev = NULL, *cursor;
+
+ if (!qemu_put_mouse_event_head || entry == NULL)
+ return;
+
+ cursor = qemu_put_mouse_event_head;
+ while (cursor != NULL && cursor != entry) {
+ prev = cursor;
+ cursor = cursor->next;
+ }
+
+ if (cursor == NULL) // does not exist or list empty
+ return;
+ else if (prev == NULL) { // entry is head
+ qemu_put_mouse_event_head = cursor->next;
+ if (qemu_put_mouse_event_current == entry)
+ qemu_put_mouse_event_current = cursor->next;
+ qemu_free(entry->qemu_put_mouse_event_name);
+ qemu_free(entry);
+ return;
+ }
+
+ prev->next = entry->next;
+
+ if (qemu_put_mouse_event_current == entry)
+ qemu_put_mouse_event_current = prev;
+
+ qemu_free(entry->qemu_put_mouse_event_name);
+ qemu_free(entry);
}
void kbd_put_keycode(int keycode)
void kbd_mouse_event(int dx, int dy, int dz, int buttons_state)
{
- if (qemu_put_mouse_event) {
- qemu_put_mouse_event(qemu_put_mouse_event_opaque,
- dx, dy, dz, buttons_state);
+ QEMUPutMouseEvent *mouse_event;
+ void *mouse_event_opaque;
+
+ if (!qemu_put_mouse_event_current) {
+ return;
+ }
+
+ mouse_event =
+ qemu_put_mouse_event_current->qemu_put_mouse_event;
+ mouse_event_opaque =
+ qemu_put_mouse_event_current->qemu_put_mouse_event_opaque;
+
+ if (mouse_event) {
+ mouse_event(mouse_event_opaque, dx, dy, dz, buttons_state);
}
}
int kbd_mouse_is_absolute(void)
{
- return qemu_put_mouse_event_absolute;
+ if (!qemu_put_mouse_event_current)
+ return 0;
+
+ return qemu_put_mouse_event_current->qemu_put_mouse_event_absolute;
+}
+
+void do_info_mice(void)
+{
+ QEMUPutMouseEntry *cursor;
+ int index = 0;
+
+ if (!qemu_put_mouse_event_head) {
+ term_printf("No mouse devices connected\n");
+ return;
+ }
+
+ term_printf("Mouse devices available:\n");
+ cursor = qemu_put_mouse_event_head;
+ while (cursor != NULL) {
+ term_printf("%c Mouse #%d: %s\n",
+ (cursor == qemu_put_mouse_event_current ? '*' : ' '),
+ index, cursor->qemu_put_mouse_event_name);
+ index++;
+ cursor = cursor->next;
+ }
+}
+
+void do_mouse_set(int index)
+{
+ QEMUPutMouseEntry *cursor;
+ int i = 0;
+
+ if (!qemu_put_mouse_event_head) {
+ term_printf("No mouse devices connected\n");
+ return;
+ }
+
+ cursor = qemu_put_mouse_event_head;
+ while (cursor != NULL && index != i) {
+ i++;
+ cursor = cursor->next;
+ }
+
+ if (cursor != NULL)
+ qemu_put_mouse_event_current = cursor;
+ else
+ term_printf("Mouse at given index not found\n");
}
/* compute with 96 bit intermediate result: (a*b)/c */
/***********************************************************/
/* character device */
+static void qemu_chr_event(CharDriverState *s, int event)
+{
+ if (!s->chr_event)
+ return;
+ s->chr_event(s->handler_opaque, event);
+}
+
+static void qemu_chr_reset_bh(void *opaque)
+{
+ CharDriverState *s = opaque;
+ qemu_chr_event(s, CHR_EVENT_RESET);
+ qemu_bh_delete(s->bh);
+ s->bh = NULL;
+}
+
+void qemu_chr_reset(CharDriverState *s)
+{
+ if (s->bh == NULL) {
+ s->bh = qemu_bh_new(qemu_chr_reset_bh, s);
+ qemu_bh_schedule(s->bh);
+ }
+}
+
int qemu_chr_write(CharDriverState *s, const uint8_t *buf, int len)
{
return s->chr_write(s, buf, len);
return s->chr_ioctl(s, cmd, arg);
}
+int qemu_chr_can_read(CharDriverState *s)
+{
+ if (!s->chr_can_read)
+ return 0;
+ return s->chr_can_read(s->handler_opaque);
+}
+
+void qemu_chr_read(CharDriverState *s, uint8_t *buf, int len)
+{
+ s->chr_read(s->handler_opaque, buf, len);
+}
+
+
void qemu_chr_printf(CharDriverState *s, const char *fmt, ...)
{
char buf[4096];
s->chr_send_event(s, event);
}
-void qemu_chr_add_read_handler(CharDriverState *s,
- IOCanRWHandler *fd_can_read,
- IOReadHandler *fd_read, void *opaque)
+void qemu_chr_add_handlers(CharDriverState *s,
+ IOCanRWHandler *fd_can_read,
+ IOReadHandler *fd_read,
+ IOEventHandler *fd_event,
+ void *opaque)
{
- s->chr_add_read_handler(s, fd_can_read, fd_read, 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);
}
-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)
+static CharDriverState *qemu_chr_open_null(void)
{
CharDriverState *chr;
if (!chr)
return NULL;
chr->chr_write = null_chr_write;
- chr->chr_add_read_handler = null_chr_add_read_handler;
return chr;
}
typedef struct {
int fd_in, fd_out;
- IOCanRWHandler *fd_can_read;
- IOReadHandler *fd_read;
- void *fd_opaque;
int max_size;
} FDCharDriver;
CharDriverState *chr = opaque;
FDCharDriver *s = chr->opaque;
- s->max_size = s->fd_can_read(s->fd_opaque);
+ s->max_size = qemu_chr_can_read(chr);
return s->max_size;
}
return;
}
if (size > 0) {
- s->fd_read(s->fd_opaque, buf, size);
+ qemu_chr_read(chr, buf, size);
}
}
-static void fd_chr_add_read_handler(CharDriverState *chr,
- IOCanRWHandler *fd_can_read,
- IOReadHandler *fd_read, void *opaque)
+static void fd_chr_update_read_handler(CharDriverState *chr)
{
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,
}
/* open a character device to a unix fd */
-CharDriverState *qemu_chr_open_fd(int fd_in, int fd_out)
+static CharDriverState *qemu_chr_open_fd(int fd_in, int fd_out)
{
CharDriverState *chr;
FDCharDriver *s;
s->fd_out = fd_out;
chr->opaque = s;
chr->chr_write = fd_chr_write;
- chr->chr_add_read_handler = fd_chr_add_read_handler;
+ chr->chr_update_read_handler = fd_chr_update_read_handler;
+
+ qemu_chr_reset(chr);
+
return chr;
}
-CharDriverState *qemu_chr_open_file_out(const char *file_out)
+static CharDriverState *qemu_chr_open_file_out(const char *file_out)
{
int fd_out;
return qemu_chr_open_fd(-1, fd_out);
}
-CharDriverState *qemu_chr_open_pipe(const char *filename)
+static 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);
+ 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);
+ fd_in = open(filename_in, O_RDWR | O_BINARY);
+ 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);
+ 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);
}
chr = stdio_clients[client_index];
s = chr->opaque;
- chr->chr_event(s->fd_opaque, CHR_EVENT_BREAK);
+ qemu_chr_event(chr, CHR_EVENT_BREAK);
}
break;
case 'c':
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) {
+ if (qemu_chr_can_read(chr) > 0) {
buf[0] = ch;
- s->fd_read(s->fd_opaque, buf, 1);
+ qemu_chr_read(chr, 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);
+ 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 */
fcntl(0, F_SETFL, O_NONBLOCK);
}
-CharDriverState *qemu_chr_open_stdio(void)
+static CharDriverState *qemu_chr_open_stdio(void)
{
CharDriverState *chr;
}
#if defined(__linux__)
-CharDriverState *qemu_chr_open_pty(void)
+static CharDriverState *qemu_chr_open_pty(void)
{
struct termios tty;
char slave_name[1024];
return 0;
}
-CharDriverState *qemu_chr_open_tty(const char *filename)
+static CharDriverState *qemu_chr_open_tty(const char *filename)
{
CharDriverState *chr;
int fd;
if (!chr)
return NULL;
chr->chr_ioctl = tty_serial_ioctl;
+ qemu_chr_reset(chr);
return chr;
}
return 0;
}
-CharDriverState *qemu_chr_open_pp(const char *filename)
+static CharDriverState *qemu_chr_open_pp(const char *filename)
{
CharDriverState *chr;
int fd;
}
chr->opaque = (void *)fd;
chr->chr_write = null_chr_write;
- chr->chr_add_read_handler = null_chr_add_read_handler;
chr->chr_ioctl = pp_ioctl;
+
+ qemu_chr_reset(chr);
+
return chr;
}
#else
-CharDriverState *qemu_chr_open_pty(void)
+static CharDriverState *qemu_chr_open_pty(void)
{
return NULL;
}
#ifdef _WIN32
typedef struct {
- IOCanRWHandler *fd_can_read;
- IOReadHandler *fd_read;
- void *win_opaque;
int max_size;
HANDLE hcom, hrecv, hsend;
OVERLAPPED orecv, osend;
static int win_chr_poll(void *opaque);
static int win_chr_pipe_poll(void *opaque);
-static void win_chr_close2(WinCharState *s)
+static void win_chr_close(CharDriverState *chr)
{
+ WinCharState *s = chr->opaque;
+
if (s->hsend) {
CloseHandle(s->hsend);
s->hsend = NULL;
s->hcom = NULL;
}
if (s->fpipe)
- qemu_del_polling_cb(win_chr_pipe_poll, s);
+ qemu_del_polling_cb(win_chr_pipe_poll, chr);
else
- qemu_del_polling_cb(win_chr_poll, s);
+ qemu_del_polling_cb(win_chr_poll, chr);
}
-static void win_chr_close(CharDriverState *chr)
+static int win_chr_init(CharDriverState *chr, const char *filename)
{
WinCharState *s = chr->opaque;
- win_chr_close2(s);
-}
-
-static int win_chr_init(WinCharState *s, const char *filename)
-{
COMMCONFIG comcfg;
COMMTIMEOUTS cto = { 0, 0, 0, 0, 0};
COMSTAT comstat;
fprintf(stderr, "Failed ClearCommError\n");
goto fail;
}
- qemu_add_polling_cb(win_chr_poll, s);
+ qemu_add_polling_cb(win_chr_poll, chr);
return 0;
fail:
- win_chr_close2(s);
+ win_chr_close(chr);
return -1;
}
return len1 - len;
}
-static int win_chr_read_poll(WinCharState *s)
+static int win_chr_read_poll(CharDriverState *chr)
{
- s->max_size = s->fd_can_read(s->win_opaque);
+ WinCharState *s = chr->opaque;
+
+ s->max_size = qemu_chr_can_read(chr);
return s->max_size;
}
-
-static void win_chr_readfile(WinCharState *s)
+
+static void win_chr_readfile(CharDriverState *chr)
{
+ WinCharState *s = chr->opaque;
int ret, err;
uint8_t buf[1024];
DWORD size;
}
if (size > 0) {
- s->fd_read(s->win_opaque, buf, size);
+ qemu_chr_read(chr, buf, size);
}
}
-static void win_chr_read(WinCharState *s)
+static void win_chr_read(CharDriverState *chr)
{
+ WinCharState *s = chr->opaque;
+
if (s->len > s->max_size)
s->len = s->max_size;
if (s->len == 0)
return;
- win_chr_readfile(s);
+ win_chr_readfile(chr);
}
static int win_chr_poll(void *opaque)
{
- WinCharState *s = opaque;
+ CharDriverState *chr = opaque;
+ WinCharState *s = chr->opaque;
COMSTAT status;
DWORD comerr;
ClearCommError(s->hcom, &comerr, &status);
if (status.cbInQue > 0) {
s->len = status.cbInQue;
- win_chr_read_poll(s);
- win_chr_read(s);
+ win_chr_read_poll(chr);
+ win_chr_read(chr);
return 1;
}
return 0;
}
-static void win_chr_add_read_handler(CharDriverState *chr,
- IOCanRWHandler *fd_can_read,
- IOReadHandler *fd_read, void *opaque)
-{
- WinCharState *s = chr->opaque;
-
- s->fd_can_read = fd_can_read;
- s->fd_read = fd_read;
- s->win_opaque = opaque;
-}
-
-CharDriverState *qemu_chr_open_win(const char *filename)
+static CharDriverState *qemu_chr_open_win(const char *filename)
{
CharDriverState *chr;
WinCharState *s;
}
chr->opaque = s;
chr->chr_write = win_chr_write;
- chr->chr_add_read_handler = win_chr_add_read_handler;
chr->chr_close = win_chr_close;
- if (win_chr_init(s, filename) < 0) {
+ if (win_chr_init(chr, filename) < 0) {
free(s);
free(chr);
return NULL;
}
+ qemu_chr_reset(chr);
return chr;
}
static int win_chr_pipe_poll(void *opaque)
{
- WinCharState *s = opaque;
+ CharDriverState *chr = opaque;
+ WinCharState *s = chr->opaque;
DWORD size;
PeekNamedPipe(s->hcom, NULL, 0, NULL, &size, NULL);
if (size > 0) {
s->len = size;
- win_chr_read_poll(s);
- win_chr_read(s);
+ win_chr_read_poll(chr);
+ win_chr_read(chr);
return 1;
}
return 0;
}
-static int win_chr_pipe_init(WinCharState *s, const char *filename)
+static int win_chr_pipe_init(CharDriverState *chr, const char *filename)
{
+ WinCharState *s = chr->opaque;
OVERLAPPED ov;
int ret;
DWORD size;
CloseHandle(ov.hEvent);
ov.hEvent = NULL;
}
- qemu_add_polling_cb(win_chr_pipe_poll, s);
+ qemu_add_polling_cb(win_chr_pipe_poll, chr);
return 0;
fail:
- win_chr_close2(s);
+ win_chr_close(chr);
return -1;
}
-CharDriverState *qemu_chr_open_win_pipe(const char *filename)
+static CharDriverState *qemu_chr_open_win_pipe(const char *filename)
{
CharDriverState *chr;
WinCharState *s;
}
chr->opaque = s;
chr->chr_write = win_chr_write;
- chr->chr_add_read_handler = win_chr_add_read_handler;
chr->chr_close = win_chr_close;
- if (win_chr_pipe_init(s, filename) < 0) {
+ if (win_chr_pipe_init(chr, filename) < 0) {
free(s);
free(chr);
return NULL;
}
+ qemu_chr_reset(chr);
return chr;
}
-CharDriverState *qemu_chr_open_win_file(HANDLE fd_out)
+static CharDriverState *qemu_chr_open_win_file(HANDLE fd_out)
{
CharDriverState *chr;
WinCharState *s;
s->hcom = fd_out;
chr->opaque = s;
chr->chr_write = win_chr_write;
- chr->chr_add_read_handler = win_chr_add_read_handler;
+ qemu_chr_reset(chr);
return chr;
}
-CharDriverState *qemu_chr_open_win_file_out(const char *file_out)
+static CharDriverState *qemu_chr_open_win_file_out(const char *file_out)
{
HANDLE fd_out;
/* UDP Net console */
typedef struct {
- IOCanRWHandler *fd_can_read;
- IOReadHandler *fd_read;
- void *fd_opaque;
int fd;
struct sockaddr_in daddr;
char buf[1024];
CharDriverState *chr = opaque;
NetCharDriver *s = chr->opaque;
- s->max_size = s->fd_can_read(s->fd_opaque);
+ s->max_size = qemu_chr_can_read(chr);
/* If there were any stray characters in the queue process them
* first
*/
while (s->max_size > 0 && s->bufptr < s->bufcnt) {
- s->fd_read(s->fd_opaque, &s->buf[s->bufptr], 1);
+ qemu_chr_read(chr, &s->buf[s->bufptr], 1);
s->bufptr++;
- s->max_size = s->fd_can_read(s->fd_opaque);
+ s->max_size = qemu_chr_can_read(chr);
}
return s->max_size;
}
s->bufptr = 0;
while (s->max_size > 0 && s->bufptr < s->bufcnt) {
- s->fd_read(s->fd_opaque, &s->buf[s->bufptr], 1);
+ qemu_chr_read(chr, &s->buf[s->bufptr], 1);
s->bufptr++;
- s->max_size = s->fd_can_read(s->fd_opaque);
+ s->max_size = qemu_chr_can_read(chr);
}
}
-static void udp_chr_add_read_handler(CharDriverState *chr,
- IOCanRWHandler *fd_can_read,
- IOReadHandler *fd_read, void *opaque)
+static void udp_chr_update_read_handler(CharDriverState *chr)
{
NetCharDriver *s = chr->opaque;
if (s->fd >= 0) {
- s->fd_can_read = fd_can_read;
- s->fd_read = fd_read;
- s->fd_opaque = opaque;
qemu_set_fd_handler2(s->fd, udp_chr_read_poll,
udp_chr_read, NULL, chr);
}
}
int parse_host_port(struct sockaddr_in *saddr, const char *str);
-int parse_unix_path(struct sockaddr_un *uaddr, const char *str);
+#ifndef _WIN32
+static int parse_unix_path(struct sockaddr_un *uaddr, const char *str);
+#endif
int parse_host_src_port(struct sockaddr_in *haddr,
struct sockaddr_in *saddr,
const char *str);
-CharDriverState *qemu_chr_open_udp(const char *def)
+static CharDriverState *qemu_chr_open_udp(const char *def)
{
CharDriverState *chr = NULL;
NetCharDriver *s = NULL;
s->bufptr = 0;
chr->opaque = s;
chr->chr_write = udp_chr_write;
- chr->chr_add_read_handler = udp_chr_add_read_handler;
+ chr->chr_update_read_handler = udp_chr_update_read_handler;
return chr;
return_err:
/* TCP Net console */
typedef struct {
- IOCanRWHandler *fd_can_read;
- IOReadHandler *fd_read;
- void *fd_opaque;
int fd, listen_fd;
int connected;
int max_size;
int do_telnetopt;
+ int do_nodelay;
int is_unix;
} TCPCharDriver;
TCPCharDriver *s = chr->opaque;
if (!s->connected)
return 0;
- if (!s->fd_can_read)
- return 0;
- s->max_size = s->fd_can_read(s->fd_opaque);
+ s->max_size = qemu_chr_can_read(chr);
return s->max_size;
}
} else {
if ((unsigned char)buf[i] == IAC_BREAK && s->do_telnetopt == 2) {
/* Handle IAC break commands by sending a serial break */
- chr->chr_event(s->fd_opaque, CHR_EVENT_BREAK);
+ qemu_chr_event(chr, CHR_EVENT_BREAK);
s->do_telnetopt++;
}
s->do_telnetopt++;
if (s->do_telnetopt)
tcp_chr_process_IAC_bytes(chr, s, buf, &size);
if (size > 0)
- s->fd_read(s->fd_opaque, buf, size);
+ qemu_chr_read(chr, buf, size);
}
}
-static void tcp_chr_add_read_handler(CharDriverState *chr,
- IOCanRWHandler *fd_can_read,
- IOReadHandler *fd_read, void *opaque)
-{
- TCPCharDriver *s = chr->opaque;
-
- s->fd_can_read = fd_can_read;
- s->fd_read = fd_read;
- s->fd_opaque = opaque;
-}
-
static void tcp_chr_connect(void *opaque)
{
CharDriverState *chr = opaque;
s->connected = 1;
qemu_set_fd_handler2(s->fd, tcp_chr_read_poll,
tcp_chr_read, NULL, chr);
+ qemu_chr_reset(chr);
}
#define IACSET(x,a,b,c) x[0] = a; x[1] = b; x[2] = c;
send(fd, (char *)buf, 3, 0);
}
+static void socket_set_nodelay(int fd)
+{
+ int val = 1;
+ setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val));
+}
+
static void tcp_chr_accept(void *opaque)
{
CharDriverState *chr = opaque;
}
}
socket_set_nonblock(fd);
+ if (s->do_nodelay)
+ socket_set_nodelay(fd);
s->fd = fd;
qemu_set_fd_handler(s->listen_fd, NULL, NULL, NULL);
tcp_chr_connect(chr);
int fd = -1, ret, err, val;
int is_listen = 0;
int is_waitconnect = 1;
+ int do_nodelay = 0;
const char *ptr;
struct sockaddr_in saddr;
#ifndef _WIN32
is_listen = 1;
} else if (!strncmp(ptr,"nowait",6)) {
is_waitconnect = 0;
+ } else if (!strncmp(ptr,"nodelay",6)) {
+ do_nodelay = 1;
} else {
printf("Unknown option: %s\n", ptr);
goto fail;
s->fd = -1;
s->listen_fd = -1;
s->is_unix = is_unix;
+ s->do_nodelay = do_nodelay && !is_unix;
chr->opaque = s;
chr->chr_write = tcp_chr_write;
- chr->chr_add_read_handler = tcp_chr_add_read_handler;
chr->chr_close = tcp_chr_close;
if (is_listen) {
}
}
s->fd = fd;
+ socket_set_nodelay(fd);
if (s->connected)
tcp_chr_connect(chr);
else
return 0;
}
-int parse_unix_path(struct sockaddr_un *uaddr, const char *str)
+#ifndef _WIN32
+static int parse_unix_path(struct sockaddr_un *uaddr, const char *str)
{
const char *p;
int len;
return 0;
}
+#endif
/* find or alloc a new VLAN */
VLANState *qemu_find_vlan(int id)
fclose(f);
atexit(smb_exit);
- snprintf(smb_cmdline, sizeof(smb_cmdline), "/usr/sbin/smbd -s %s",
- smb_conf);
+ snprintf(smb_cmdline, sizeof(smb_cmdline), "%s -s %s",
+ SMBD_COMMAND, smb_conf);
slirp_add_exec(0, smb_cmdline, 4, 139);
}
if (fd < 0)
return -1;
- if (!setup_script)
+ if (!setup_script || !strcmp(setup_script, "no"))
setup_script = "";
if (setup_script[0] != '\0') {
/* try to launch network init script */
return 0;
}
-int net_client_init(const char *str)
+static int net_client_init(const char *str)
{
const char *p;
char *q;
if (net_tap_fd_init(vlan, fd))
ret = 0;
} else {
- get_param_value(ifname, sizeof(ifname), "ifname", p);
+ if (get_param_value(ifname, sizeof(ifname), "ifname", p) <= 0) {
+ ifname[0] = '\0';
+ }
if (get_param_value(setup_script, sizeof(setup_script), "script", p) == 0) {
pstrcpy(setup_script, sizeof(setup_script), DEFAULT_NETWORK_SCRIPT);
}
term_printf(" %s\n", vc->info_str);
}
}
-
+
/***********************************************************/
/* USB devices */
*pre = re;
}
-void qemu_system_reset(void)
+static void qemu_system_reset(void)
{
QEMUResetEntry *re;
void help(void)
{
- printf("QEMU PC emulator version " QEMU_VERSION ", Copyright (c) 2003-2006 Fabrice Bellard\n"
+ printf("QEMU PC emulator version " QEMU_VERSION ", Copyright (c) 2003-2007 Fabrice Bellard\n"
"usage: %s [options] [disk_image]\n"
"\n"
"'disk_image' is a raw hard image image for IDE hard disk 0\n"
"-hda/-hdb file use 'file' as IDE hard disk 0/1 image\n"
"-hdc/-hdd file use 'file' as IDE hard disk 2/3 image\n"
"-cdrom file use 'file' as IDE cdrom image (cdrom is ide1 master)\n"
- "-boot [a|c|d] boot on floppy (a), hard disk (c) or CD-ROM (d)\n"
+ "-boot [a|c|d|n] boot on floppy (a), hard disk (c), CD-ROM (d), or network (n)\n"
"-snapshot write to temporary files instead of disk image files\n"
#ifdef CONFIG_SDL
"-no-quit disable SDL window close capability\n"
"-net tap[,vlan=n][,fd=h][,ifname=name][,script=file]\n"
" connect the host TAP network interface to VLAN 'n' and use\n"
" the network script 'file' (default=%s);\n"
+ " use 'script=no' to disable script execution;\n"
" use 'fd=h' to connect to an already opened TAP interface\n"
#endif
"-net socket[,vlan=n][,fd=h][,listen=[host]:port][,connect=host:port]\n"
#ifndef _WIN32
"-daemonize daemonize QEMU after initializing\n"
#endif
+ "-option-rom rom load a file, rom, into the option ROM space\n"
"\n"
"During emulation, the following keys are useful:\n"
"ctrl-alt-f toggle full screen\n"
QEMU_OPTION_no_acpi,
QEMU_OPTION_no_reboot,
QEMU_OPTION_daemonize,
+ QEMU_OPTION_option_rom,
+ QEMU_OPTION_semihosting
};
typedef struct QEMUOption {
const QEMUOption qemu_options[] = {
{ "h", 0, QEMU_OPTION_h },
+ { "help", 0, QEMU_OPTION_h },
{ "M", HAS_ARG, QEMU_OPTION_M },
{ "fda", HAS_ARG, QEMU_OPTION_fda },
{ "usbdevice", HAS_ARG, QEMU_OPTION_usbdevice },
{ "smp", HAS_ARG, QEMU_OPTION_smp },
{ "vnc", HAS_ARG, QEMU_OPTION_vnc },
-
+
/* temporary options */
{ "usb", 0, QEMU_OPTION_usb },
{ "cirrusvga", 0, QEMU_OPTION_cirrusvga },
{ "no-acpi", 0, QEMU_OPTION_no_acpi },
{ "no-reboot", 0, QEMU_OPTION_no_reboot },
{ "daemonize", 0, QEMU_OPTION_daemonize },
+ { "option-rom", HAS_ARG, QEMU_OPTION_option_rom },
+#if defined(TARGET_ARM)
+ { "semihosting", 0, QEMU_OPTION_semihosting },
+#endif
{ NULL },
};
qemu_register_machine(&prep_machine);
#elif defined(TARGET_MIPS)
qemu_register_machine(&mips_machine);
+ qemu_register_machine(&mips_malta_machine);
#elif defined(TARGET_SPARC)
#ifdef TARGET_SPARC64
qemu_register_machine(&sun4u_machine);
const char *kernel_filename, *kernel_cmdline;
DisplayState *ds = &display_state;
int cyls, heads, secs, translation;
- int start_emulation = 1;
char net_clients[MAX_NET_CLIENTS][256];
int nb_net_clients;
int optind;
hd_filename[i] = NULL;
ram_size = DEFAULT_RAM_SIZE * 1024 * 1024;
vga_ram_size = VGA_RAM_SIZE;
- bios_size = BIOS_SIZE;
#ifdef CONFIG_GDBSTUB
use_gdbstub = 0;
gdbstub_port = DEFAULT_GDBSTUB_PORT;
const QEMUOption *popt;
optind++;
+ /* Treat --foo the same as -foo. */
+ if (r[1] == '-')
+ r++;
popt = qemu_options;
for(;;) {
if (!popt->name) {
case QEMU_OPTION_boot:
boot_device = optarg[0];
if (boot_device != 'a' &&
-#ifdef TARGET_SPARC
+#if defined(TARGET_SPARC) || defined(TARGET_I386)
// Network boot
boot_device != 'n' &&
#endif
bios_dir = optarg;
break;
case QEMU_OPTION_S:
- start_emulation = 0;
+ autostart = 0;
break;
case QEMU_OPTION_k:
keyboard_layout = optarg;
case QEMU_OPTION_daemonize:
daemonize = 1;
break;
+ case QEMU_OPTION_option_rom:
+ if (nb_option_roms >= MAX_OPTION_ROMS) {
+ fprintf(stderr, "Too many option ROMs\n");
+ exit(1);
+ }
+ option_rom[nb_option_roms] = optarg;
+ nb_option_roms++;
+ break;
+ case QEMU_OPTION_semihosting:
+ semihosting_enabled = 1;
+ break;
}
}
}
kqemu_allowed = 0;
#endif
linux_boot = (kernel_filename != NULL);
-
- if (!linux_boot &&
+
+ if (!linux_boot &&
hd_filename[0] == '\0' &&
(cdrom_index >= 0 && hd_filename[cdrom_index] == '\0') &&
fd_filename[0] == '\0')
help();
-
- /* boot to cd by default if no hard disk */
+
+ /* boot to floppy or the default cd if no hard disk defined yet */
if (hd_filename[0] == '\0' && boot_device == 'c') {
if (fd_filename[0] != '\0')
boot_device = 'a';
exit(1);
}
+#ifdef TARGET_I386
+ if (boot_device == 'n') {
+ for (i = 0; i < nb_nics; i++) {
+ const char *model = nd_table[i].model;
+ char buf[1024];
+ if (model == NULL)
+ model = "ne2k_pci";
+ snprintf(buf, sizeof(buf), "%s/pxe-%s.bin", bios_dir, model);
+ if (get_image_size(buf) > 0) {
+ option_rom[nb_option_roms] = strdup(buf);
+ nb_option_roms++;
+ break;
+ }
+ }
+ if (i == nb_nics) {
+ fprintf(stderr, "No valid PXE rom found for network device\n");
+ exit(1);
+ }
+ boot_device = 'c'; /* to prevent confusion by the BIOS */
+ }
+#endif
+
/* init the memory */
- phys_ram_size = ram_size + vga_ram_size + bios_size;
+ phys_ram_size = ram_size + vga_ram_size + MAX_BIOS_SIZE;
phys_ram_base = qemu_vmalloc(phys_ram_size);
if (!phys_ram_base) {
#ifdef CONFIG_GDBSTUB
if (use_gdbstub) {
- if (gdbserver_start(gdbstub_port) < 0) {
- fprintf(stderr, "Could not open gdbserver socket on port %d\n",
+ /* XXX: use standard host:port notation and modify options
+ accordingly. */
+ if (gdbserver_start_port(gdbstub_port) < 0) {
+ fprintf(stderr, "qemu: could not open gdbstub device on port '%d'\n",
gdbstub_port);
exit(1);
- } else {
- printf("Waiting gdb connection on port %d\n", gdbstub_port);
}
} else
#endif
{
/* XXX: simplify init */
read_passwords();
- if (start_emulation) {
+ if (autostart) {
vm_start();
}
}