#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
#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];
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
#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)
#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)
uint32_t high, low;
#else
uint32_t low, high;
-#endif
+#endif
} l;
} u, res;
uint64_t rl, rh;
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;
}
}
pt = &t->next;
}
-
- qemu_rearm_alarm_timer(alarm_timer);
}
/* modify the current timer so that it will be fired when 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)
/* 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);
}
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])
/* 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);
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);
/* 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);
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;
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);
FDCharDriver *s = chr->opaque;
int size, len;
uint8_t buf[1024];
-
+
len = sizeof(buf);
if (len > s->max_size)
len = s->max_size;
tty.c_cflag |= CS8;
tty.c_cc[VMIN] = 1;
tty.c_cc[VTIME] = 0;
-
+
tcsetattr (0, TCSANOW, &tty);
atexit(term_exit);
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);
}
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:
{
COMSTAT comstat;
DWORD size;
DWORD err;
-
+
s->hsend = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!s->hsend) {
fprintf(stderr, "Failed CreateEvent\n");
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);
fprintf(stderr, "Failed SetCommTimeouts\n");
goto fail;
}
-
+
if (!ClearCommError(s->hcom, &err, &comstat)) {
fprintf(stderr, "Failed ClearCommError\n");
goto fail;
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);
s->len = s->max_size;
if (s->len == 0)
return;
-
+
win_chr_readfile(chr);
}
WinCharState *s = chr->opaque;
COMSTAT status;
DWORD comerr;
-
+
ClearCommError(s->hcom, &comerr, &status);
if (status.cbInQue > 0) {
s->len = status.cbInQue;
{
CharDriverState *chr;
WinCharState *s;
-
+
chr = qemu_mallocz(sizeof(CharDriverState));
if (!chr)
return NULL;
int ret;
DWORD size;
char openname[256];
-
+
s->fpipe = TRUE;
s->hsend = CreateEvent(NULL, TRUE, FALSE, NULL);
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 |
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);
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)
val = 1;
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(val));
}
-
+
ret = bind(fd, addr, addrlen);
if (ret < 0)
goto fail;
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);
const char *p;
struct in_addr guest_addr;
int host_port, guest_port;
-
+
if (!slirp_inited) {
slirp_inited = 1;
slirp_init();
}
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);
fprintf(stderr, "qemu: syntax: -redir [tcp|udp]:host-port:[guest-host]:guest-port\n");
exit(1);
}
-
+
#ifndef _WIN32
char smb_dir[1024];
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);
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 */
typedef struct TAPState {
VLANClientState *vc;
int fd;
+ char down_script[1024];
} TAPState;
static void tap_receive(void *opaque, const uint8_t *buf, int 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;
{
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");
}
#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) {
parg = args;
*parg++ = (char *)setup_script;
- *parg++ = ifname;
+ *parg++ = (char *)ifname;
*parg++ = NULL;
execv(setup_script, args);
_exit(1);
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;
}
perror("bind");
goto fail;
}
-
+
/* Add host to multicast group */
imr.imr_multiaddr = mcastaddr->sin_addr;
imr.imr_interface.s_addr = htonl(INADDR_ANY);
static void net_socket_accept(void *opaque)
{
- NetSocketListenState *s = opaque;
+ NetSocketListenState *s = opaque;
NetSocketState *s1;
struct sockaddr_in saddr;
socklen_t len;
if (parse_host_port(&saddr, host_str) < 0)
return -1;
-
+
s = qemu_mallocz(sizeof(NetSocketListenState));
if (!s)
return -1;
/* 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");
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));
#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) {
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
if (ret < 0) {
fprintf(stderr, "Could not initialize device '%s'\n", device);
}
-
+
return ret;
}
} WaitObjects;
static WaitObjects wait_objects = {0};
-
+
int qemu_add_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque)
{
WaitObjects *w = &wait_objects;
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--;
/* record size: filled later */
len_pos = qemu_ftell(f);
qemu_put_be32(f, 0);
-
+
se->save_state(f, se->opaque);
/* fill record size */
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;
{
QEMUSnapshotInfo *sn_tab, *sn;
int nb_sns, i, ret;
-
+
ret = -ENOENT;
nb_sns = bdrv_snapshot_list(bs, &sn_tab);
if (nb_sns < 0)
saved_vm_running = vm_running;
vm_stop(0);
-
+
must_delete = 0;
if (name) {
ret = bdrv_snapshot_find(bs, old_sn, 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) {
term_printf("Error %d while writing VM\n", ret);
goto the_end;
}
-
+
/* create the snapshots */
for(i = 0; i < MAX_DISKS; i++) {
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();
bdrv_get_device_name(bs));
return;
}
-
+
/* restore the VM state */
f = qemu_fopen_bdrv(bs, bdi->vm_state_offset, 0);
if (!f) {
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)) {
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;
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);
fpregs_format = 1;
#endif
qemu_put_be16s(f, &fpregs_format);
-
+
for(i = 0; i < 8; i++) {
#ifdef USE_X86LDOUBLE
{
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]);
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. */
for(i = 0; i < 8; i++) {
uint64_t mant;
uint16_t exp;
-
+
switch(fpregs_format) {
case 0:
mant = qemu_get_be64(f);
}
#else
env->fpregs[i].mmx.MMX_Q(0) = mant;
-#endif
+#endif
break;
default:
return -EINVAL;
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]);
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);
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);
/* 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)) {
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)
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++) {
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);
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);
/* 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)) {
}
}
+ 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;
}
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;
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) {
} else {
err = GetLastError();
fprintf(stderr, "WaitForSingleObject error %d %d\n", i, err);
- }
- }
+ }
+ }
} else if (ret == WAIT_TIMEOUT) {
} else {
err = GetLastError();
nfds = ioh->fd;
}
}
-
+
tv.tv_sec = 0;
#ifdef _WIN32
tv.tv_usec = 0;
/* Check bottom-halves last in case any of the earlier events triggered
them. */
qemu_bh_poll();
-
+
}
static CPUState *cur_cpu;
"-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"
"-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"
DEFAULT_RAM_SIZE,
#ifndef _WIN32
DEFAULT_NETWORK_SCRIPT,
+ DEFAULT_NETWORK_DOWN_SCRIPT,
#endif
DEFAULT_GDBSTUB_PORT,
"/tmp/qemu.log");
QEMU_OPTION_d,
QEMU_OPTION_hdachs,
QEMU_OPTION_L,
+ QEMU_OPTION_bios,
QEMU_OPTION_no_code_copy,
QEMU_OPTION_k,
QEMU_OPTION_localtime,
QEMU_OPTION_prom_env,
QEMU_OPTION_old_param,
QEMU_OPTION_clock,
+ QEMU_OPTION_startdate,
};
typedef struct QEMUOption {
{ "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 },
{ "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)
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);
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
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];
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)
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 {
}
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:
break;
#endif
case QEMU_OPTION_redir:
- net_slirp_redir(optarg);
+ net_slirp_redir(optarg);
break;
#endif
#ifdef HAS_AUDIO
{
int mask;
CPULogItem *item;
-
+
mask = cpu_str_to_log_mask(optarg);
if (!mask) {
printf("Log items (comma separated):\n");
case QEMU_OPTION_L:
bios_dir = optarg;
break;
+ case QEMU_OPTION_bios:
+ bios_name = optarg;
+ break;
case QEMU_OPTION_S:
autostart = 0;
break;
} else {
goto graphic_error;
}
-
+
graphic_width = w;
graphic_height = h;
graphic_depth = depth;
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;
}
}
}
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();
}
#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);
}
}
}
- 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);
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;
}