#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__
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 */
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();
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;
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,
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;
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;
}
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)
/***********************************************************/
/* 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)
{
}
{
if (cpu_signal_handler(host_signum, info, puc))
return;
- term_exit();
+ if (stdio_nb_clients > 0)
+ term_exit();
abort();
}
#endif
{
}
+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;
"-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"
"-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"
"-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"
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,
QEMU_OPTION_std_vga,
QEMU_OPTION_monitor,
QEMU_OPTION_serial,
+ QEMU_OPTION_loadvm,
+ QEMU_OPTION_full_screen,
};
typedef struct QEMUOption {
{ "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 },
{ "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 },
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);
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;
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:
}
}
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;
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;
}
}
dumb_display_init(ds);
} else {
#ifdef CONFIG_SDL
- sdl_display_init(ds);
+ sdl_display_init(ds, full_screen);
#else
dumb_display_init(ds);
#endif
}
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)
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);
} 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) {