]> Git Repo - qemu.git/blobdiff - vl.c
removed unused variables
[qemu.git] / vl.c
diff --git a/vl.c b/vl.c
index cea4871be3881e0708e7ee049d9e8028bae4030f..d281f8a996bc99731965dcfc04c869971179c4c5 100644 (file)
--- a/vl.c
+++ b/vl.c
@@ -117,6 +117,7 @@ int inet_aton(const char *cp, struct in_addr *ia);
 #include "exec-all.h"
 
 #define DEFAULT_NETWORK_SCRIPT "/etc/qemu-ifup"
+#define DEFAULT_NETWORK_DOWN_SCRIPT "/etc/qemu-ifdown"
 #ifdef __sun__
 #define SMBD_COMMAND "/usr/sfw/sbin/smbd"
 #else
@@ -143,6 +144,7 @@ int inet_aton(const char *cp, struct in_addr *ia);
 #define MAX_IOPORTS 65536
 
 const char *bios_dir = CONFIG_QEMU_SHAREDIR;
+const char *bios_name = NULL;
 char phys_ram_file[1024];
 void *ioport_opaque[MAX_IOPORTS];
 IOPortReadFunc *ioport_read_table[3][MAX_IOPORTS];
@@ -160,13 +162,13 @@ static DisplayState display_state;
 int nographic;
 const char* keyboard_layout = NULL;
 int64_t ticks_per_sec;
-int boot_device = 'c';
 int ram_size;
 int pit_min_timer_count = 0;
 int nb_nics;
 NICInfo nd_table[MAX_NICS];
 int vm_running;
 int rtc_utc = 1;
+int rtc_start_date = -1; /* -1 means now */
 int cirrus_vga_enabled = 1;
 int vmsvga_enabled = 0;
 #ifdef TARGET_SPARC
@@ -358,7 +360,7 @@ void cpu_outb(CPUState *env, int addr, int val)
 #ifdef DEBUG_IOPORT
     if (loglevel & CPU_LOG_IOPORT)
         fprintf(logfile, "outb: %04x %02x\n", addr, val);
-#endif   
+#endif
     ioport_write_table[0][addr](ioport_opaque[addr], addr, val);
 #ifdef USE_KQEMU
     if (env)
@@ -371,7 +373,7 @@ void cpu_outw(CPUState *env, int addr, int val)
 #ifdef DEBUG_IOPORT
     if (loglevel & CPU_LOG_IOPORT)
         fprintf(logfile, "outw: %04x %04x\n", addr, val);
-#endif   
+#endif
     ioport_write_table[1][addr](ioport_opaque[addr], addr, val);
 #ifdef USE_KQEMU
     if (env)
@@ -634,7 +636,7 @@ uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
             uint32_t high, low;
 #else
             uint32_t low, high;
-#endif           
+#endif
         } l;
     } u, res;
     uint64_t rl, rh;
@@ -903,7 +905,7 @@ static void configure_alarms(char const *opt)
     while (name) {
         struct qemu_alarm_timer tmp;
 
-        for (i = 0; i < count; i++) {
+        for (i = 0; i < count && alarm_timers[i].name; i++) {
             if (!strcmp(alarm_timers[i].name, name))
                 break;
         }
@@ -988,8 +990,6 @@ void qemu_del_timer(QEMUTimer *ts)
         }
         pt = &t->next;
     }
-
-    qemu_rearm_alarm_timer(alarm_timer);
 }
 
 /* modify the current timer so that it will be fired when current_time
@@ -1037,7 +1037,7 @@ static inline int qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time
 static void qemu_run_timers(QEMUTimer **ptimer_head, int64_t current_time)
 {
     QEMUTimer *ts;
-   
+
     for(;;) {
         ts = *ptimer_head;
         if (!ts || ts->expire_time > current_time)
@@ -1045,7 +1045,7 @@ static void qemu_run_timers(QEMUTimer **ptimer_head, int64_t current_time)
         /* remove timer from the list before calling the callback */
         *ptimer_head = ts->next;
         ts->next = NULL;
-       
+
         /* run the callback (the timer list can be modified) */
         ts->cb(ts->opaque);
     }
@@ -1181,7 +1181,7 @@ static void host_alarm_handler(int host_signum)
 
 static uint64_t qemu_next_deadline(void)
 {
-    int64_t nearest_delta_us = UINT64_MAX;
+    int64_t nearest_delta_us = INT64_MAX;
     int64_t vmdelta_us;
 
     if (active_timers[QEMU_TIMER_REALTIME])
@@ -1216,9 +1216,6 @@ static void enable_sigio_timer(int fd)
     /* timer signal */
     sigfillset(&act.sa_mask);
     act.sa_flags = 0;
-#if defined (TARGET_I386) && defined(USE_CODE_COPY)
-    act.sa_flags |= SA_ONSTACK;
-#endif
     act.sa_handler = host_alarm_handler;
 
     sigaction(SIGIO, &act, NULL);
@@ -1316,9 +1313,6 @@ static int dynticks_start_timer(struct qemu_alarm_timer *t)
 
     sigfillset(&act.sa_mask);
     act.sa_flags = 0;
-#if defined(TARGET_I386) && defined(USE_CODE_COPY)
-    act.sa_flags |= SA_ONSTACK;
-#endif
     act.sa_handler = host_alarm_handler;
 
     sigaction(SIGALRM, &act, NULL);
@@ -1393,9 +1387,6 @@ static int unix_start_timer(struct qemu_alarm_timer *t)
     /* timer signal */
     sigfillset(&act.sa_mask);
     act.sa_flags = 0;
-#if defined(TARGET_I386) && defined(USE_CODE_COPY)
-    act.sa_flags |= SA_ONSTACK;
-#endif
     act.sa_handler = host_alarm_handler;
 
     sigaction(SIGALRM, &act, NULL);
@@ -1619,7 +1610,7 @@ void qemu_chr_add_handlers(CharDriverState *s,
     if (s->chr_update_read_handler)
         s->chr_update_read_handler(s);
 }
-            
+
 static int null_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
 {
     return len;
@@ -1874,7 +1865,7 @@ static int socket_init(void)
 static int send_all(int fd, const uint8_t *buf, int len1)
 {
     int ret, len;
-   
+
     len = len1;
     while (len > 0) {
         ret = send(fd, buf, len, 0);
@@ -1964,7 +1955,7 @@ static void fd_chr_read(void *opaque)
     FDCharDriver *s = chr->opaque;
     int size, len;
     uint8_t buf[1024];
-   
+
     len = sizeof(buf);
     if (len > s->max_size)
         len = s->max_size;
@@ -2125,7 +2116,7 @@ static void term_init(void)
     tty.c_cflag |= CS8;
     tty.c_cc[VMIN] = 1;
     tty.c_cc[VTIME] = 0;
-   
+
     tcsetattr (0, TCSANOW, &tty);
 
     atexit(term_exit);
@@ -2153,14 +2144,14 @@ static CharDriverState *qemu_chr_open_pty(void)
     struct termios tty;
     char slave_name[1024];
     int master_fd, slave_fd;
-   
+
 #if defined(__linux__)
     /* Not satisfying */
     if (openpty(&master_fd, &slave_fd, slave_name, NULL, NULL) < 0) {
         return NULL;
     }
 #endif
-   
+
     /* Disabling local echo and line-buffered output */
     tcgetattr (master_fd, &tty);
     tty.c_lflag &= ~(ECHO|ICANON|ISIG);
@@ -2260,14 +2251,14 @@ static void tty_serial_init(int fd, int speed,
     }
     if (stop_bits == 2)
         tty.c_cflag |= CSTOPB;
-   
+
     tcsetattr (fd, TCSANOW, &tty);
 }
 
 static int tty_serial_ioctl(CharDriverState *chr, int cmd, void *arg)
 {
     FDCharDriver *s = chr->opaque;
-   
+
     switch(cmd) {
     case CHR_IOCTL_SERIAL_SET_PARAMS:
         {
@@ -2506,7 +2497,7 @@ static int win_chr_init(CharDriverState *chr, const char *filename)
     COMSTAT comstat;
     DWORD size;
     DWORD err;
-   
+
     s->hsend = CreateEvent(NULL, TRUE, FALSE, NULL);
     if (!s->hsend) {
         fprintf(stderr, "Failed CreateEvent\n");
@@ -2525,12 +2516,12 @@ static int win_chr_init(CharDriverState *chr, const char *filename)
         s->hcom = NULL;
         goto fail;
     }
-   
+
     if (!SetupComm(s->hcom, NRECVBUF, NSENDBUF)) {
         fprintf(stderr, "Failed SetupComm\n");
         goto fail;
     }
-   
+
     ZeroMemory(&comcfg, sizeof(COMMCONFIG));
     size = sizeof(COMMCONFIG);
     GetDefaultCommConfig(filename, &comcfg, &size);
@@ -2552,7 +2543,7 @@ static int win_chr_init(CharDriverState *chr, const char *filename)
         fprintf(stderr, "Failed SetCommTimeouts\n");
         goto fail;
     }
-   
+
     if (!ClearCommError(s->hcom, &err, &comstat)) {
         fprintf(stderr, "Failed ClearCommError\n");
         goto fail;
@@ -2613,7 +2604,7 @@ static void win_chr_readfile(CharDriverState *chr)
     int ret, err;
     uint8_t buf[1024];
     DWORD size;
-   
+
     ZeroMemory(&s->orecv, sizeof(s->orecv));
     s->orecv.hEvent = s->hrecv;
     ret = ReadFile(s->hcom, buf, s->len, &size, &s->orecv);
@@ -2637,7 +2628,7 @@ static void win_chr_read(CharDriverState *chr)
         s->len = s->max_size;
     if (s->len == 0)
         return;
-   
+
     win_chr_readfile(chr);
 }
 
@@ -2647,7 +2638,7 @@ static int win_chr_poll(void *opaque)
     WinCharState *s = chr->opaque;
     COMSTAT status;
     DWORD comerr;
-   
+
     ClearCommError(s->hcom, &comerr, &status);
     if (status.cbInQue > 0) {
         s->len = status.cbInQue;
@@ -2662,7 +2653,7 @@ static CharDriverState *qemu_chr_open_win(const char *filename)
 {
     CharDriverState *chr;
     WinCharState *s;
-   
+
     chr = qemu_mallocz(sizeof(CharDriverState));
     if (!chr)
         return NULL;
@@ -2707,7 +2698,7 @@ static int win_chr_pipe_init(CharDriverState *chr, const char *filename)
     int ret;
     DWORD size;
     char openname[256];
-   
+
     s->fpipe = TRUE;
 
     s->hsend = CreateEvent(NULL, TRUE, FALSE, NULL);
@@ -2720,7 +2711,7 @@ static int win_chr_pipe_init(CharDriverState *chr, const char *filename)
         fprintf(stderr, "Failed CreateEvent\n");
         goto fail;
     }
-   
+
     snprintf(openname, sizeof(openname), "\\\\.\\pipe\\%s", filename);
     s->hcom = CreateNamedPipe(openname, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
                               PIPE_TYPE_BYTE | PIPE_READMODE_BYTE |
@@ -2779,7 +2770,7 @@ static CharDriverState *qemu_chr_open_win_pipe(const char *filename)
     chr->opaque = s;
     chr->chr_write = win_chr_write;
     chr->chr_close = win_chr_close;
-   
+
     if (win_chr_pipe_init(chr, filename) < 0) {
         free(s);
         free(chr);
@@ -2817,7 +2808,7 @@ static CharDriverState *qemu_chr_open_win_con(const char *filename)
 static CharDriverState *qemu_chr_open_win_file_out(const char *file_out)
 {
     HANDLE fd_out;
-   
+
     fd_out = CreateFile(file_out, GENERIC_WRITE, FILE_SHARE_READ, NULL,
                         OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
     if (fd_out == INVALID_HANDLE_VALUE)
@@ -3243,7 +3234,7 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str,
            val = 1;
            setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(val));
        }
-       
+
         ret = bind(fd, addr, addrlen);
         if (ret < 0)
             goto fail;
@@ -3283,7 +3274,7 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str,
         else
             qemu_set_fd_handler(s->fd, NULL, tcp_chr_connect, chr);
     }
-   
+
     if (is_listen && is_waitconnect) {
         printf("QEMU waiting for connection on: %s\n", host_str);
         tcp_chr_accept(chr);
@@ -3654,7 +3645,7 @@ static void net_slirp_redir(const char *redir_str)
     const char *p;
     struct in_addr guest_addr;
     int host_port, guest_port;
-   
+
     if (!slirp_inited) {
         slirp_inited = 1;
         slirp_init();
@@ -3684,11 +3675,11 @@ static void net_slirp_redir(const char *redir_str)
     }
     if (!inet_aton(buf, &guest_addr))
         goto fail;
-   
+
     guest_port = strtol(p, &r, 0);
     if (r == p)
         goto fail;
-   
+
     if (slirp_redir(is_udp, host_port, guest_addr, guest_port) < 0) {
         fprintf(stderr, "qemu: could not set up redirection\n");
         exit(1);
@@ -3698,7 +3689,7 @@ static void net_slirp_redir(const char *redir_str)
     fprintf(stderr, "qemu: syntax: -redir [tcp|udp]:host-port:[guest-host]:guest-port\n");
     exit(1);
 }
-   
+
 #ifndef _WIN32
 
 char smb_dir[1024];
@@ -3745,7 +3736,7 @@ void net_slirp_smb(const char *exported_dir)
         exit(1);
     }
     snprintf(smb_conf, sizeof(smb_conf), "%s/%s", smb_dir, "smb.conf");
-   
+
     f = fopen(smb_conf, "w");
     if (!f) {
         fprintf(stderr, "qemu: could not create samba server configuration file '%s'\n", smb_conf);
@@ -3777,11 +3768,15 @@ void net_slirp_smb(const char *exported_dir)
 
     snprintf(smb_cmdline, sizeof(smb_cmdline), "%s -s %s",
              SMBD_COMMAND, smb_conf);
-   
+
     slirp_add_exec(0, smb_cmdline, 4, 139);
 }
 
 #endif /* !defined(_WIN32) */
+void do_info_slirp(void)
+{
+    slirp_stats();
+}
 
 #endif /* CONFIG_SLIRP */
 
@@ -3790,6 +3785,7 @@ void net_slirp_smb(const char *exported_dir)
 typedef struct TAPState {
     VLANClientState *vc;
     int fd;
+    char down_script[1024];
 } TAPState;
 
 static void tap_receive(void *opaque, const uint8_t *buf, int size)
@@ -3866,7 +3862,7 @@ static int tap_open(char *ifname, int ifname_size)
 /*
  * 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;
@@ -4001,7 +3997,7 @@ static int tap_open(char *ifname, int ifname_size)
 {
     struct ifreq ifr;
     int fd, ret;
-   
+
     TFR(fd = open("/dev/net/tun", O_RDWR));
     if (fd < 0) {
         fprintf(stderr, "warning: could not open /dev/net/tun: no virtual network emulation\n");
@@ -4025,27 +4021,13 @@ static int tap_open(char *ifname, int ifname_size)
 }
 #endif
 
-static int net_tap_init(VLANState *vlan, const char *ifname1,
-                        const char *setup_script)
+static int launch_script(const char *setup_script, const char *ifname, int fd)
 {
-    TAPState *s;
-    int pid, status, fd;
+    int pid, status;
     char *args[3];
     char **parg;
-    char ifname[128];
-
-    if (ifname1 != NULL)
-        pstrcpy(ifname, sizeof(ifname), ifname1);
-    else
-        ifname[0] = '\0';
-    TFR(fd = tap_open(ifname, sizeof(ifname)));
-    if (fd < 0)
-        return -1;
 
-    if (!setup_script || !strcmp(setup_script, "no"))
-        setup_script = "";
-    if (setup_script[0] != '\0') {
-        /* try to launch network init script */
+        /* try to launch network script */
         pid = fork();
         if (pid >= 0) {
             if (pid == 0) {
@@ -4059,7 +4041,7 @@ static int net_tap_init(VLANState *vlan, const char *ifname1,
 
                 parg = args;
                 *parg++ = (char *)setup_script;
-                *parg++ = ifname;
+                *parg++ = (char *)ifname;
                 *parg++ = NULL;
                 execv(setup_script, args);
                 _exit(1);
@@ -4072,12 +4054,37 @@ static int net_tap_init(VLANState *vlan, const char *ifname1,
                 return -1;
             }
         }
+    return 0;
+}
+
+static int net_tap_init(VLANState *vlan, const char *ifname1,
+                        const char *setup_script, const char *down_script)
+{
+    TAPState *s;
+    int fd;
+    char ifname[128];
+
+    if (ifname1 != NULL)
+        pstrcpy(ifname, sizeof(ifname), ifname1);
+    else
+        ifname[0] = '\0';
+    TFR(fd = tap_open(ifname, sizeof(ifname)));
+    if (fd < 0)
+        return -1;
+
+    if (!setup_script || !strcmp(setup_script, "no"))
+        setup_script = "";
+    if (setup_script[0] != '\0') {
+       if (launch_script(setup_script, ifname, fd))
+           return -1;
     }
     s = net_tap_fd_init(vlan, fd);
     if (!s)
         return -1;
     snprintf(s->vc->info_str, sizeof(s->vc->info_str),
              "tap: ifname=%s setup_script=%s", ifname, setup_script);
+    if (down_script && strcmp(down_script, "no"))
+        snprintf(s->down_script, sizeof(s->down_script), "%s", down_script);
     return 0;
 }
 
@@ -4220,7 +4227,7 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr)
         perror("bind");
         goto fail;
     }
-   
+
     /* Add host to multicast group */
     imr.imr_multiaddr = mcastaddr->sin_addr;
     imr.imr_interface.s_addr = htonl(INADDR_ANY);
@@ -4356,7 +4363,7 @@ static NetSocketState *net_socket_fd_init(VLANState *vlan, int fd,
 
 static void net_socket_accept(void *opaque)
 {
-    NetSocketListenState *s = opaque;   
+    NetSocketListenState *s = opaque;
     NetSocketState *s1;
     struct sockaddr_in saddr;
     socklen_t len;
@@ -4389,7 +4396,7 @@ static int net_socket_listen_init(VLANState *vlan, const char *host_str)
 
     if (parse_host_port(&saddr, host_str) < 0)
         return -1;
-   
+
     s = qemu_mallocz(sizeof(NetSocketListenState));
     if (!s)
         return -1;
@@ -4404,7 +4411,7 @@ static int net_socket_listen_init(VLANState *vlan, const char *host_str)
     /* allow fast reuse */
     val = 1;
     setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(val));
-   
+
     ret = bind(fd, (struct sockaddr *)&saddr, sizeof(saddr));
     if (ret < 0) {
         perror("bind");
@@ -4487,7 +4494,7 @@ static int net_socket_mcast_init(VLANState *vlan, const char *host_str)
         return -1;
 
     s->dgram_dst = saddr;
-   
+
     snprintf(s->vc->info_str, sizeof(s->vc->info_str),
              "socket: mcast=%s:%d",
              inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
@@ -4621,7 +4628,7 @@ static int net_client_init(const char *str)
 #else
     if (!strcmp(device, "tap")) {
         char ifname[64];
-        char setup_script[1024];
+        char setup_script[1024], down_script[1024];
         int fd;
         vlan->nb_host_devs++;
         if (get_param_value(buf, sizeof(buf), "fd", p) > 0) {
@@ -4636,7 +4643,10 @@ static int net_client_init(const char *str)
             if (get_param_value(setup_script, sizeof(setup_script), "script", p) == 0) {
                 pstrcpy(setup_script, sizeof(setup_script), DEFAULT_NETWORK_SCRIPT);
             }
-            ret = net_tap_init(vlan, ifname, setup_script);
+            if (get_param_value(down_script, sizeof(down_script), "downscript", p) == 0) {
+                pstrcpy(down_script, sizeof(down_script), DEFAULT_NETWORK_DOWN_SCRIPT);
+            }
+            ret = net_tap_init(vlan, ifname, setup_script, down_script);
         }
     } else
 #endif
@@ -4666,7 +4676,7 @@ static int net_client_init(const char *str)
     if (ret < 0) {
         fprintf(stderr, "Could not initialize device '%s'\n", device);
     }
-   
+
     return ret;
 }
 
@@ -5024,7 +5034,7 @@ typedef struct WaitObjects {
 } WaitObjects;
 
 static WaitObjects wait_objects = {0};
-   
+
 int qemu_add_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque)
 {
     WaitObjects *w = &wait_objects;
@@ -5051,7 +5061,7 @@ void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque)
             w->events[i] = w->events[i + 1];
             w->func[i] = w->func[i + 1];
             w->opaque[i] = w->opaque[i + 1];
-        }           
+        }
     }
     if (found)
         w->num--;
@@ -5359,7 +5369,7 @@ int qemu_savevm_state(QEMUFile *f)
         /* record size: filled later */
         len_pos = qemu_ftell(f);
         qemu_put_be32(f, 0);
-       
+
         se->save_state(f, se->opaque);
 
         /* fill record size */
@@ -5397,7 +5407,7 @@ int qemu_loadvm_state(QEMUFile *f)
     int64_t total_len, end_pos, cur_pos;
     unsigned int v;
     char idstr[256];
-   
+
     v = qemu_get_be32(f);
     if (v != QEMU_VM_FILE_MAGIC)
         goto fail;
@@ -5481,7 +5491,7 @@ static int bdrv_snapshot_find(BlockDriverState *bs, QEMUSnapshotInfo *sn_info,
 {
     QEMUSnapshotInfo *sn_tab, *sn;
     int nb_sns, i, ret;
-   
+
     ret = -ENOENT;
     nb_sns = bdrv_snapshot_list(bs, &sn_tab);
     if (nb_sns < 0)
@@ -5523,7 +5533,7 @@ void do_savevm(const char *name)
 
     saved_vm_running = vm_running;
     vm_stop(0);
-   
+
     must_delete = 0;
     if (name) {
         ret = bdrv_snapshot_find(bs, old_sn, name);
@@ -5551,13 +5561,13 @@ void do_savevm(const char *name)
     sn->date_nsec = tv.tv_usec * 1000;
 #endif
     sn->vm_clock_nsec = qemu_get_clock(vm_clock);
-   
+
     if (bdrv_get_info(bs, bdi) < 0 || bdi->vm_state_offset <= 0) {
         term_printf("Device %s does not support VM state snapshots\n",
                     bdrv_get_device_name(bs));
         goto the_end;
     }
-   
+
     /* save the VM state */
     f = qemu_fopen_bdrv(bs, bdi->vm_state_offset, 1);
     if (!f) {
@@ -5571,7 +5581,7 @@ void do_savevm(const char *name)
         term_printf("Error %d while writing VM\n", ret);
         goto the_end;
     }
-   
+
     /* create the snapshots */
 
     for(i = 0; i < MAX_DISKS; i++) {
@@ -5610,7 +5620,7 @@ void do_loadvm(const char *name)
         term_printf("No block device supports snapshots\n");
         return;
     }
-   
+
     /* Flush all IO requests so they don't interfere with the new state.  */
     qemu_aio_flush();
 
@@ -5650,7 +5660,7 @@ void do_loadvm(const char *name)
                     bdrv_get_device_name(bs));
         return;
     }
-   
+
     /* restore the VM state */
     f = qemu_fopen_bdrv(bs, bdi->vm_state_offset, 0);
     if (!f) {
@@ -5677,7 +5687,7 @@ void do_delvm(const char *name)
         term_printf("No block device supports snapshots\n");
         return;
     }
-   
+
     for(i = 0; i <= MAX_DISKS; i++) {
         bs1 = bs_table[i];
         if (bdrv_has_snapshot(bs1)) {
@@ -5757,14 +5767,14 @@ void cpu_save(QEMUFile *f, void *opaque)
     uint16_t fptag, fpus, fpuc, fpregs_format;
     uint32_t hflags;
     int i;
-   
+
     for(i = 0; i < CPU_NB_REGS; i++)
         qemu_put_betls(f, &env->regs[i]);
     qemu_put_betls(f, &env->eip);
     qemu_put_betls(f, &env->eflags);
     hflags = env->hflags; /* XXX: suppress most of the redundant hflags */
     qemu_put_be32s(f, &hflags);
-   
+
     /* FPU */
     fpuc = env->fpuc;
     fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
@@ -5772,7 +5782,7 @@ void cpu_save(QEMUFile *f, void *opaque)
     for(i = 0; i < 8; i++) {
         fptag |= ((!env->fptags[i]) << i);
     }
-   
+
     qemu_put_be16s(f, &fpuc);
     qemu_put_be16s(f, &fpus);
     qemu_put_be16s(f, &fptag);
@@ -5783,7 +5793,7 @@ void cpu_save(QEMUFile *f, void *opaque)
     fpregs_format = 1;
 #endif
     qemu_put_be16s(f, &fpregs_format);
-   
+
     for(i = 0; i < 8; i++) {
 #ifdef USE_X86LDOUBLE
         {
@@ -5810,16 +5820,16 @@ void cpu_save(QEMUFile *f, void *opaque)
     cpu_put_seg(f, &env->tr);
     cpu_put_seg(f, &env->gdt);
     cpu_put_seg(f, &env->idt);
-   
+
     qemu_put_be32s(f, &env->sysenter_cs);
     qemu_put_be32s(f, &env->sysenter_esp);
     qemu_put_be32s(f, &env->sysenter_eip);
-   
+
     qemu_put_betls(f, &env->cr[0]);
     qemu_put_betls(f, &env->cr[2]);
     qemu_put_betls(f, &env->cr[3]);
     qemu_put_betls(f, &env->cr[4]);
-   
+
     for(i = 0; i < 8; i++)
         qemu_put_betls(f, &env->dr[i]);
 
@@ -5887,7 +5897,7 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
     qemu_get_be16s(f, &fpus);
     qemu_get_be16s(f, &fptag);
     qemu_get_be16s(f, &fpregs_format);
-   
+
     /* NOTE: we cannot always restore the FPU state if the image come
        from a host with a different 'USE_X86LDOUBLE' define. We guess
        if we are in an MMX state to restore correctly in that case. */
@@ -5895,7 +5905,7 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
     for(i = 0; i < 8; i++) {
         uint64_t mant;
         uint16_t exp;
-       
+
         switch(fpregs_format) {
         case 0:
             mant = qemu_get_be64(f);
@@ -5926,7 +5936,7 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
             }
 #else
             env->fpregs[i].mmx.MMX_Q(0) = mant;
-#endif           
+#endif
             break;
         default:
             return -EINVAL;
@@ -5941,23 +5951,23 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
     for(i = 0; i < 8; i++) {
         env->fptags[i] = (fptag >> i) & 1;
     }
-   
+
     for(i = 0; i < 6; i++)
         cpu_get_seg(f, &env->segs[i]);
     cpu_get_seg(f, &env->ldt);
     cpu_get_seg(f, &env->tr);
     cpu_get_seg(f, &env->gdt);
     cpu_get_seg(f, &env->idt);
-   
+
     qemu_get_be32s(f, &env->sysenter_cs);
     qemu_get_be32s(f, &env->sysenter_esp);
     qemu_get_be32s(f, &env->sysenter_eip);
-   
+
     qemu_get_betls(f, &env->cr[0]);
     qemu_get_betls(f, &env->cr[2]);
     qemu_get_betls(f, &env->cr[3]);
     qemu_get_betls(f, &env->cr[4]);
-   
+
     for(i = 0; i < 8; i++)
         qemu_get_betls(f, &env->dr[i]);
 
@@ -6110,7 +6120,9 @@ void cpu_save(QEMUFile *f, void *opaque)
     qemu_put_be32(f, env->cp15.c1_sys);
     qemu_put_be32(f, env->cp15.c1_coproc);
     qemu_put_be32(f, env->cp15.c1_xscaleauxcr);
-    qemu_put_be32(f, env->cp15.c2_base);
+    qemu_put_be32(f, env->cp15.c2_base0);
+    qemu_put_be32(f, env->cp15.c2_base1);
+    qemu_put_be32(f, env->cp15.c2_mask);
     qemu_put_be32(f, env->cp15.c2_data);
     qemu_put_be32(f, env->cp15.c2_insn);
     qemu_put_be32(f, env->cp15.c3);
@@ -6125,6 +6137,9 @@ void cpu_save(QEMUFile *f, void *opaque)
     qemu_put_be32(f, env->cp15.c9_data);
     qemu_put_be32(f, env->cp15.c13_fcse);
     qemu_put_be32(f, env->cp15.c13_context);
+    qemu_put_be32(f, env->cp15.c13_tls1);
+    qemu_put_be32(f, env->cp15.c13_tls2);
+    qemu_put_be32(f, env->cp15.c13_tls3);
     qemu_put_be32(f, env->cp15.c15_cpar);
 
     qemu_put_be32(f, env->features);
@@ -6143,6 +6158,15 @@ void cpu_save(QEMUFile *f, void *opaque)
         /* TODO: Should use proper FPSCR access functions.  */
         qemu_put_be32(f, env->vfp.vec_len);
         qemu_put_be32(f, env->vfp.vec_stride);
+
+        if (arm_feature(env, ARM_FEATURE_VFP3)) {
+            for (i = 16;  i < 32; i++) {
+                CPU_DoubleU u;
+                u.d = env->vfp.regs[i];
+                qemu_put_be32(f, u.l.upper);
+                qemu_put_be32(f, u.l.lower);
+            }
+        }
     }
 
     if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
@@ -6153,6 +6177,15 @@ void cpu_save(QEMUFile *f, void *opaque)
             qemu_put_be32(f, env->iwmmxt.cregs[i]);
         }
     }
+
+    if (arm_feature(env, ARM_FEATURE_M)) {
+        qemu_put_be32(f, env->v7m.other_sp);
+        qemu_put_be32(f, env->v7m.vecbase);
+        qemu_put_be32(f, env->v7m.basepri);
+        qemu_put_be32(f, env->v7m.control);
+        qemu_put_be32(f, env->v7m.current_sp);
+        qemu_put_be32(f, env->v7m.exception);
+    }
 }
 
 int cpu_load(QEMUFile *f, void *opaque, int version_id)
@@ -6160,7 +6193,7 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
     CPUARMState *env = (CPUARMState *)opaque;
     int i;
 
-    if (version_id != 0)
+    if (version_id != ARM_CPU_SAVE_VERSION)
         return -EINVAL;
 
     for (i = 0; i < 16; i++) {
@@ -6182,7 +6215,9 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
     env->cp15.c1_sys = qemu_get_be32(f);
     env->cp15.c1_coproc = qemu_get_be32(f);
     env->cp15.c1_xscaleauxcr = qemu_get_be32(f);
-    env->cp15.c2_base = qemu_get_be32(f);
+    env->cp15.c2_base0 = qemu_get_be32(f);
+    env->cp15.c2_base1 = qemu_get_be32(f);
+    env->cp15.c2_mask = qemu_get_be32(f);
     env->cp15.c2_data = qemu_get_be32(f);
     env->cp15.c2_insn = qemu_get_be32(f);
     env->cp15.c3 = qemu_get_be32(f);
@@ -6197,6 +6232,9 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
     env->cp15.c9_data = qemu_get_be32(f);
     env->cp15.c13_fcse = qemu_get_be32(f);
     env->cp15.c13_context = qemu_get_be32(f);
+    env->cp15.c13_tls1 = qemu_get_be32(f);
+    env->cp15.c13_tls2 = qemu_get_be32(f);
+    env->cp15.c13_tls3 = qemu_get_be32(f);
     env->cp15.c15_cpar = qemu_get_be32(f);
 
     env->features = qemu_get_be32(f);
@@ -6215,6 +6253,15 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
         /* TODO: Should use proper FPSCR access functions.  */
         env->vfp.vec_len = qemu_get_be32(f);
         env->vfp.vec_stride = qemu_get_be32(f);
+
+        if (arm_feature(env, ARM_FEATURE_VFP3)) {
+            for (i = 0;  i < 16; i++) {
+                CPU_DoubleU u;
+                u.l.upper = qemu_get_be32(f);
+                u.l.lower = qemu_get_be32(f);
+                env->vfp.regs[i] = u.d;
+            }
+        }
     }
 
     if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
@@ -6226,6 +6273,15 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
         }
     }
 
+    if (arm_feature(env, ARM_FEATURE_M)) {
+        env->v7m.other_sp = qemu_get_be32(f);
+        env->v7m.vecbase = qemu_get_be32(f);
+        env->v7m.basepri = qemu_get_be32(f);
+        env->v7m.control = qemu_get_be32(f);
+        env->v7m.current_sp = qemu_get_be32(f);
+        env->v7m.exception = qemu_get_be32(f);
+    }
+
     return 0;
 }
 
@@ -6399,7 +6455,7 @@ static void ram_save(QEMUFile *f, void *opaque)
     int i;
     RamCompressState s1, *s = &s1;
     uint8_t buf[10];
-   
+
     qemu_put_be32(f, phys_ram_size);
     if (ram_compress_open(s, f) < 0)
         return;
@@ -6766,15 +6822,15 @@ void main_loop_wait(int timeout)
     if (ret == 0) {
         int err;
         WaitObjects *w = &wait_objects;
-       
+
         ret = WaitForMultipleObjects(w->num, w->events, FALSE, timeout);
         if (WAIT_OBJECT_0 + 0 <= ret && ret <= WAIT_OBJECT_0 + w->num - 1) {
             if (w->func[ret - WAIT_OBJECT_0])
                 w->func[ret - WAIT_OBJECT_0](w->opaque[ret - WAIT_OBJECT_0]);
-               
+
             /* Check for additional signaled events */
             for(i = (ret - WAIT_OBJECT_0 + 1); i < w->num; i++) {
-                               
+
                 /* Check if event is signaled */
                 ret2 = WaitForSingleObject(w->events[i], 0);
                 if(ret2 == WAIT_OBJECT_0) {
@@ -6784,8 +6840,8 @@ void main_loop_wait(int timeout)
                 } else {
                     err = GetLastError();
                     fprintf(stderr, "WaitForSingleObject error %d %d\n", i, err);
-                }               
-            }                
+                }
+            }
         } else if (ret == WAIT_TIMEOUT) {
         } else {
             err = GetLastError();
@@ -6815,7 +6871,7 @@ void main_loop_wait(int timeout)
                 nfds = ioh->fd;
         }
     }
-   
+
     tv.tv_sec = 0;
 #ifdef _WIN32
     tv.tv_usec = 0;
@@ -6877,7 +6933,7 @@ void main_loop_wait(int timeout)
     /* Check bottom-halves last in case any of the earlier events triggered
        them.  */
     qemu_bh_poll();
-   
+
 }
 
 static CPUState *cur_cpu;
@@ -7023,10 +7079,11 @@ static void help(int exitcode)
            "-net tap[,vlan=n],ifname=name\n"
            "                connect the host TAP network interface to VLAN 'n'\n"
 #else
-           "-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"
+           "-net tap[,vlan=n][,fd=h][,ifname=name][,script=file][,downscript=dfile]\n"
+           "                connect the host TAP network interface to VLAN 'n' and use the\n"
+           "                network scripts 'file' (default=%s)\n"
+           "                and 'dfile' (default=%s);\n"
+           "                use '[down]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"
@@ -7067,9 +7124,6 @@ static void help(int exitcode)
            "-kernel-kqemu   enable KQEMU full virtualization (default is user mode only)\n"
            "-no-kqemu       disable KQEMU kernel module usage\n"
 #endif
-#ifdef USE_CODE_COPY
-           "-no-code-copy   disable code copy acceleration\n"
-#endif
 #ifdef TARGET_I386
            "-std-vga        simulate a standard VGA card with VESA Bochs Extensions\n"
            "                (default is CL-GD5446 PCI VGA)\n"
@@ -7099,6 +7153,7 @@ static void help(int exitcode)
            DEFAULT_RAM_SIZE,
 #ifndef _WIN32
            DEFAULT_NETWORK_SCRIPT,
+           DEFAULT_NETWORK_DOWN_SCRIPT,
 #endif
            DEFAULT_GDBSTUB_PORT,
            "/tmp/qemu.log");
@@ -7151,6 +7206,7 @@ enum {
     QEMU_OPTION_d,
     QEMU_OPTION_hdachs,
     QEMU_OPTION_L,
+    QEMU_OPTION_bios,
     QEMU_OPTION_no_code_copy,
     QEMU_OPTION_k,
     QEMU_OPTION_localtime,
@@ -7185,6 +7241,7 @@ enum {
     QEMU_OPTION_prom_env,
     QEMU_OPTION_old_param,
     QEMU_OPTION_clock,
+    QEMU_OPTION_startdate,
 };
 
 typedef struct QEMUOption {
@@ -7243,6 +7300,7 @@ const QEMUOption qemu_options[] = {
     { "d", HAS_ARG, QEMU_OPTION_d },
     { "hdachs", HAS_ARG, QEMU_OPTION_hdachs },
     { "L", HAS_ARG, QEMU_OPTION_L },
+    { "bios", HAS_ARG, QEMU_OPTION_bios },
     { "no-code-copy", 0, QEMU_OPTION_no_code_copy },
 #ifdef USE_KQEMU
     { "no-kqemu", 0, QEMU_OPTION_no_kqemu },
@@ -7290,18 +7348,10 @@ const QEMUOption qemu_options[] = {
     { "old-param", 0, QEMU_OPTION_old_param },
 #endif
     { "clock", HAS_ARG, QEMU_OPTION_clock },
+    { "startdate", HAS_ARG, QEMU_OPTION_startdate },
     { NULL },
 };
 
-#if defined (TARGET_I386) && defined(USE_CODE_COPY)
-
-/* this stack is only used during signal handling */
-#define SIGNAL_STACK_SIZE 32768
-
-static uint8_t *signal_stack;
-
-#endif
-
 /* password input */
 
 int qemu_key_check(BlockDriverState *bs, const char *name)
@@ -7364,12 +7414,14 @@ void register_machines(void)
     qemu_register_machine(&mips_machine);
     qemu_register_machine(&mips_malta_machine);
     qemu_register_machine(&mips_pica61_machine);
+    qemu_register_machine(&mips_mipssim_machine);
 #elif defined(TARGET_SPARC)
 #ifdef TARGET_SPARC64
     qemu_register_machine(&sun4u_machine);
 #else
     qemu_register_machine(&ss5_machine);
     qemu_register_machine(&ss10_machine);
+    qemu_register_machine(&ss600mp_machine);
 #endif
 #elif defined(TARGET_ARM)
     qemu_register_machine(&integratorcp_machine);
@@ -7381,13 +7433,19 @@ void register_machines(void)
     qemu_register_machine(&borzoipda_machine);
     qemu_register_machine(&terrierpda_machine);
     qemu_register_machine(&palmte_machine);
+    qemu_register_machine(&lm3s811evb_machine);
+    qemu_register_machine(&lm3s6965evb_machine);
 #elif defined(TARGET_SH4)
     qemu_register_machine(&shix_machine);
+    qemu_register_machine(&r2d_machine);
 #elif defined(TARGET_ALPHA)
     /* XXX: TODO */
 #elif defined(TARGET_M68K)
     qemu_register_machine(&mcf5208evb_machine);
     qemu_register_machine(&an5206_machine);
+    qemu_register_machine(&dummy_m68k_machine);
+#elif defined(TARGET_CRIS)
+    qemu_register_machine(&bareetraxfs_machine);
 #else
 #error unsupported CPU
 #endif
@@ -7524,14 +7582,16 @@ int main(int argc, char **argv)
     int use_gdbstub;
     const char *gdbstub_port;
 #endif
+    uint32_t boot_devices_bitmap = 0;
     int i, cdrom_index, pflash_index;
-    int snapshot, linux_boot;
+    int snapshot, linux_boot, net_boot;
     const char *initrd_filename;
     const char *hd_filename[MAX_DISKS], *fd_filename[MAX_FD];
     const char *pflash_filename[MAX_PFLASH];
     const char *sd_filename;
     const char *mtd_filename;
     const char *kernel_filename, *kernel_cmdline;
+    const char *boot_devices = "";
     DisplayState *ds = &display_state;
     int cyls, heads, secs, translation;
     char net_clients[MAX_NET_CLIENTS][256];
@@ -7620,19 +7680,19 @@ int main(int argc, char **argv)
     for(i = 1; i < MAX_SERIAL_PORTS; i++)
         serial_devices[i][0] = '\0';
     serial_device_index = 0;
-   
+
     pstrcpy(parallel_devices[0], sizeof(parallel_devices[0]), "vc");
     for(i = 1; i < MAX_PARALLEL_PORTS; i++)
         parallel_devices[i][0] = '\0';
     parallel_device_index = 0;
-   
+
     usb_devices_index = 0;
-   
+
     nb_net_clients = 0;
 
     nb_nics = 0;
     /* default mac address of the first network interface */
-   
+
     optind = 1;
     for(;;) {
         if (optind >= argc)
@@ -7686,14 +7746,9 @@ int main(int argc, char **argv)
             case QEMU_OPTION_cpu:
                 /* hw initialization will check this */
                 if (*optarg == '?') {
-#if defined(TARGET_PPC)
-                    ppc_cpu_list(stdout, &fprintf);
-#elif defined(TARGET_ARM)
-                    arm_cpu_list();
-#elif defined(TARGET_MIPS)
-                    mips_cpu_list(stdout, &fprintf);
-#elif defined(TARGET_SPARC)
-                    sparc_cpu_list(stdout, &fprintf);
+/* XXX: implement xxx_cpu_list for targets that still miss it */
+#if defined(cpu_list)
+                    cpu_list(stdout, &fprintf);
 #endif
                     exit(0);
                 } else {
@@ -7788,15 +7843,34 @@ int main(int argc, char **argv)
                 }
                 break;
             case QEMU_OPTION_boot:
-                boot_device = optarg[0];
-                if (boot_device != 'a' &&
-#if defined(TARGET_SPARC) || defined(TARGET_I386)
-                   // Network boot
-                   boot_device != 'n' &&
-#endif
-                    boot_device != 'c' && boot_device != 'd') {
-                    fprintf(stderr, "qemu: invalid boot device '%c'\n", boot_device);
-                    exit(1);
+                boot_devices = optarg;
+                /* We just do some generic consistency checks */
+                {
+                    /* Could easily be extended to 64 devices if needed */
+                    const unsigned char *p;
+                    
+                    boot_devices_bitmap = 0;
+                    for (p = boot_devices; *p != '\0'; p++) {
+                        /* Allowed boot devices are:
+                         * a b     : floppy disk drives
+                         * c ... f : IDE disk drives
+                         * g ... m : machine implementation dependant drives
+                         * n ... p : network devices
+                         * It's up to each machine implementation to check
+                         * if the given boot devices match the actual hardware
+                         * implementation and firmware features.
+                         */
+                        if (*p < 'a' || *p > 'q') {
+                            fprintf(stderr, "Invalid boot device '%c'\n", *p);
+                            exit(1);
+                        }
+                        if (boot_devices_bitmap & (1 << (*p - 'a'))) {
+                            fprintf(stderr,
+                                    "Boot device '%c' was given twice\n",*p);
+                            exit(1);
+                        }
+                        boot_devices_bitmap |= 1 << (*p - 'a');
+                    }
                 }
                 break;
             case QEMU_OPTION_fda:
@@ -7836,7 +7910,7 @@ int main(int argc, char **argv)
                 break;
 #endif
             case QEMU_OPTION_redir:
-                net_slirp_redir(optarg);               
+                net_slirp_redir(optarg);
                 break;
 #endif
 #ifdef HAS_AUDIO
@@ -7865,7 +7939,7 @@ int main(int argc, char **argv)
                 {
                     int mask;
                     CPULogItem *item;
-                   
+
                     mask = cpu_str_to_log_mask(optarg);
                     if (!mask) {
                         printf("Log items (comma separated):\n");
@@ -7888,6 +7962,9 @@ int main(int argc, char **argv)
             case QEMU_OPTION_L:
                 bios_dir = optarg;
                 break;
+            case QEMU_OPTION_bios:
+                bios_name = optarg;
+                break;
             case QEMU_OPTION_S:
                 autostart = 0;
                 break;
@@ -7937,7 +8014,7 @@ int main(int argc, char **argv)
                     } else {
                         goto graphic_error;
                     }
-                   
+
                     graphic_width = w;
                     graphic_height = h;
                     graphic_depth = depth;
@@ -8072,6 +8149,42 @@ int main(int argc, char **argv)
             case QEMU_OPTION_clock:
                 configure_alarms(optarg);
                 break;
+            case QEMU_OPTION_startdate:
+                {
+                    struct tm tm;
+                    if (!strcmp(optarg, "now")) {
+                        rtc_start_date = -1;
+                    } else {
+                        if (sscanf(optarg, "%d-%d-%dT%d:%d:%d",
+                               &tm.tm_year,
+                               &tm.tm_mon,
+                               &tm.tm_mday,
+                               &tm.tm_hour,
+                               &tm.tm_min,
+                               &tm.tm_sec) == 6) {
+                            /* OK */
+                        } else if (sscanf(optarg, "%d-%d-%d",
+                                          &tm.tm_year,
+                                          &tm.tm_mon,
+                                          &tm.tm_mday) == 3) {
+                            tm.tm_hour = 0;
+                            tm.tm_min = 0;
+                            tm.tm_sec = 0;
+                        } else {
+                            goto date_fail;
+                        }
+                        tm.tm_year -= 1900;
+                        tm.tm_mon--;
+                        rtc_start_date = mktimegm(&tm);
+                        if (rtc_start_date == -1) {
+                        date_fail:
+                            fprintf(stderr, "Invalid date format. Valid format are:\n"
+                                    "'now' or '2006-06-17T16:01:21' or '2006-06-17'\n");
+                            exit(1);
+                        }
+                    }
+                }
+                break;
             }
         }
     }
@@ -8141,24 +8254,26 @@ int main(int argc, char **argv)
         kqemu_allowed = 0;
 #endif
     linux_boot = (kernel_filename != NULL);
-
-    if (!linux_boot &&
-        boot_device != 'n' &&
+    net_boot = (boot_devices_bitmap >> ('n' - 'a')) && 0xF;
+    
+    /* XXX: this should not be: some embedded targets just have flash */
+    if (!linux_boot && net_boot == 0 &&
         hd_filename[0] == '\0' &&
         (cdrom_index >= 0 && hd_filename[cdrom_index] == '\0') &&
         fd_filename[0] == '\0')
         help(1);
 
     /* 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';
+    if (!boot_devices[0]) {
+        if (hd_filename[0] != '\0')
+            boot_devices = "c";
+        else if (fd_filename[0] != '\0')
+            boot_devices = "a";
         else
-            boot_device = 'd';
+            boot_devices = "d";
     }
-
     setvbuf(stdout, NULL, _IOLBF, 0);
-   
+
     init_timers();
     init_timer_alarm();
     qemu_aio_init();
@@ -8195,20 +8310,28 @@ int main(int argc, char **argv)
     }
 
 #ifdef TARGET_I386
-    if (boot_device == 'n') {
-       for (i = 0; i < nb_nics; i++) {
+    /* XXX: this should be moved in the PC machine instanciation code */
+    if (net_boot != 0) {
+        int netroms = 0;
+       for (i = 0; i < nb_nics && i < 4; 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 (net_boot & (1 << i)) {
+                if (model == NULL)
+                    model = "ne2k_pci";
+                snprintf(buf, sizeof(buf), "%s/pxe-%s.bin", bios_dir, model);
+                if (get_image_size(buf) > 0) {
+                    if (nb_option_roms >= MAX_OPTION_ROMS) {
+                        fprintf(stderr, "Too many option ROMs\n");
+                        exit(1);
+                    }
+                    option_rom[nb_option_roms] = strdup(buf);
+                    nb_option_roms++;
+                    netroms++;
+                }
+            }
        }
-       if (i == nb_nics) {
+       if (netroms == 0) {
            fprintf(stderr, "No valid PXE rom found for network device\n");
            exit(1);
        }
@@ -8388,7 +8511,7 @@ int main(int argc, char **argv)
         }
     }
 
-    machine->init(ram_size, vga_ram_size, boot_device,
+    machine->init(ram_size, vga_ram_size, boot_devices,
                   ds, fd_filename, snapshot,
                   kernel_filename, kernel_cmdline, initrd_filename, cpu_model);
 
@@ -8456,5 +8579,23 @@ int main(int argc, char **argv)
 
     main_loop();
     quit_timers();
+
+#if !defined(_WIN32)
+    /* close network clients */
+    for(vlan = first_vlan; vlan != NULL; vlan = vlan->next) {
+        VLANClientState *vc;
+
+        for(vc = vlan->first_client; vc != NULL; vc = vc->next) {
+            if (vc->fd_read == tap_receive) {
+                char ifname[64];
+                TAPState *s = vc->opaque;
+
+                if (sscanf(vc->info_str, "tap: ifname=%63s ", ifname) == 1 &&
+                    s->down_script[0])
+                    launch_script(s->down_script, ifname, s->fd);
+            }
+    }
+    }
+#endif
     return 0;
 }
This page took 0.06821 seconds and 4 git commands to generate.