]> Git Repo - qemu.git/blobdiff - vl.c
Fix typo, and some reformatting.
[qemu.git] / vl.c
diff --git a/vl.c b/vl.c
index d422fedcf0f7c3751ed5593338ba8996dcdaa9e7..71e21be0d72faadc629f37594a77d12602e32b31 100644 (file)
--- a/vl.c
+++ b/vl.c
@@ -1,7 +1,7 @@
 /*
  * 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
@@ -120,7 +125,6 @@ BlockDriverState *bs_table[MAX_DISKS + 1], *fd_table[MAX_FD];
 /* 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;
@@ -143,6 +147,7 @@ int graphic_height = 600;
 #endif
 int graphic_depth = 15;
 int full_screen = 0;
+int no_quit = 0;
 CharDriverState *serial_hds[MAX_SERIAL_PORTS];
 CharDriverState *parallel_hds[MAX_PARALLEL_PORTS];
 #ifdef TARGET_I386
@@ -151,7 +156,7 @@ int win2k_install_hack = 0;
 int usb_enabled = 0;
 static VLANState *first_vlan;
 int smp_cpus = 1;
-int vnc_display = -1;
+const char *vnc_display;
 #if defined(TARGET_SPARC)
 #define MAX_CPUS 16
 #elif defined(TARGET_I386)
@@ -161,6 +166,12 @@ int vnc_display = -1;
 #endif
 int acpi_enabled = 1;
 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 */
@@ -273,7 +284,7 @@ int register_ioport_write(int start, int length, int size,
     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;
@@ -296,49 +307,6 @@ void isa_unassign_ioport(int start, int length)
 
 /***********************************************************/
 
-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
@@ -450,9 +418,8 @@ void hw_error(const char *fmt, ...)
 
 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)
 {
@@ -460,11 +427,68 @@ 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)
@@ -476,15 +500,72 @@ 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 */
@@ -1037,6 +1118,29 @@ void quit_timers(void)
 /***********************************************************/
 /* 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);
@@ -1049,6 +1153,19 @@ int qemu_chr_ioctl(CharDriverState *s, int cmd, void *arg)
     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];
@@ -1065,30 +1182,26 @@ void qemu_chr_send_event(CharDriverState *s, int event)
         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;
 
@@ -1096,7 +1209,6 @@ CharDriverState *qemu_chr_open_null(void)
     if (!chr)
         return NULL;
     chr->chr_write = null_chr_write;
-    chr->chr_add_read_handler = null_chr_add_read_handler;
     return chr;
 }
 
@@ -1188,9 +1300,6 @@ void socket_set_nonblock(int fd)
 
 typedef struct {
     int fd_in, fd_out;
-    IOCanRWHandler *fd_can_read; 
-    IOReadHandler *fd_read;
-    void *fd_opaque;
     int max_size;
 } FDCharDriver;
 
@@ -1210,7 +1319,7 @@ 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);
+    s->max_size = qemu_chr_can_read(chr);
     return s->max_size;
 }
 
@@ -1227,21 +1336,21 @@ static void fd_chr_read(void *opaque)
     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) {
-        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, 
@@ -1251,7 +1360,7 @@ static void fd_chr_add_read_handler(CharDriverState *chr,
 }
 
 /* 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;
@@ -1268,11 +1377,14 @@ CharDriverState *qemu_chr_open_fd(int fd_in, int fd_out)
     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;
 
@@ -1282,14 +1394,25 @@ CharDriverState *qemu_chr_open_file_out(const char *file_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);
 }
 
 
@@ -1347,7 +1470,7 @@ static void stdio_received_byte(int ch)
 
                 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':
@@ -1374,13 +1497,11 @@ static void stdio_received_byte(int ch)
         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;
             }
@@ -1391,14 +1512,12 @@ static void stdio_received_byte(int 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 */
@@ -1496,7 +1615,7 @@ static void term_init(void)
     fcntl(0, F_SETFL, O_NONBLOCK);
 }
 
-CharDriverState *qemu_chr_open_stdio(void)
+static CharDriverState *qemu_chr_open_stdio(void)
 {
     CharDriverState *chr;
 
@@ -1522,7 +1641,7 @@ CharDriverState *qemu_chr_open_stdio(void)
 }
 
 #if defined(__linux__)
-CharDriverState *qemu_chr_open_pty(void)
+static CharDriverState *qemu_chr_open_pty(void)
 {
     struct termios tty;
     char slave_name[1024];
@@ -1661,7 +1780,7 @@ static int tty_serial_ioctl(CharDriverState *chr, int cmd, void *arg)
     return 0;
 }
 
-CharDriverState *qemu_chr_open_tty(const char *filename)
+static CharDriverState *qemu_chr_open_tty(const char *filename)
 {
     CharDriverState *chr;
     int fd;
@@ -1675,6 +1794,7 @@ CharDriverState *qemu_chr_open_tty(const char *filename)
     if (!chr)
         return NULL;
     chr->chr_ioctl = tty_serial_ioctl;
+    qemu_chr_reset(chr);
     return chr;
 }
 
@@ -1715,7 +1835,7 @@ static int pp_ioctl(CharDriverState *chr, int cmd, void *arg)
     return 0;
 }
 
-CharDriverState *qemu_chr_open_pp(const char *filename)
+static CharDriverState *qemu_chr_open_pp(const char *filename)
 {
     CharDriverState *chr;
     int fd;
@@ -1736,13 +1856,15 @@ CharDriverState *qemu_chr_open_pp(const char *filename)
     }
     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;
 }
@@ -1752,9 +1874,6 @@ CharDriverState *qemu_chr_open_pty(void)
 
 #ifdef _WIN32
 typedef struct {
-    IOCanRWHandler *fd_can_read; 
-    IOReadHandler *fd_read;
-    void *win_opaque;
     int max_size;
     HANDLE hcom, hrecv, hsend;
     OVERLAPPED orecv, osend;
@@ -1770,8 +1889,10 @@ typedef struct {
 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;
@@ -1785,19 +1906,14 @@ static void win_chr_close2(WinCharState *s)
         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;
@@ -1854,11 +1970,11 @@ static int win_chr_init(WinCharState *s, const char *filename)
         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;
 }
 
@@ -1896,14 +2012,17 @@ static int win_chr_write(CharDriverState *chr, const uint8_t *buf, int len1)
     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;
@@ -1919,48 +2038,40 @@ static void win_chr_readfile(WinCharState *s)
     }
 
     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;
@@ -1975,34 +2086,36 @@ CharDriverState *qemu_chr_open_win(const char *filename)
     }
     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;
@@ -2054,16 +2167,16 @@ static int win_chr_pipe_init(WinCharState *s, const char *filename)
         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;
@@ -2078,18 +2191,18 @@ CharDriverState *qemu_chr_open_win_pipe(const char *filename)
     }
     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;
@@ -2105,11 +2218,11 @@ CharDriverState *qemu_chr_open_win_file(HANDLE fd_out)
     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;
     
@@ -2126,9 +2239,6 @@ CharDriverState *qemu_chr_open_win_file_out(const char *file_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];
@@ -2150,15 +2260,15 @@ static int udp_chr_read_poll(void *opaque)
     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;
 }
@@ -2177,33 +2287,31 @@ static void udp_chr_read(void *opaque)
 
     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);
+#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;
@@ -2239,7 +2347,7 @@ CharDriverState *qemu_chr_open_udp(const char *def)
     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:
@@ -2256,13 +2364,12 @@ 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;
 
 static void tcp_chr_accept(void *opaque);
@@ -2284,7 +2391,7 @@ static int tcp_chr_read_poll(void *opaque)
     TCPCharDriver *s = chr->opaque;
     if (!s->connected)
         return 0;
-    s->max_size = s->fd_can_read(s->fd_opaque);
+    s->max_size = qemu_chr_can_read(chr);
     return s->max_size;
 }
 
@@ -2317,7 +2424,7 @@ static void tcp_chr_process_IAC_bytes(CharDriverState *chr,
             } 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++;
@@ -2364,21 +2471,10 @@ static void tcp_chr_read(void *opaque)
         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;
@@ -2387,6 +2483,7 @@ static void tcp_chr_connect(void *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;
@@ -2404,17 +2501,36 @@ static void tcp_chr_telnet_init(int fd)
     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;
     TCPCharDriver *s = chr->opaque;
     struct sockaddr_in saddr;
+#ifndef _WIN32
+    struct sockaddr_un uaddr;
+#endif
+    struct sockaddr *addr;
     socklen_t len;
     int fd;
 
     for(;;) {
-        len = sizeof(saddr);
-        fd = accept(s->listen_fd, (struct sockaddr *)&saddr, &len);
+#ifndef _WIN32
+       if (s->is_unix) {
+           len = sizeof(uaddr);
+           addr = (struct sockaddr *)&uaddr;
+       } else
+#endif
+       {
+           len = sizeof(saddr);
+           addr = (struct sockaddr *)&saddr;
+       }
+        fd = accept(s->listen_fd, addr, &len);
         if (fd < 0 && errno != EINTR) {
             return;
         } else if (fd >= 0) {
@@ -2424,6 +2540,8 @@ static void tcp_chr_accept(void *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);
@@ -2440,18 +2558,37 @@ static void tcp_chr_close(CharDriverState *chr)
 }
 
 static CharDriverState *qemu_chr_open_tcp(const char *host_str, 
-                                          int is_telnet)
+                                          int is_telnet,
+                                         int is_unix)
 {
     CharDriverState *chr = NULL;
     TCPCharDriver *s = NULL;
     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
+    struct sockaddr_un uaddr;
+#endif
+    struct sockaddr *addr;
+    socklen_t addrlen;
 
-    if (parse_host_port(&saddr, host_str) < 0)
-        goto fail;
+#ifndef _WIN32
+    if (is_unix) {
+       addr = (struct sockaddr *)&uaddr;
+       addrlen = sizeof(uaddr);
+       if (parse_unix_path(&uaddr, host_str) < 0)
+           goto fail;
+    } else
+#endif
+    {
+       addr = (struct sockaddr *)&saddr;
+       addrlen = sizeof(saddr);
+       if (parse_host_port(&saddr, host_str) < 0)
+           goto fail;
+    }
 
     ptr = host_str;
     while((ptr = strchr(ptr,','))) {
@@ -2460,6 +2597,8 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str,
             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;
@@ -2474,8 +2613,14 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str,
     s = qemu_mallocz(sizeof(TCPCharDriver));
     if (!s)
         goto fail;
-    
-    fd = socket(PF_INET, SOCK_STREAM, 0);
+
+#ifndef _WIN32
+    if (is_unix)
+       fd = socket(PF_UNIX, SOCK_STREAM, 0);
+    else
+#endif
+       fd = socket(PF_INET, SOCK_STREAM, 0);
+       
     if (fd < 0) 
         goto fail;
 
@@ -2485,24 +2630,43 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str,
     s->connected = 0;
     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_close = tcp_chr_close;
+
     if (is_listen) {
         /* allow fast reuse */
-        val = 1;
-        setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(val));
+#ifndef _WIN32
+       if (is_unix) {
+           char path[109];
+           strncpy(path, uaddr.sun_path, 108);
+           path[108] = 0;
+           unlink(path);
+       } else
+#endif
+       {
+           val = 1;
+           setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(val));
+       }
         
-        ret = bind(fd, (struct sockaddr *)&saddr, sizeof(saddr));
-        if (ret < 0) 
+        ret = bind(fd, addr, addrlen);
+        if (ret < 0)
             goto fail;
+
         ret = listen(fd, 0);
         if (ret < 0)
             goto fail;
+
         s->listen_fd = fd;
         qemu_set_fd_handler(s->listen_fd, tcp_chr_accept, NULL, chr);
         if (is_telnet)
             s->do_telnetopt = 1;
     } else {
         for(;;) {
-            ret = connect(fd, (struct sockaddr *)&saddr, sizeof(saddr));
+            ret = connect(fd, addr, addrlen);
             if (ret < 0) {
                 err = socket_error();
                 if (err == EINTR || err == EWOULDBLOCK) {
@@ -2517,16 +2681,13 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str,
             }
         }
         s->fd = fd;
+        socket_set_nodelay(fd);
         if (s->connected)
             tcp_chr_connect(chr);
         else
             qemu_set_fd_handler(s->fd, NULL, tcp_chr_connect, chr);
     }
     
-    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 && is_waitconnect) {
         printf("QEMU waiting for connection on: %s\n", host_str);
         tcp_chr_accept(chr);
@@ -2552,16 +2713,18 @@ CharDriverState *qemu_chr_open(const char *filename)
         return qemu_chr_open_null();
     } else 
     if (strstart(filename, "tcp:", &p)) {
-        return qemu_chr_open_tcp(p, 0);
+        return qemu_chr_open_tcp(p, 0, 0);
     } else
     if (strstart(filename, "telnet:", &p)) {
-        return qemu_chr_open_tcp(p, 1);
+        return qemu_chr_open_tcp(p, 1, 0);
     } else
     if (strstart(filename, "udp:", &p)) {
         return qemu_chr_open_udp(p);
     } else
 #ifndef _WIN32
-    if (strstart(filename, "file:", &p)) {
+    if (strstart(filename, "unix:", &p)) {
+       return qemu_chr_open_tcp(p, 0, 1);
+    } else if (strstart(filename, "file:", &p)) {
         return qemu_chr_open_file_out(p);
     } else if (strstart(filename, "pipe:", &p)) {
         return qemu_chr_open_pipe(p);
@@ -2736,6 +2899,26 @@ int parse_host_port(struct sockaddr_in *saddr, const char *str)
     return 0;
 }
 
+#ifndef _WIN32
+static int parse_unix_path(struct sockaddr_un *uaddr, const char *str)
+{
+    const char *p;
+    int len;
+
+    len = MIN(108, strlen(str));
+    p = strchr(str, ',');
+    if (p)
+       len = MIN(len, p - str);
+
+    memset(uaddr, 0, sizeof(*uaddr));
+
+    uaddr->sun_family = AF_UNIX;
+    memcpy(uaddr->sun_path, str, len);
+
+    return 0;
+}
+#endif
+
 /* find or alloc a new VLAN */
 VLANState *qemu_find_vlan(int id)
 {
@@ -2980,8 +3163,8 @@ void net_slirp_smb(const char *exported_dir)
     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);
 }
@@ -3110,7 +3293,7 @@ static int net_tap_init(VLANState *vlan, const char *ifname1,
     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 */
@@ -3591,7 +3774,7 @@ static int get_param_value(char *buf, int buf_size,
     return 0;
 }
 
-int net_client_init(const char *str)
+static int net_client_init(const char *str)
 {
     const char *p;
     char *q;
@@ -3682,7 +3865,9 @@ int net_client_init(const char *str)
             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);
             }
@@ -3730,7 +3915,7 @@ void do_info_network(void)
             term_printf("  %s\n", vc->info_str);
     }
 }
+
 /***********************************************************/
 /* USB devices */
 
@@ -4881,6 +5066,7 @@ void cpu_save(QEMUFile *f, void *opaque)
     qemu_put_be64s(f, &env->fmask);
     qemu_put_be64s(f, &env->kernelgsbase);
 #endif
+    qemu_put_be32s(f, &env->smbase);
 }
 
 #ifdef USE_X86LDOUBLE
@@ -4914,7 +5100,7 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
     uint32_t hflags;
     uint16_t fpus, fpuc, fptag, fpregs_format;
 
-    if (version_id != 3)
+    if (version_id != 3 && version_id != 4)
         return -EINVAL;
     for(i = 0; i < CPU_NB_REGS; i++)
         qemu_get_betls(f, &env->regs[i]);
@@ -5017,6 +5203,8 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
     qemu_get_be64s(f, &env->fmask);
     qemu_get_be64s(f, &env->kernelgsbase);
 #endif
+    if (version_id >= 4) 
+        qemu_get_be32s(f, &env->smbase);
 
     /* XXX: compute hflags from scratch, except for CPL and IIF */
     env->hflags = hflags;
@@ -5612,7 +5800,7 @@ void qemu_register_reset(QEMUResetHandler *func, void *opaque)
     *pre = re;
 }
 
-void qemu_system_reset(void)
+static void qemu_system_reset(void)
 {
     QEMUResetEntry *re;
 
@@ -5624,7 +5812,11 @@ void qemu_system_reset(void)
 
 void qemu_system_reset_request(void)
 {
-    reset_requested = 1;
+    if (no_reboot) {
+        shutdown_requested = 1;
+    } else {
+        reset_requested = 1;
+    }
     if (cpu_single_env)
         cpu_interrupt(cpu_single_env, CPU_INTERRUPT_EXIT);
 }
@@ -5820,7 +6012,7 @@ int main_loop(void)
 
 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"
@@ -5831,8 +6023,11 @@ void help(void)
            "-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"
-          "-snapshot       write to temporary files instead of disk image files\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"
+#endif
 #ifdef TARGET_I386
            "-no-fd-bootchk  disable boot signature checking for floppy disks\n"
 #endif
@@ -5840,7 +6035,7 @@ void help(void)
            "-smp n          set the number of CPUs to 'n' [default=1]\n"
            "-nographic      disable graphical output and redirect serial I/Os to console\n"
 #ifndef _WIN32
-          "-k language     use keyboard layout (for example \"fr\" for French)\n"
+           "-k language     use keyboard layout (for example \"fr\" for French)\n"
 #endif
 #ifdef HAS_AUDIO
            "-audio-help     print list of audio drivers and their options\n"
@@ -5875,6 +6070,7 @@ void help(void)
            "-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"
@@ -5922,8 +6118,13 @@ void help(void)
            "                (default is CL-GD5446 PCI VGA)\n"
            "-no-acpi        disable ACPI\n"
 #endif
+           "-no-reboot      exit instead of rebooting\n"
            "-loadvm file    start right away with a saved state (loadvm in monitor)\n"
           "-vnc display    start a VNC server on display\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"
@@ -5993,6 +6194,7 @@ enum {
     QEMU_OPTION_parallel,
     QEMU_OPTION_loadvm,
     QEMU_OPTION_full_screen,
+    QEMU_OPTION_no_quit,
     QEMU_OPTION_pidfile,
     QEMU_OPTION_no_kqemu,
     QEMU_OPTION_kernel_kqemu,
@@ -6002,6 +6204,10 @@ enum {
     QEMU_OPTION_smp,
     QEMU_OPTION_vnc,
     QEMU_OPTION_no_acpi,
+    QEMU_OPTION_no_reboot,
+    QEMU_OPTION_daemonize,
+    QEMU_OPTION_option_rom,
+    QEMU_OPTION_semihosting
 };
 
 typedef struct QEMUOption {
@@ -6012,6 +6218,7 @@ 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 },
@@ -6068,16 +6275,25 @@ const QEMUOption qemu_options[] = {
     { "parallel", 1, QEMU_OPTION_parallel },
     { "loadvm", HAS_ARG, QEMU_OPTION_loadvm },
     { "full-screen", 0, QEMU_OPTION_full_screen },
+#ifdef CONFIG_SDL
+    { "no-quit", 0, QEMU_OPTION_no_quit },
+#endif
     { "pidfile", HAS_ARG, QEMU_OPTION_pidfile },
     { "win2k-hack", 0, QEMU_OPTION_win2k_hack },
     { "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 },
 };
 
@@ -6139,6 +6355,7 @@ void register_machines(void)
     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);
@@ -6150,6 +6367,7 @@ void register_machines(void)
     qemu_register_machine(&integratorcp1026_machine);
     qemu_register_machine(&versatilepb_machine);
     qemu_register_machine(&versatileab_machine);
+    qemu_register_machine(&realview_machine);
 #elif defined(TARGET_SH4)
     qemu_register_machine(&shix_machine);
 #else
@@ -6292,7 +6510,6 @@ int main(int argc, char **argv)
     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;
@@ -6307,6 +6524,7 @@ int main(int argc, char **argv)
     QEMUMachine *machine;
     char usb_devices[MAX_USB_CMDLINE][128];
     int usb_devices_index;
+    int fds[2];
 
     LIST_INIT (&vm_change_state_head);
 #ifndef _WIN32
@@ -6348,7 +6566,6 @@ int main(int argc, char **argv)
         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;
@@ -6394,6 +6611,9 @@ int main(int argc, char **argv)
             const QEMUOption *popt;
 
             optind++;
+            /* Treat --foo the same as -foo.  */
+            if (r[1] == '-')
+                r++;
             popt = qemu_options;
             for(;;) {
                 if (!popt->name) {
@@ -6503,7 +6723,7 @@ int main(int argc, char **argv)
             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
@@ -6599,7 +6819,7 @@ int main(int argc, char **argv)
                 bios_dir = optarg;
                 break;
             case QEMU_OPTION_S:
-                start_emulation = 0;
+                autostart = 0;
                 break;
            case QEMU_OPTION_k:
                keyboard_layout = optarg;
@@ -6674,6 +6894,11 @@ int main(int argc, char **argv)
             case QEMU_OPTION_full_screen:
                 full_screen = 1;
                 break;
+#ifdef CONFIG_SDL
+            case QEMU_OPTION_no_quit:
+                no_quit = 1;
+                break;
+#endif
             case QEMU_OPTION_pidfile:
                 create_pidfile(optarg);
                 break;
@@ -6712,32 +6937,93 @@ int main(int argc, char **argv)
                 }
                 break;
            case QEMU_OPTION_vnc:
-               vnc_display = atoi(optarg);
-               if (vnc_display < 0) {
-                   fprintf(stderr, "Invalid VNC display\n");
-                   exit(1);
-               }
+               vnc_display = optarg;
                break;
             case QEMU_OPTION_no_acpi:
                 acpi_enabled = 0;
                 break;
+            case QEMU_OPTION_no_reboot:
+                no_reboot = 1;
+                break;
+           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;
             }
         }
     }
 
+#ifndef _WIN32
+    if (daemonize && !nographic && vnc_display == NULL) {
+       fprintf(stderr, "Can only daemonize if using -nographic or -vnc\n");
+       daemonize = 0;
+    }
+
+    if (daemonize) {
+       pid_t pid;
+
+       if (pipe(fds) == -1)
+           exit(1);
+
+       pid = fork();
+       if (pid > 0) {
+           uint8_t status;
+           ssize_t len;
+
+           close(fds[1]);
+
+       again:
+           len = read(fds[0], &status, 1);
+           if (len == -1 && (errno == EINTR))
+               goto again;
+           
+           if (len != 1 || status != 0)
+               exit(1);
+           else
+               exit(0);
+       } else if (pid < 0)
+           exit(1);
+
+       setsid();
+
+       pid = fork();
+       if (pid > 0)
+           exit(0);
+       else if (pid < 0)
+           exit(1);
+
+       umask(027);
+       chdir("/");
+
+        signal(SIGTSTP, SIG_IGN);
+        signal(SIGTTOU, SIG_IGN);
+        signal(SIGTTIN, SIG_IGN);
+    }
+#endif
+
 #ifdef USE_KQEMU
     if (smp_cpus > 1)
         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';
@@ -6770,8 +7056,30 @@ int main(int argc, char **argv)
             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) {
@@ -6837,7 +7145,7 @@ int main(int argc, char **argv)
     /* terminal init */
     if (nographic) {
         dumb_display_init(ds);
-    } else if (vnc_display != -1) {
+    } else if (vnc_display != NULL) {
        vnc_display_init(ds, vnc_display);
     } else {
 #if defined(CONFIG_SDL)
@@ -6903,12 +7211,12 @@ int main(int argc, char **argv)
 
 #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
@@ -6918,10 +7226,35 @@ int main(int argc, char **argv)
     {
         /* XXX: simplify init */
         read_passwords();
-        if (start_emulation) {
+        if (autostart) {
             vm_start();
         }
     }
+
+    if (daemonize) {
+       uint8_t status = 0;
+       ssize_t len;
+       int fd;
+
+    again1:
+       len = write(fds[1], &status, 1);
+       if (len == -1 && (errno == EINTR))
+           goto again1;
+
+       if (len != 1)
+           exit(1);
+
+       fd = open("/dev/null", O_RDWR);
+       if (fd == -1)
+           exit(1);
+
+       dup2(fd, 0);
+       dup2(fd, 1);
+       dup2(fd, 2);
+
+       close(fd);
+    }
+
     main_loop();
     quit_timers();
     return 0;
This page took 0.084225 seconds and 4 git commands to generate.