]> git.proxmox.com Git - qemu.git/blobdiff - vl.c
monitor fixes
[qemu.git] / vl.c
diff --git a/vl.c b/vl.c
index 646d1ff94753aac251b25686f766028c2f251857..4569cda204c1ebccb2e2492042fd8775919379c9 100644 (file)
--- a/vl.c
+++ b/vl.c
@@ -38,6 +38,8 @@
 #include <sys/mman.h>
 #include <sys/ioctl.h>
 #include <sys/socket.h>
+#include <netinet/in.h>
+#include <dirent.h>
 #ifdef _BSD
 #include <sys/stat.h>
 #ifndef __APPLE__
@@ -127,7 +129,9 @@ int cirrus_vga_enabled = 1;
 int graphic_width = 800;
 int graphic_height = 600;
 int graphic_depth = 15;
+int full_screen = 0;
 TextConsole *vga_console;
+CharDriverState *serial_hds[MAX_SERIAL_PORTS];
 
 /***********************************************************/
 /* x86 ISA bus support */
@@ -402,9 +406,9 @@ void hw_error(const char *fmt, ...)
     vfprintf(stderr, fmt, ap);
     fprintf(stderr, "\n");
 #ifdef TARGET_I386
-    cpu_x86_dump_state(global_env, stderr, X86_DUMP_FPU | X86_DUMP_CCOP);
+    cpu_dump_state(global_env, stderr, fprintf, X86_DUMP_FPU | X86_DUMP_CCOP);
 #else
-    cpu_dump_state(global_env, stderr, 0);
+    cpu_dump_state(global_env, stderr, fprintf, 0);
 #endif
     va_end(ap);
     abort();
@@ -707,7 +711,7 @@ static void qemu_run_timers(QEMUTimer **ptimer_head, int64_t current_time)
     
     for(;;) {
         ts = *ptimer_head;
-        if (ts->expire_time > current_time)
+        if (!ts || ts->expire_time > current_time)
             break;
         /* remove timer from the list before calling the callback */
         *ptimer_head = ts->next;
@@ -1027,10 +1031,30 @@ typedef struct {
 static int stdio_nb_clients;
 static CharDriverState *stdio_clients[STDIO_MAX_CLIENTS];
 
+static int unix_write(int fd, const uint8_t *buf, int len1)
+{
+    int ret, len;
+
+    len = len1;
+    while (len > 0) {
+        ret = write(fd, buf, len);
+        if (ret < 0) {
+            if (errno != EINTR && errno != EAGAIN)
+                return -1;
+        } else if (ret == 0) {
+            break;
+        } else {
+            buf += ret;
+            len -= ret;
+        }
+    }
+    return len1 - len;
+}
+
 static int fd_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
 {
     FDCharDriver *s = chr->opaque;
-    return write(s->fd_out, buf, len);
+    return unix_write(s->fd_out, buf, len);
 }
 
 static void fd_chr_add_read_handler(CharDriverState *chr, 
@@ -1166,6 +1190,43 @@ static void stdio_read(void *opaque, const uint8_t *buf, int size)
         stdio_received_byte(buf[i]);
 }
 
+/* init terminal so that we can grab keys */
+static struct termios oldtty;
+static int old_fd0_flags;
+
+static void term_exit(void)
+{
+    tcsetattr (0, TCSANOW, &oldtty);
+    fcntl(0, F_SETFL, old_fd0_flags);
+}
+
+static void term_init(void)
+{
+    struct termios tty;
+
+    tcgetattr (0, &tty);
+    oldtty = tty;
+    old_fd0_flags = fcntl(0, F_GETFL);
+
+    tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
+                          |INLCR|IGNCR|ICRNL|IXON);
+    tty.c_oflag |= OPOST;
+    tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN);
+    /* if graphical mode, we allow Ctrl-C handling */
+    if (nographic)
+        tty.c_lflag &= ~ISIG;
+    tty.c_cflag &= ~(CSIZE|PARENB);
+    tty.c_cflag |= CS8;
+    tty.c_cc[VMIN] = 1;
+    tty.c_cc[VTIME] = 0;
+    
+    tcsetattr (0, TCSANOW, &tty);
+
+    atexit(term_exit);
+
+    fcntl(0, F_SETFL, O_NONBLOCK);
+}
+
 CharDriverState *qemu_chr_open_stdio(void)
 {
     CharDriverState *chr;
@@ -1183,6 +1244,10 @@ CharDriverState *qemu_chr_open_stdio(void)
         chr = qemu_chr_open_fd(0, 1);
     }
     stdio_clients[stdio_nb_clients++] = chr;
+    if (stdio_nb_clients == 1) {
+        /* set the terminal in raw mode */
+        term_init();
+    }
     return chr;
 }
 
@@ -1340,6 +1405,158 @@ static int net_slirp_init(NetDriverState *nd)
     return 0;
 }
 
+static int get_str_sep(char *buf, int buf_size, const char **pp, int sep)
+{
+    const char *p, *p1;
+    int len;
+    p = *pp;
+    p1 = strchr(p, sep);
+    if (!p1)
+        return -1;
+    len = p1 - p;
+    p1++;
+    if (buf_size > 0) {
+        if (len > buf_size - 1)
+            len = buf_size - 1;
+        memcpy(buf, p, len);
+        buf[len] = '\0';
+    }
+    *pp = p1;
+    return 0;
+}
+
+static void net_slirp_redir(const char *redir_str)
+{
+    int is_udp;
+    char buf[256], *r;
+    const char *p;
+    struct in_addr guest_addr;
+    int host_port, guest_port;
+    
+    if (!slirp_inited) {
+        slirp_inited = 1;
+        slirp_init();
+    }
+
+    p = redir_str;
+    if (get_str_sep(buf, sizeof(buf), &p, ':') < 0)
+        goto fail;
+    if (!strcmp(buf, "tcp")) {
+        is_udp = 0;
+    } else if (!strcmp(buf, "udp")) {
+        is_udp = 1;
+    } else {
+        goto fail;
+    }
+
+    if (get_str_sep(buf, sizeof(buf), &p, ':') < 0)
+        goto fail;
+    host_port = strtol(buf, &r, 0);
+    if (r == buf)
+        goto fail;
+
+    if (get_str_sep(buf, sizeof(buf), &p, ':') < 0)
+        goto fail;
+    if (buf[0] == '\0') {
+        pstrcpy(buf, sizeof(buf), "10.0.2.15");
+    }
+    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);
+    }
+    return;
+ fail:
+    fprintf(stderr, "qemu: syntax: -redir [tcp|udp]:host-port:[guest-host]:guest-port\n");
+    exit(1);
+}
+    
+#ifndef _WIN32
+
+char smb_dir[1024];
+
+static void smb_exit(void)
+{
+    DIR *d;
+    struct dirent *de;
+    char filename[1024];
+
+    /* erase all the files in the directory */
+    d = opendir(smb_dir);
+    for(;;) {
+        de = readdir(d);
+        if (!de)
+            break;
+        if (strcmp(de->d_name, ".") != 0 &&
+            strcmp(de->d_name, "..") != 0) {
+            snprintf(filename, sizeof(filename), "%s/%s", 
+                     smb_dir, de->d_name);
+            unlink(filename);
+        }
+    }
+    closedir(d);
+    rmdir(smb_dir);
+}
+
+/* automatic user mode samba server configuration */
+void net_slirp_smb(const char *exported_dir)
+{
+    char smb_conf[1024];
+    char smb_cmdline[1024];
+    FILE *f;
+
+    if (!slirp_inited) {
+        slirp_inited = 1;
+        slirp_init();
+    }
+
+    /* XXX: better tmp dir construction */
+    snprintf(smb_dir, sizeof(smb_dir), "/tmp/qemu-smb.%d", getpid());
+    if (mkdir(smb_dir, 0700) < 0) {
+        fprintf(stderr, "qemu: could not create samba server dir '%s'\n", smb_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);
+        exit(1);
+    }
+    fprintf(f, 
+            "[global]\n"
+            "pid directory=%s\n"
+            "lock directory=%s\n"
+            "log file=%s/log.smbd\n"
+            "smb passwd file=%s/smbpasswd\n"
+            "security = share\n"
+            "[qemu]\n"
+            "path=%s\n"
+            "read only=no\n"
+            "guest ok=yes\n",
+            smb_dir,
+            smb_dir,
+            smb_dir,
+            smb_dir,
+            exported_dir
+            );
+    fclose(f);
+    atexit(smb_exit);
+
+    snprintf(smb_cmdline, sizeof(smb_cmdline), "/usr/sbin/smbd -s %s",
+             smb_conf);
+    
+    slirp_add_exec(0, smb_cmdline, 4, 139);
+}
+
+#endif /* !defined(_WIN32) */
+
 #endif /* CONFIG_SLIRP */
 
 #if !defined(_WIN32)
@@ -1449,57 +1666,6 @@ static int net_fd_init(NetDriverState *nd, int fd)
 /***********************************************************/
 /* dumb display */
 
-#ifdef _WIN32
-
-static void term_exit(void)
-{
-}
-
-static void term_init(void)
-{
-}
-
-#else
-
-/* init terminal so that we can grab keys */
-static struct termios oldtty;
-static int old_fd0_flags;
-
-static void term_exit(void)
-{
-    tcsetattr (0, TCSANOW, &oldtty);
-    fcntl(0, F_SETFL, old_fd0_flags);
-}
-
-static void term_init(void)
-{
-    struct termios tty;
-
-    tcgetattr (0, &tty);
-    oldtty = tty;
-    old_fd0_flags = fcntl(0, F_GETFL);
-
-    tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
-                          |INLCR|IGNCR|ICRNL|IXON);
-    tty.c_oflag |= OPOST;
-    tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN);
-    /* if graphical mode, we allow Ctrl-C handling */
-    if (nographic)
-        tty.c_lflag &= ~ISIG;
-    tty.c_cflag &= ~(CSIZE|PARENB);
-    tty.c_cflag |= CS8;
-    tty.c_cc[VMIN] = 1;
-    tty.c_cc[VTIME] = 0;
-    
-    tcsetattr (0, TCSANOW, &tty);
-
-    atexit(term_exit);
-
-    fcntl(0, F_SETFL, O_NONBLOCK);
-}
-
-#endif
-
 static void dumb_update(DisplayState *ds, int x, int y, int w, int h)
 {
 }
@@ -1531,7 +1697,8 @@ static void host_segv_handler(int host_signum, siginfo_t *info,
 {
     if (cpu_signal_handler(host_signum, info, puc))
         return;
-    term_exit();
+    if (stdio_nb_clients > 0)
+        term_exit();
     abort();
 }
 #endif
@@ -1996,6 +2163,15 @@ void cpu_save(QEMUFile *f, void *opaque)
 {
 }
 
+int cpu_load(QEMUFile *f, void *opaque, int version_id)
+{
+    return 0;
+}
+#elif defined(TARGET_SPARC)
+void cpu_save(QEMUFile *f, void *opaque)
+{
+}
+
 int cpu_load(QEMUFile *f, void *opaque, int version_id)
 {
     return 0;
@@ -2330,6 +2506,7 @@ void help(void)
            "-nographic      disable graphical output and redirect serial I/Os to console\n"
            "-enable-audio   enable audio support\n"
            "-localtime      set the real time clock to local time [default=utc]\n"
+           "-full-screen    start in full screen\n"
 #ifdef TARGET_PPC
            "-prep           Simulate a PREP system (default is PowerMAC)\n"
            "-g WxH[xDEPTH]  Set the initial VGA graphic mode\n"
@@ -2342,6 +2519,12 @@ void help(void)
            "-tun-fd fd      use this fd as already opened tap/tun interface\n"
 #ifdef CONFIG_SLIRP
            "-user-net       use user mode network stack [default if no tap/tun script]\n"
+           "-tftp prefix    allow tftp access to files starting with prefix [-user-net]\n"
+#ifndef _WIN32
+           "-smb dir        allow SMB access to files in 'dir' [-user-net]\n"
+#endif
+           "-redir [tcp|udp]:host-port:[guest-host]:guest-port\n"
+           "                redirect TCP or UDP connections from host to guest [-user-net]\n"
 #endif
            "-dummy-net      use dummy network stack\n"
            "\n"
@@ -2367,6 +2550,7 @@ void help(void)
            "-std-vga        simulate a standard VGA card with VESA Bochs Extensions\n"
            "                (default is CL-GD5446 PCI VGA)\n"
 #endif
+           "-loadvm file    start right away with a saved state (loadvm in monitor)\n"
            "\n"
            "During emulation, the following keys are useful:\n"
            "ctrl-shift-f    toggle full screen\n"
@@ -2416,6 +2600,9 @@ enum {
     QEMU_OPTION_n,
     QEMU_OPTION_tun_fd,
     QEMU_OPTION_user_net,
+    QEMU_OPTION_tftp,
+    QEMU_OPTION_smb,
+    QEMU_OPTION_redir,
     QEMU_OPTION_dummy_net,
 
     QEMU_OPTION_kernel,
@@ -2438,6 +2625,8 @@ enum {
     QEMU_OPTION_std_vga,
     QEMU_OPTION_monitor,
     QEMU_OPTION_serial,
+    QEMU_OPTION_loadvm,
+    QEMU_OPTION_full_screen,
 };
 
 typedef struct QEMUOption {
@@ -2468,6 +2657,11 @@ const QEMUOption qemu_options[] = {
     { "tun-fd", HAS_ARG, QEMU_OPTION_tun_fd },
 #ifdef CONFIG_SLIRP
     { "user-net", 0, QEMU_OPTION_user_net },
+    { "tftp", HAS_ARG, QEMU_OPTION_tftp },
+#ifndef _WIN32
+    { "smb", HAS_ARG, QEMU_OPTION_smb },
+#endif
+    { "redir", HAS_ARG, QEMU_OPTION_redir },
 #endif
     { "dummy-net", 0, QEMU_OPTION_dummy_net },
 
@@ -2491,6 +2685,8 @@ const QEMUOption qemu_options[] = {
     { "std-vga", 0, QEMU_OPTION_std_vga },
     { "monitor", 1, QEMU_OPTION_monitor },
     { "serial", 1, QEMU_OPTION_serial },
+    { "loadvm", HAS_ARG, QEMU_OPTION_loadvm },
+    { "full-screen", 0, QEMU_OPTION_full_screen },
     
     /* temporary options */
     { "pci", 0, QEMU_OPTION_pci },
@@ -2568,8 +2764,10 @@ int main(int argc, char **argv)
     const char *r, *optarg;
     CharDriverState *monitor_hd;
     char monitor_device[128];
-    char serial_device[128];
-
+    char serial_devices[MAX_SERIAL_PORTS][128];
+    int serial_device_index;
+    const char *loadvm = NULL;
+    
 #if !defined(CONFIG_SOFTMMU)
     /* we never want that malloc() uses mmap() */
     mallopt(M_MMAP_THRESHOLD, 4096 * 1024);
@@ -2594,8 +2792,12 @@ int main(int argc, char **argv)
     has_cdrom = 1;
     cyls = heads = secs = 0;
     pstrcpy(monitor_device, sizeof(monitor_device), "vc");
-    pstrcpy(serial_device, sizeof(serial_device), "vc");
 
+    pstrcpy(serial_devices[0], sizeof(serial_devices[0]), "vc");
+    for(i = 1; i < MAX_SERIAL_PORTS; i++)
+        serial_devices[i][0] = '\0';
+    serial_device_index = 0;
+    
     nb_tun_fds = 0;
     net_if_type = -1;
     nb_nics = 1;
@@ -2674,7 +2876,7 @@ int main(int argc, char **argv)
                 break;
             case QEMU_OPTION_nographic:
                 pstrcpy(monitor_device, sizeof(monitor_device), "stdio");
-                pstrcpy(serial_device, sizeof(serial_device), "stdio");
+                pstrcpy(serial_devices[0], sizeof(serial_devices[0]), "stdio");
                 nographic = 1;
                 break;
             case QEMU_OPTION_kernel:
@@ -2754,9 +2956,22 @@ int main(int argc, char **argv)
                     }
                 }
                 break;
+#ifdef CONFIG_SLIRP
+            case QEMU_OPTION_tftp:
+               tftp_prefix = optarg;
+                break;
+#ifndef _WIN32
+            case QEMU_OPTION_smb:
+               net_slirp_smb(optarg);
+                break;
+#endif
             case QEMU_OPTION_user_net:
                 net_if_type = NET_IF_USER;
                 break;
+            case QEMU_OPTION_redir:
+                net_slirp_redir(optarg);                
+                break;
+#endif
             case QEMU_OPTION_dummy_net:
                 net_if_type = NET_IF_DUMMY;
                 break;
@@ -2865,7 +3080,19 @@ int main(int argc, char **argv)
                 pstrcpy(monitor_device, sizeof(monitor_device), optarg);
                 break;
             case QEMU_OPTION_serial:
-                pstrcpy(serial_device, sizeof(serial_device), optarg);
+                if (serial_device_index >= MAX_SERIAL_PORTS) {
+                    fprintf(stderr, "qemu: too many serial ports\n");
+                    exit(1);
+                }
+                pstrcpy(serial_devices[serial_device_index], 
+                        sizeof(serial_devices[0]), optarg);
+                serial_device_index++;
+                break;
+           case QEMU_OPTION_loadvm:
+               loadvm = optarg;
+               break;
+            case QEMU_OPTION_full_screen:
+                full_screen = 1;
                 break;
             }
         }
@@ -3051,7 +3278,7 @@ int main(int argc, char **argv)
         dumb_display_init(ds);
     } else {
 #ifdef CONFIG_SDL
-        sdl_display_init(ds);
+        sdl_display_init(ds, full_screen);
 #else
         dumb_display_init(ds);
 #endif
@@ -3066,14 +3293,18 @@ int main(int argc, char **argv)
     }
     monitor_init(monitor_hd, !nographic);
 
-    serial_hd = qemu_chr_open(serial_device);
-    if (!serial_hd) {
-        fprintf(stderr, "qemu: could not open serial device '%s'\n", serial_device);
-        exit(1);
+    for(i = 0; i < MAX_SERIAL_PORTS; i++) {
+        if (serial_devices[i][0] != '\0') {
+            serial_hds[i] = qemu_chr_open(serial_devices[i]);
+            if (!serial_hds[i]) {
+                fprintf(stderr, "qemu: could not open serial device '%s'\n", 
+                        serial_devices[i]);
+                exit(1);
+            }
+            if (!strcmp(serial_devices[i], "vc"))
+                qemu_chr_printf(serial_hds[i], "serial%d console\n", i);
+        }
     }
-    if (!strcmp(serial_device, "vc"))
-        qemu_chr_printf(serial_hd, "serial0 console\n");
-    
 
     /* setup cpu signal handlers for MMU / self modifying code handling */
 #if !defined(CONFIG_SOFTMMU)
@@ -3128,6 +3359,10 @@ int main(int argc, char **argv)
     ppc_init(ram_size, vga_ram_size, boot_device,
             ds, fd_filename, snapshot,
             kernel_filename, kernel_cmdline, initrd_filename);
+#elif defined(TARGET_SPARC)
+    sun4m_init(ram_size, vga_ram_size, boot_device,
+            ds, fd_filename, snapshot,
+            kernel_filename, kernel_cmdline, initrd_filename);
 #endif
 
     gui_timer = qemu_new_timer(rt_clock, gui_update, NULL);
@@ -3142,11 +3377,12 @@ int main(int argc, char **argv)
         } else {
             printf("Waiting gdb connection on port %d\n", gdbstub_port);
         }
-        term_init();
     } else 
 #endif
+    if (loadvm)
+        qemu_loadvm(loadvm);
+
     {
-        term_init();
         /* XXX: simplify init */
         read_passwords();
         if (start_emulation) {