]> Git Repo - qemu.git/blobdiff - vl.c
Solaris tap device, by Sittichai Palingsong.
[qemu.git] / vl.c
diff --git a/vl.c b/vl.c
index cfe94c81626ea274eafc7d471541e37f6c5822e5..009febb4c9dc9737b77f64ade07cd07af3d9992b 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 <malloc.h>
 #include <linux/rtc.h>
 #include <linux/ppdev.h>
+#else
+#include <sys/stat.h>
+#include <sys/ethernet.h>
+#include <sys/sockio.h>
+#include <arpa/inet.h>
+#include <netinet/arp.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h> // must come after ip.h
+#include <netinet/udp.h>
+#include <netinet/tcp.h>
+#include <net/if.h>
+#include <syslog.h>
+#include <stropts.h>
 #endif
 #endif
 #endif
 /* XXX: use a two level table to limit memory usage */
 #define MAX_IOPORTS 65536
 
-#define DISK_OPTIONS_SIZE 256
-
 const char *bios_dir = CONFIG_QEMU_SHAREDIR;
 char phys_ram_file[1024];
 void *ioport_opaque[MAX_IOPORTS];
@@ -126,11 +139,7 @@ IOPortWriteFunc *ioport_write_table[3][MAX_IOPORTS];
 BlockDriverState *bs_table[MAX_DISKS + 1], *fd_table[MAX_FD];
 /* point to the block driver where the snapshots are managed */
 BlockDriverState *bs_snapshots;
-BlockDriverState *bs_scsi_table[MAX_SCSI_DISKS];
-SCSIDiskInfo scsi_disks_info[MAX_SCSI_DISKS];
-int scsi_hba_lsi; /* Count of scsi disks/cdrom using this lsi adapter */
 int vga_ram_size;
-int bios_size;
 static DisplayState display_state;
 int nographic;
 const char* keyboard_layout = NULL;
@@ -176,6 +185,8 @@ 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 */
@@ -311,49 +322,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
@@ -1165,6 +1133,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);
@@ -1177,6 +1168,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];
@@ -1193,29 +1197,25 @@ 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)
-{
-}
-
 static CharDriverState *qemu_chr_open_null(void)
 {
     CharDriverState *chr;
@@ -1224,7 +1224,6 @@ static 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;
 }
 
@@ -1316,9 +1315,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;
 
@@ -1338,7 +1334,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;
 }
 
@@ -1361,20 +1357,15 @@ static void fd_chr_read(void *opaque)
         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, 
@@ -1401,7 +1392,10 @@ static 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;
 }
 
@@ -1491,7 +1485,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':
@@ -1518,13 +1512,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;
             }
@@ -1535,14 +1527,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 */
@@ -1819,6 +1809,7 @@ static CharDriverState *qemu_chr_open_tty(const char *filename)
     if (!chr)
         return NULL;
     chr->chr_ioctl = tty_serial_ioctl;
+    qemu_chr_reset(chr);
     return chr;
 }
 
@@ -1880,8 +1871,10 @@ static 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;
 }
 
@@ -1896,9 +1889,6 @@ static 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;
@@ -1914,8 +1904,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;
@@ -1929,19 +1921,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;
@@ -1998,11 +1985,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;
 }
 
@@ -2040,14 +2027,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;
@@ -2063,47 +2053,39 @@ 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;
-}
-
 static CharDriverState *qemu_chr_open_win(const char *filename)
 {
     CharDriverState *chr;
@@ -2119,34 +2101,36 @@ static 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;
@@ -2198,11 +2182,11 @@ 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;
 }
 
@@ -2222,14 +2206,14 @@ static 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;
 }
 
@@ -2249,7 +2233,7 @@ static 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;
 }
     
@@ -2270,9 +2254,6 @@ static 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];
@@ -2294,15 +2275,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;
 }
@@ -2321,22 +2302,17 @@ 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);
     }
@@ -2386,7 +2362,7 @@ static 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:
@@ -2403,13 +2379,11 @@ 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;
 
@@ -2432,9 +2406,7 @@ static int tcp_chr_read_poll(void *opaque)
     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;
 }
 
@@ -2467,7 +2439,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++;
@@ -2514,21 +2486,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;
@@ -2537,6 +2498,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;
@@ -2554,6 +2516,12 @@ 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;
@@ -2587,6 +2555,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);
@@ -2611,6 +2581,7 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str,
     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
@@ -2641,6 +2612,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;
@@ -2673,10 +2646,10 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str,
     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) {
@@ -2723,6 +2696,7 @@ 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
@@ -3240,7 +3214,15 @@ static void tap_send(void *opaque)
     uint8_t buf[4096];
     int size;
 
+#ifdef __sun__
+    struct strbuf sbuf;
+    int f = 0;
+    sbuf.maxlen = sizeof(buf);
+    sbuf.buf = buf;
+    size = getmsg(s->fd, NULL, &sbuf, &f) >=0 ? sbuf.len : -1;
+#else
     size = read(s->fd, buf, sizeof(buf));
+#endif
     if (size > 0) {
         qemu_send_packet(s->vc, buf, size);
     }
@@ -3283,10 +3265,135 @@ static int tap_open(char *ifname, int ifname_size)
     return fd;
 }
 #elif defined(__sun__)
+#define TUNNEWPPA       (('T'<<16) | 0x0001)
+/* 
+ * Allocate TAP device, returns opened fd. 
+ * Stores dev name in the first arg(must be large enough).
+ */  
+int tap_alloc(char *dev)
+{
+    int tap_fd, if_fd, ppa = -1;
+    static int ip_fd = 0;
+    char *ptr;
+
+    static int arp_fd = 0;
+    int ip_muxid, arp_muxid;
+    struct strioctl  strioc_if, strioc_ppa;
+    int link_type = I_PLINK;;
+    struct lifreq ifr;
+    char actual_name[32] = "";
+
+    memset(&ifr, 0x0, sizeof(ifr));
+
+    if( *dev ){
+       ptr = dev;      
+       while( *ptr && !isdigit((int)*ptr) ) ptr++; 
+       ppa = atoi(ptr);
+    }
+
+    /* Check if IP device was opened */
+    if( ip_fd )
+       close(ip_fd);
+
+    if( (ip_fd = open("/dev/udp", O_RDWR, 0)) < 0){
+       syslog(LOG_ERR, "Can't open /dev/ip (actually /dev/udp)");
+       return -1;
+    }
+
+    if( (tap_fd = open("/dev/tap", O_RDWR, 0)) < 0){
+       syslog(LOG_ERR, "Can't open /dev/tap");
+       return -1;
+    }
+
+    /* Assign a new PPA and get its unit number. */
+    strioc_ppa.ic_cmd = TUNNEWPPA;
+    strioc_ppa.ic_timout = 0;
+    strioc_ppa.ic_len = sizeof(ppa);
+    strioc_ppa.ic_dp = (char *)&ppa;
+    if ((ppa = ioctl (tap_fd, I_STR, &strioc_ppa)) < 0)
+       syslog (LOG_ERR, "Can't assign new interface");
+
+    if( (if_fd = open("/dev/tap", O_RDWR, 0)) < 0){
+       syslog(LOG_ERR, "Can't open /dev/tap (2)");
+       return -1;
+    }
+    if(ioctl(if_fd, I_PUSH, "ip") < 0){
+       syslog(LOG_ERR, "Can't push IP module");
+       return -1;
+    }
+
+    if (ioctl(if_fd, SIOCGLIFFLAGS, &ifr) < 0)
+       syslog(LOG_ERR, "Can't get flags\n");
+
+    snprintf (actual_name, 32, "tap%d", ppa);
+    strncpy (ifr.lifr_name, actual_name, sizeof (ifr.lifr_name));
+
+    ifr.lifr_ppa = ppa;
+    /* Assign ppa according to the unit number returned by tun device */
+
+    if (ioctl (if_fd, SIOCSLIFNAME, &ifr) < 0)
+        syslog (LOG_ERR, "Can't set PPA %d", ppa);
+    if (ioctl(if_fd, SIOCGLIFFLAGS, &ifr) <0)
+        syslog (LOG_ERR, "Can't get flags\n");
+    /* Push arp module to if_fd */
+    if (ioctl (if_fd, I_PUSH, "arp") < 0)
+        syslog (LOG_ERR, "Can't push ARP module (2)");
+
+    /* Push arp module to ip_fd */
+    if (ioctl (ip_fd, I_POP, NULL) < 0)
+        syslog (LOG_ERR, "I_POP failed\n");
+    if (ioctl (ip_fd, I_PUSH, "arp") < 0)
+        syslog (LOG_ERR, "Can't push ARP module (3)\n");
+    /* Open arp_fd */
+    if ((arp_fd = open ("/dev/tap", O_RDWR, 0)) < 0)
+       syslog (LOG_ERR, "Can't open %s\n", "/dev/tap");
+
+    /* Set ifname to arp */
+    strioc_if.ic_cmd = SIOCSLIFNAME;
+    strioc_if.ic_timout = 0;
+    strioc_if.ic_len = sizeof(ifr);
+    strioc_if.ic_dp = (char *)&ifr;
+    if (ioctl(arp_fd, I_STR, &strioc_if) < 0){
+        syslog (LOG_ERR, "Can't set ifname to arp\n");
+    }
+
+    if((ip_muxid = ioctl(ip_fd, I_LINK, if_fd)) < 0){
+       syslog(LOG_ERR, "Can't link TAP device to IP");
+       return -1;
+    }
+
+    if ((arp_muxid = ioctl (ip_fd, link_type, arp_fd)) < 0)
+        syslog (LOG_ERR, "Can't link TAP device to ARP");
+
+    close (if_fd);
+
+    memset(&ifr, 0x0, sizeof(ifr));
+    strncpy (ifr.lifr_name, actual_name, sizeof (ifr.lifr_name));
+    ifr.lifr_ip_muxid  = ip_muxid;
+    ifr.lifr_arp_muxid = arp_muxid;
+
+    if (ioctl (ip_fd, SIOCSLIFMUXID, &ifr) < 0)
+    {
+      ioctl (ip_fd, I_PUNLINK , arp_muxid);
+      ioctl (ip_fd, I_PUNLINK, ip_muxid);
+      syslog (LOG_ERR, "Can't set multiplexor id");
+    }
+
+    sprintf(dev, "tap%d", ppa);
+    return tap_fd;
+}
+
 static int tap_open(char *ifname, int ifname_size)
 {
-    fprintf(stderr, "warning: tap_open not yet implemented\n");
-    return -1;
+    char  dev[10]="";
+    int fd;
+    if( (fd = tap_alloc(dev)) < 0 ){
+       fprintf(stderr, "Cannot allocate TAP device\n");
+       return -1;
+    }
+    pstrcpy(ifname, ifname_size, dev);
+    fcntl(fd, F_SETFL, O_NONBLOCK);
+    return fd;
 }
 #else
 static int tap_open(char *ifname, int ifname_size)
@@ -3334,7 +3441,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 */
@@ -3906,7 +4013,9 @@ static 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);
             }
@@ -3955,178 +4064,6 @@ void do_info_network(void)
     }
 }
 
-/* Parse IDE and SCSI disk options */
-static int disk_options_init(int num_ide_disks,
-                             char ide_disk_options[][DISK_OPTIONS_SIZE],
-                             int snapshot,
-                             int num_scsi_disks,
-                             char scsi_disk_options[][DISK_OPTIONS_SIZE],
-                             int cdrom_index,
-                             int cyls,
-                             int heads,
-                             int secs,
-                             int translation)
-{
-    char buf[256];
-    char dev_name[64];
-    int id, i, j;
-    int cdrom_device;
-    int ide_cdrom_created = 0;
-    int scsi_index;
-    scsi_host_adapters temp_adapter;
-
-    /* Process any IDE disks/cdroms */
-    for (i=0; i< num_ide_disks; i++) {
-        for (j=0; j<MAX_DISKS; j++) {
-            if (ide_disk_options[j][0] == '\0')
-                continue;
-
-            if (get_param_value(buf, sizeof(buf),"type",ide_disk_options[j])) {
-                if (!strcmp(buf, "disk")) {
-                    cdrom_device = 0;
-                } else if (!strcmp(buf, "cdrom")) {
-                    cdrom_device = 1;
-                    ide_cdrom_created = 1;
-                } else {
-                    fprintf(stderr, "qemu: invalid IDE disk type= value: %s\n", buf);
-                    return -1;
-                }
-            } else {
-                cdrom_device = 0;
-            }
-
-            if (cdrom_device) {
-                snprintf(dev_name, sizeof(dev_name), "cdrom%c", i + '0');
-            } else {
-                snprintf(dev_name, sizeof(dev_name), "hd%c", i + 'a');
-            }
-
-            if (!(get_param_value(buf, sizeof(buf),"img",ide_disk_options[j]))) {
-                fprintf(stderr, "qemu: missing IDE disk img= value.\n");
-                return -1;
-            }
-
-            if (!(bs_table[i] = bdrv_new(dev_name))) {
-                fprintf(stderr, "qemu: unable to create new block device for:%s\n",dev_name);
-                return -1;
-            }
-
-            if (cdrom_device) {
-                bdrv_set_type_hint(bs_table[i], BDRV_TYPE_CDROM);
-            }
-
-            if (bdrv_open(bs_table[i], buf, snapshot ? BDRV_O_SNAPSHOT : 0) < 0) {
-                fprintf(stderr, "qemu: could not open hard disk image: '%s'\n",
-                        buf);
-                return -1;
-            }
-            if (i == 0 && cyls != 0) {
-                bdrv_set_geometry_hint(bs_table[i], cyls, heads, secs);
-                bdrv_set_translation_hint(bs_table[i], translation);
-            }
-            ide_disk_options[j][0] = '\0';
-
-            if (i == cdrom_index) {
-                cdrom_index = -1;
-            }
-            break; /* finished with this IDE device*/
-        }
-    }
-
-    if (cdrom_index >= 0 && (!ide_cdrom_created)) {
-        bs_table[cdrom_index] = bdrv_new("cdrom");
-        bdrv_set_type_hint(bs_table[cdrom_index], BDRV_TYPE_CDROM);
-    }
-
-    for(i = 0; i < num_scsi_disks; i++) {
-
-#if !defined(TARGET_SPARC) || defined(TARGET_SPARC64)
-        temp_adapter = SCSI_LSI_53C895A;
-        scsi_hba_lsi++;
-#else
-        temp_adapter = SCSI_ESP;
-#endif
-
-        /*Check for sdx= parameter */
-        if (get_param_value(buf, sizeof(buf), "sdx", scsi_disk_options[i])) {
-            if (buf[0] >= 'a' && buf[0] <= 'g') {
-                scsi_index = buf[0] - 'a';
-            } else{
-                fprintf(stderr, "qemu: sdx= option for SCSI must be one letter from a-g. %s \n",buf);
-                exit(1);
-            }
-        } else {
-             scsi_index = 0;
-        }
-
-        /* Check for SCSI id specified. */
-        if (get_param_value(buf, sizeof(buf),"id",scsi_disk_options[i])) {
-            id = strtol(buf, NULL, 0);
-            if (id < 0 || id > 6) {
-                fprintf(stderr, "qemu: SCSI id must be from 0-6: %d\n", id);
-                return -1;
-            }
-            /* Check if id already used */
-            for(j = 0; j < MAX_SCSI_DISKS; j++) {
-                if (scsi_disks_info[j].device_type != SCSI_NONE &&
-                    j != i &&
-                    scsi_disks_info[j].adapter == temp_adapter &&
-                    scsi_disks_info[j].id == id  ) {
-                    fprintf(stderr, "qemu: SCSI id already used: %u\n", id);
-                    return -1;
-                }
-            }
-        } else {
-            id = -1;
-        }
-        scsi_disks_info[i].adapter = temp_adapter;
-        scsi_disks_info[i].id = id;
-
-        if (get_param_value(buf, sizeof(buf),"type",scsi_disk_options[i])) {
-            if (!strcmp(buf, "disk")) {
-                cdrom_device = 0;
-            } else if (!strcmp(buf, "cdrom")) {
-                cdrom_device = 1;
-            } else {
-                fprintf(stderr, "qemu: invalid SCSI disk type= value: %s\n", buf);
-                return -1;
-            }
-        } else {
-            cdrom_device = 0;
-        }
-
-        if (cdrom_device) {
-            snprintf(dev_name, sizeof(buf), "cdrom%c", scsi_index + '0');
-            scsi_disks_info[scsi_index].device_type = SCSI_CDROM;
-        } else {
-            snprintf(dev_name, sizeof(buf), "sd%c", scsi_index + 'a');
-            scsi_disks_info[scsi_index].device_type = SCSI_DISK;
-        }
-
-        if (!(bs_scsi_table[scsi_index] = bdrv_new(dev_name))) {
-            fprintf(stderr, "qemu: unable to create new block device for:%s\n",dev_name);
-            return -1;
-        }
-
-        /* Get image filename from options and then try to open it */
-        if (get_param_value(buf, sizeof(buf),"img",scsi_disk_options[i])) {
-            if (bdrv_open(bs_scsi_table[scsi_index], buf, 0) < 0) {
-                fprintf(stderr, "qemu: could not open SCSI disk image img='%s'\n",buf);
-                return -1;
-            }
-        } else {
-            fprintf(stderr, "qemu: SCSI disk image not specified for sd%c \n", i + 'a');
-            return -1;
-        }
-        if (cdrom_device) {
-            bdrv_set_type_hint(bs_scsi_table[scsi_index], BDRV_TYPE_CDROM);
-        }
-    }
-
-    return 0;
-}
-
-
 /***********************************************************/
 /* USB devices */
 
@@ -6223,7 +6160,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"
@@ -6234,11 +6171,7 @@ 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"
-           "-disk ide,img=file[,hdx=a..dd][,type=disk|cdrom] \n"
-           "                defaults are: hdx=a,type=disk \n"
-           "-disk scsi,img=file[,sdx=a..g][,type=disk|cdrom][,id=n]  \n"
-           "                defaults are: sdx=a,type=disk,id='auto assign' \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"
@@ -6285,6 +6218,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"
@@ -6420,8 +6354,8 @@ enum {
     QEMU_OPTION_no_acpi,
     QEMU_OPTION_no_reboot,
     QEMU_OPTION_daemonize,
-    QEMU_OPTION_disk,
     QEMU_OPTION_option_rom,
+    QEMU_OPTION_semihosting
 };
 
 typedef struct QEMUOption {
@@ -6432,6 +6366,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 },
@@ -6496,8 +6431,7 @@ const QEMUOption qemu_options[] = {
     { "usbdevice", HAS_ARG, QEMU_OPTION_usbdevice },
     { "smp", HAS_ARG, QEMU_OPTION_smp },
     { "vnc", HAS_ARG, QEMU_OPTION_vnc },
-    { "disk", HAS_ARG, QEMU_OPTION_disk },
-    
+
     /* temporary options */
     { "usb", 0, QEMU_OPTION_usb },
     { "cirrusvga", 0, QEMU_OPTION_cirrusvga },
@@ -6505,6 +6439,9 @@ const QEMUOption qemu_options[] = {
     { "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 },
 };
 
@@ -6566,6 +6503,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);
@@ -6716,15 +6654,10 @@ int main(int argc, char **argv)
     int i, cdrom_index;
     int snapshot, linux_boot;
     const char *initrd_filename;
-    const char *fd_filename[MAX_FD];
-    char scsi_options[MAX_SCSI_DISKS] [DISK_OPTIONS_SIZE];
-    char ide_options[MAX_DISKS] [DISK_OPTIONS_SIZE];
-    int num_ide_disks;
-    int num_scsi_disks;
+    const char *hd_filename[MAX_DISKS], *fd_filename[MAX_FD];
     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;
@@ -6775,22 +6708,12 @@ int main(int argc, char **argv)
     register_machines();
     machine = first_machine;
     initrd_filename = NULL;
-    for(i = 0; i < MAX_SCSI_DISKS; i++) {
-        scsi_disks_info[i].device_type = SCSI_NONE;
-        bs_scsi_table[i] = NULL;
-    }
-
-    num_ide_disks = 0;
-    num_scsi_disks = 0;
-
     for(i = 0; i < MAX_FD; i++)
         fd_filename[i] = NULL;
-    for(i = 0; i < MAX_DISKS; i++) {
-        ide_options[i][0] =  '\0';
-    }
+    for(i = 0; i < MAX_DISKS; i++)
+        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;
@@ -6831,20 +6754,14 @@ int main(int argc, char **argv)
             break;
         r = argv[optind];
         if (r[0] != '-') {
-
-        /* Build new disk IDE syntax string */
-        pstrcpy(ide_options[0],
-                14,
-                "hdx=a,img=");
-        /*Add on image filename */
-        pstrcpy(&(ide_options[0][13]),
-                sizeof(ide_options[0])-13,
-                argv[optind++]);
-        num_ide_disks++;
+            hd_filename[0] = argv[optind++];
         } else {
             const QEMUOption *popt;
 
             optind++;
+            /* Treat --foo the same as -foo.  */
+            if (r[1] == '-')
+                r++;
             popt = qemu_options;
             for(;;) {
                 if (!popt->name) {
@@ -6890,75 +6807,10 @@ int main(int argc, char **argv)
             case QEMU_OPTION_hdd:
                 {
                     int hd_index;
-                    const char newIDE_DiskSyntax [][10] = {
-                       "hdx=a,img=", "hdx=b,img=", "hdx=c,img=", "hdx=d,img=" };
-
                     hd_index = popt->index - QEMU_OPTION_hda;
-                    if (num_ide_disks >= MAX_DISKS) {
-                        fprintf(stderr, "qemu: too many IDE disks defined.\n");
-                        exit(1);
-                    }
-                    /* Build new disk IDE syntax string */
-                    pstrcpy(ide_options[hd_index],
-                            11,
-                            newIDE_DiskSyntax[hd_index]);
-                    /* Add on image filename */
-                    pstrcpy(&(ide_options[hd_index][10]),
-                            sizeof(ide_options[0])-10,
-                            optarg);
-                    num_ide_disks++;
-                }
-                break;
-            case QEMU_OPTION_disk: /*Combined IDE and SCSI, for disk and CDROM */
-                {
-                    const char *p_input_char;
-                    char *p_output_string;
-                    char device[64];
-                    int disk_index;
-
-                    p_input_char = optarg;
-                    p_output_string = device;
-                    while (*p_input_char != '\0' && *p_input_char != ',') {
-                        if ((p_output_string - device) < sizeof(device) - 1)
-                            *p_output_string++ = *p_input_char;
-                        p_input_char++;
-                    }
-                    *p_output_string = '\0';
-                    if (*p_input_char == ',')
-                        p_input_char++;
-
-                    if (!strcmp(device, "scsi")) {
-                        if (num_scsi_disks >= MAX_SCSI_DISKS) {
-                            fprintf(stderr, "qemu: too many SCSI disks defined.\n");
-                            exit(1);
-                        }
-                        pstrcpy(scsi_options[num_scsi_disks],
-                                sizeof(scsi_options[0]),
-                                p_input_char);
-                        num_scsi_disks++;
-                    } else if (!strcmp(device,"ide")) {
-                        if (num_ide_disks >= MAX_DISKS) {
-                            fprintf(stderr, "qemu: too many IDE disks/cdroms defined.\n");
-                            exit(1);
-                        }
-                        disk_index = 0; /* default is hda */
-                        if (get_param_value(device, sizeof(device),"hdx",p_input_char)) {
-                            if (device[0] >= 'a' && device[0] <= 'd') {
-                                disk_index = device[0] - 'a';
-                            } else {
-                                fprintf(stderr, "qemu: invalid IDE disk hdx= value: %s\n", device);
-                                return -1;
-                            }
-                        }
-                        else disk_index=0;
-                        pstrcpy(ide_options[disk_index],
-                                sizeof(ide_options[0]),
-                                p_input_char);
-                        num_ide_disks++;
-                    } else {
-                        fprintf(stderr, "qemu: -disk option must specify IDE or SCSI: %s \n",device);
-                        exit(1);
-                    }
+                    hd_filename[hd_index] = optarg;
+                    if (hd_index == cdrom_index)
+                        cdrom_index = -1;
                 }
                 break;
             case QEMU_OPTION_snapshot:
@@ -7012,51 +6864,14 @@ int main(int argc, char **argv)
                 kernel_cmdline = optarg;
                 break;
             case QEMU_OPTION_cdrom:
-#if !defined(TARGET_SPARC) || defined(TARGET_SPARC64)
-                /* Assume boot cdrom is IDE */
-                {
-                    char buf[22];
-                    if (num_ide_disks >= MAX_DISKS) {
-                        fprintf(stderr, "qemu: too many IDE disks/cdroms defined.\n");
-                        exit(1);
-                    }
-                    snprintf(buf, sizeof(buf), "type=cdrom,hdx=%c,img=", cdrom_index + 'a');
-                    /* Build new disk IDE syntax string */
-                    pstrcpy(ide_options[cdrom_index],
-                            22,
-                            buf);
-                    /* Add on image filename */
-                    pstrcpy(&(ide_options[cdrom_index][21]),
-                            sizeof(ide_options[0])-21,
-                            optarg);
-                    num_ide_disks++;
-                }
-#else
-                /* Assume boot cdrom is SCSI */
-                {
-                    char buf[27];
-                    if (num_scsi_disks >= MAX_SCSI_DISKS) {
-                        fprintf(stderr, "qemu: too many SCSI disks/cdroms defined.\n");
-                        exit(1);
-                    }
-                    snprintf(buf, sizeof(buf), "type=cdrom,sdx=%c,id=%d,img=",
-                             num_scsi_disks + 'a', num_scsi_disks + 2);
-                    /* Build new disk SCSI syntax string */
-                    pstrcpy(scsi_options[num_scsi_disks],
-                            27,
-                            buf);
-                    /* Add on image filename */
-                    pstrcpy(&(scsi_options[num_scsi_disks][26]),
-                            sizeof(scsi_options[0])-26,
-                            optarg);
-                    num_scsi_disks++;
+                if (cdrom_index >= 0) {
+                    hd_filename[cdrom_index] = optarg;
                 }
-#endif
                 break;
             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
@@ -7152,7 +6967,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;
@@ -7289,6 +7104,9 @@ int main(int argc, char **argv)
                option_rom[nb_option_roms] = optarg;
                nb_option_roms++;
                break;
+            case QEMU_OPTION_semihosting:
+                semihosting_enabled = 1;
+                break;
             }
         }
     }
@@ -7348,11 +7166,19 @@ int main(int argc, char **argv)
     linux_boot = (kernel_filename != NULL);
 
     if (!linux_boot &&
-        num_ide_disks == 0 &&
-        num_scsi_disks == 0 &&
+        hd_filename[0] == '\0' && 
+        (cdrom_index >= 0 && hd_filename[cdrom_index] == '\0') &&
         fd_filename[0] == '\0')
         help();
 
+    /* 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';
+        else
+            boot_device = 'd';
+    }
+
     setvbuf(stdout, NULL, _IOLBF, 0);
     
     init_timers();
@@ -7378,17 +7204,30 @@ int main(int argc, char **argv)
             exit(1);
     }
 
-    /* init the memory */
-    phys_ram_size = ram_size + vga_ram_size + bios_size;
-
-    for (i = 0; i < nb_option_roms; i++) {
-       int ret = get_image_size(option_rom[i]);
-       if (ret == -1) {
-           fprintf(stderr, "Could not load option rom '%s'\n", option_rom[i]);
+#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);
        }
-       phys_ram_size += ret;
+       boot_device = 'c'; /* to prevent confusion by the BIOS */
     }
+#endif
+
+    /* init the memory */
+    phys_ram_size = ram_size + vga_ram_size + MAX_BIOS_SIZE;
 
     phys_ram_base = qemu_vmalloc(phys_ram_size);
     if (!phys_ram_base) {
@@ -7396,22 +7235,31 @@ int main(int argc, char **argv)
         exit(1);
     }
 
+    /* we always create the cdrom drive, even if no disk is there */
     bdrv_init();
-
-    /* open the virtual block devices, disks or CDRoms */
-    if (disk_options_init(num_ide_disks,ide_options,snapshot,
-                          num_scsi_disks,scsi_options,
-                          cdrom_index,
-                          cyls, heads, secs, translation)){
-        exit(1);
+    if (cdrom_index >= 0) {
+        bs_table[cdrom_index] = bdrv_new("cdrom");
+        bdrv_set_type_hint(bs_table[cdrom_index], BDRV_TYPE_CDROM);
     }
 
-    /* boot to floppy or default cd if no hard disk */
-    if (num_ide_disks == 0 && boot_device == 'c') {
-        if (fd_filename[0] != '\0')
-            boot_device = 'a';
-        else
-            boot_device = 'd';
+    /* open the virtual block devices */
+    for(i = 0; i < MAX_DISKS; i++) {
+        if (hd_filename[i]) {
+            if (!bs_table[i]) {
+                char buf[64];
+                snprintf(buf, sizeof(buf), "hd%c", i + 'a');
+                bs_table[i] = bdrv_new(buf);
+            }
+            if (bdrv_open(bs_table[i], hd_filename[i], snapshot ? BDRV_O_SNAPSHOT : 0) < 0) {
+                fprintf(stderr, "qemu: could not open hard disk image '%s'\n",
+                        hd_filename[i]);
+                exit(1);
+            }
+            if (i == 0 && cyls != 0) {
+                bdrv_set_geometry_hint(bs_table[i], cyls, heads, secs);
+                bdrv_set_translation_hint(bs_table[i], translation);
+            }
+        }
     }
 
     /* we always create at least one floppy disk */
@@ -7511,12 +7359,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
@@ -7526,7 +7374,7 @@ int main(int argc, char **argv)
     {
         /* XXX: simplify init */
         read_passwords();
-        if (start_emulation) {
+        if (autostart) {
             vm_start();
         }
     }
This page took 0.07293 seconds and 4 git commands to generate.