X-Git-Url: https://vcs.maemo.org/git/?a=blobdiff_plain;f=vl.c;h=46ce9008d8bd840c6e26ccdf06a27e25ed079cc7;hb=30032c940a625f0aa8f04becf78e47274ec3a319;hp=cbf63167b25de916e2ff869397e54675f1617a34;hpb=1196be3713ebd728359ada9ebf292f0059694a73;p=qemu diff --git a/vl.c b/vl.c index cbf6316..46ce900 100644 --- a/vl.c +++ b/vl.c @@ -1,8 +1,8 @@ /* * QEMU System Emulator - * + * * Copyright (c) 2003-2007 Fabrice Bellard - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights @@ -42,11 +42,15 @@ #include #include #include +#include +#include #ifdef _BSD #include #ifndef __APPLE__ #include #endif +#elif defined (__GLIBC__) && defined (__FreeBSD_kernel__) +#include #else #ifndef __sun__ #include @@ -54,13 +58,18 @@ #include #include #include + +/* For the benefit of older linux systems which don't supply it, + we use a local copy of hpet.h. */ +/* #include */ +#include "hpet.h" + #include #include #else #include #include #include -#include #include #include #include @@ -73,6 +82,9 @@ #include #endif #endif +#else +#include +int inet_aton(const char *cp, struct in_addr *ia); #endif #if defined(CONFIG_SLIRP) @@ -138,6 +150,9 @@ IOPortWriteFunc *ioport_write_table[3][MAX_IOPORTS]; /* Note: bs_table[MAX_DISKS] is a dummy block driver if none available to store the VM snapshots */ BlockDriverState *bs_table[MAX_DISKS + 1], *fd_table[MAX_FD]; +BlockDriverState *pflash_table[MAX_PFLASH]; +BlockDriverState *sd_bdrv; +BlockDriverState *mtd_bdrv; /* point to the block driver where the snapshots are managed */ BlockDriverState *bs_snapshots; int vga_ram_size; @@ -150,18 +165,19 @@ int ram_size; int pit_min_timer_count = 0; int nb_nics; NICInfo nd_table[MAX_NICS]; -QEMUTimer *gui_timer; int vm_running; int rtc_utc = 1; int cirrus_vga_enabled = 1; +int vmsvga_enabled = 0; #ifdef TARGET_SPARC int graphic_width = 1024; int graphic_height = 768; +int graphic_depth = 8; #else int graphic_width = 800; int graphic_height = 600; -#endif int graphic_depth = 15; +#endif int full_screen = 0; int no_frame = 0; int no_quit = 0; @@ -184,11 +200,24 @@ const char *vnc_display; int acpi_enabled = 1; int fd_bootchk = 1; int no_reboot = 0; +int cursor_hide = 1; +int graphic_rotate = 0; int daemonize = 0; const char *option_rom[MAX_OPTION_ROMS]; int nb_option_roms; int semihosting_enabled = 0; int autostart = 1; +#ifdef TARGET_ARM +int old_param = 0; +#endif +const char *qemu_name; +int alt_grab = 0; +#ifdef TARGET_SPARC +unsigned int nb_prom_envs = 0; +const char *prom_envs[MAX_PROM_ENVS]; +#endif + +#define TFR(expr) do { if ((expr) != -1) break; } while (errno == EINTR) /***********************************************************/ /* x86 ISA bus support */ @@ -258,7 +287,7 @@ void init_ioports(void) } /* size is the word size in byte */ -int register_ioport_read(int start, int length, int size, +int register_ioport_read(int start, int length, int size, IOPortReadFunc *func, void *opaque) { int i, bsize; @@ -283,7 +312,7 @@ int register_ioport_read(int start, int length, int size, } /* size is the word size in byte */ -int register_ioport_write(int start, int length, int size, +int register_ioport_write(int start, int length, int size, IOPortWriteFunc *func, void *opaque) { int i, bsize; @@ -329,7 +358,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) @@ -342,7 +371,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) @@ -519,6 +548,7 @@ void kbd_mouse_event(int dx, int dy, int dz, int buttons_state) { QEMUPutMouseEvent *mouse_event; void *mouse_event_opaque; + int width; if (!qemu_put_mouse_event_current) { return; @@ -530,7 +560,16 @@ void kbd_mouse_event(int dx, int dy, int dz, int buttons_state) qemu_put_mouse_event_current->qemu_put_mouse_event_opaque; if (mouse_event) { - mouse_event(mouse_event_opaque, dx, dy, dz, buttons_state); + if (graphic_rotate) { + if (qemu_put_mouse_event_current->qemu_put_mouse_event_absolute) + width = 0x7fff; + else + width = graphic_width; + mouse_event(mouse_event_opaque, + width - dy, dx, dz, buttons_state); + } else + mouse_event(mouse_event_opaque, + dx, dy, dz, buttons_state); } } @@ -595,7 +634,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; @@ -661,7 +700,7 @@ static int64_t get_clock(void) struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); return ts.tv_sec * 1000000000LL + ts.tv_nsec; - } else + } else #endif { /* XXX: using gettimeofday leads to problems if the date @@ -735,7 +774,7 @@ void cpu_disable_ticks(void) /***********************************************************/ /* timers */ - + #define QEMU_TIMER_REALTIME 0 #define QEMU_TIMER_VIRTUAL 1 @@ -752,18 +791,158 @@ struct QEMUTimer { struct QEMUTimer *next; }; -QEMUClock *rt_clock; -QEMUClock *vm_clock; +struct qemu_alarm_timer { + char const *name; + unsigned int flags; + + int (*start)(struct qemu_alarm_timer *t); + void (*stop)(struct qemu_alarm_timer *t); + void (*rearm)(struct qemu_alarm_timer *t); + void *priv; +}; + +#define ALARM_FLAG_DYNTICKS 0x1 + +static inline int alarm_has_dynticks(struct qemu_alarm_timer *t) +{ + return t->flags & ALARM_FLAG_DYNTICKS; +} + +static void qemu_rearm_alarm_timer(struct qemu_alarm_timer *t) +{ + if (!alarm_has_dynticks(t)) + return; + + t->rearm(t); +} + +/* TODO: MIN_TIMER_REARM_US should be optimized */ +#define MIN_TIMER_REARM_US 250 + +static struct qemu_alarm_timer *alarm_timer; -static QEMUTimer *active_timers[2]; #ifdef _WIN32 -static MMRESULT timerID; -static HANDLE host_alarm = NULL; -static unsigned int period = 1; + +struct qemu_alarm_win32 { + MMRESULT timerId; + HANDLE host_alarm; + unsigned int period; +} alarm_win32_data = {0, NULL, -1}; + +static int win32_start_timer(struct qemu_alarm_timer *t); +static void win32_stop_timer(struct qemu_alarm_timer *t); +static void win32_rearm_timer(struct qemu_alarm_timer *t); + #else -/* frequency of the times() clock tick */ -static int timer_freq; + +static int unix_start_timer(struct qemu_alarm_timer *t); +static void unix_stop_timer(struct qemu_alarm_timer *t); + +#ifdef __linux__ + +static int dynticks_start_timer(struct qemu_alarm_timer *t); +static void dynticks_stop_timer(struct qemu_alarm_timer *t); +static void dynticks_rearm_timer(struct qemu_alarm_timer *t); + +static int hpet_start_timer(struct qemu_alarm_timer *t); +static void hpet_stop_timer(struct qemu_alarm_timer *t); + +static int rtc_start_timer(struct qemu_alarm_timer *t); +static void rtc_stop_timer(struct qemu_alarm_timer *t); + +#endif /* __linux__ */ + +#endif /* _WIN32 */ + +static struct qemu_alarm_timer alarm_timers[] = { +#ifndef _WIN32 +#ifdef __linux__ + {"dynticks", ALARM_FLAG_DYNTICKS, dynticks_start_timer, + dynticks_stop_timer, dynticks_rearm_timer, NULL}, + /* HPET - if available - is preferred */ + {"hpet", 0, hpet_start_timer, hpet_stop_timer, NULL, NULL}, + /* ...otherwise try RTC */ + {"rtc", 0, rtc_start_timer, rtc_stop_timer, NULL, NULL}, +#endif + {"unix", 0, unix_start_timer, unix_stop_timer, NULL, NULL}, +#else + {"dynticks", ALARM_FLAG_DYNTICKS, win32_start_timer, + win32_stop_timer, win32_rearm_timer, &alarm_win32_data}, + {"win32", 0, win32_start_timer, + win32_stop_timer, NULL, &alarm_win32_data}, #endif + {NULL, } +}; + +static void show_available_alarms() +{ + int i; + + printf("Available alarm timers, in order of precedence:\n"); + for (i = 0; alarm_timers[i].name; i++) + printf("%s\n", alarm_timers[i].name); +} + +static void configure_alarms(char const *opt) +{ + int i; + int cur = 0; + int count = (sizeof(alarm_timers) / sizeof(*alarm_timers)) - 1; + char *arg; + char *name; + + if (!strcmp(opt, "help")) { + show_available_alarms(); + exit(0); + } + + arg = strdup(opt); + + /* Reorder the array */ + name = strtok(arg, ","); + while (name) { + struct qemu_alarm_timer tmp; + + for (i = 0; i < count && alarm_timers[i].name; i++) { + if (!strcmp(alarm_timers[i].name, name)) + break; + } + + if (i == count) { + fprintf(stderr, "Unknown clock %s\n", name); + goto next; + } + + if (i < cur) + /* Ignore */ + goto next; + + /* Swap */ + tmp = alarm_timers[i]; + alarm_timers[i] = alarm_timers[cur]; + alarm_timers[cur] = tmp; + + cur++; +next: + name = strtok(NULL, ","); + } + + free(arg); + + if (cur) { + /* Disable remaining timers */ + for (i = cur; i < count; i++) + alarm_timers[i].name = NULL; + } + + /* debug */ + show_available_alarms(); +} + +QEMUClock *rt_clock; +QEMUClock *vm_clock; + +static QEMUTimer *active_timers[2]; QEMUClock *qemu_new_clock(int type) { @@ -809,6 +988,8 @@ 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 @@ -827,7 +1008,7 @@ void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time) t = *pt; if (!t) break; - if (t->expire_time > expire_time) + if (t->expire_time > expire_time) break; pt = &t->next; } @@ -856,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) @@ -864,10 +1045,11 @@ 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); } + qemu_rearm_alarm_timer(alarm_timer); } int64_t qemu_get_clock(QEMUClock *clock) @@ -940,7 +1122,7 @@ static int timer_load(QEMUFile *f, void *opaque, int version_id) } #ifdef _WIN32 -void CALLBACK host_alarm_handler(UINT uTimerID, UINT uMsg, +void CALLBACK host_alarm_handler(UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2) #else static void host_alarm_handler(int host_signum) @@ -975,12 +1157,14 @@ static void host_alarm_handler(int host_signum) last_clock = ti; } #endif - if (qemu_timer_expired(active_timers[QEMU_TIMER_VIRTUAL], + if (alarm_has_dynticks(alarm_timer) || + qemu_timer_expired(active_timers[QEMU_TIMER_VIRTUAL], qemu_get_clock(vm_clock)) || qemu_timer_expired(active_timers[QEMU_TIMER_REALTIME], qemu_get_clock(rt_clock))) { #ifdef _WIN32 - SetEvent(host_alarm); + struct qemu_alarm_win32 *data = ((struct qemu_alarm_timer*)dwUser)->priv; + SetEvent(data->host_alarm); #endif CPUState *env = cpu_single_env; if (env) { @@ -995,17 +1179,107 @@ static void host_alarm_handler(int host_signum) } } +static uint64_t qemu_next_deadline(void) +{ + int64_t nearest_delta_us = UINT64_MAX; + int64_t vmdelta_us; + + if (active_timers[QEMU_TIMER_REALTIME]) + nearest_delta_us = (active_timers[QEMU_TIMER_REALTIME]->expire_time - + qemu_get_clock(rt_clock))*1000; + + if (active_timers[QEMU_TIMER_VIRTUAL]) { + /* round up */ + vmdelta_us = (active_timers[QEMU_TIMER_VIRTUAL]->expire_time - + qemu_get_clock(vm_clock)+999)/1000; + if (vmdelta_us < nearest_delta_us) + nearest_delta_us = vmdelta_us; + } + + /* Avoid arming the timer to negative, zero, or too low values */ + if (nearest_delta_us <= MIN_TIMER_REARM_US) + nearest_delta_us = MIN_TIMER_REARM_US; + + return nearest_delta_us; +} + #ifndef _WIN32 #if defined(__linux__) #define RTC_FREQ 1024 -static int rtc_fd; +static void enable_sigio_timer(int fd) +{ + struct sigaction act; + + /* 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); + fcntl(fd, F_SETFL, O_ASYNC); + fcntl(fd, F_SETOWN, getpid()); +} + +static int hpet_start_timer(struct qemu_alarm_timer *t) +{ + struct hpet_info info; + int r, fd; + + fd = open("/dev/hpet", O_RDONLY); + if (fd < 0) + return -1; + + /* Set frequency */ + r = ioctl(fd, HPET_IRQFREQ, RTC_FREQ); + if (r < 0) { + fprintf(stderr, "Could not configure '/dev/hpet' to have a 1024Hz timer. This is not a fatal\n" + "error, but for better emulation accuracy type:\n" + "'echo 1024 > /proc/sys/dev/hpet/max-user-freq' as root.\n"); + goto fail; + } + + /* Check capabilities */ + r = ioctl(fd, HPET_INFO, &info); + if (r < 0) + goto fail; + + /* Enable periodic mode */ + r = ioctl(fd, HPET_EPI, 0); + if (info.hi_flags && (r < 0)) + goto fail; + + /* Enable interrupt */ + r = ioctl(fd, HPET_IE_ON, 0); + if (r < 0) + goto fail; + + enable_sigio_timer(fd); + t->priv = (void *)(long)fd; + + return 0; +fail: + close(fd); + return -1; +} + +static void hpet_stop_timer(struct qemu_alarm_timer *t) +{ + int fd = (long)t->priv; + + close(fd); +} -static int start_rtc_timer(void) +static int rtc_start_timer(struct qemu_alarm_timer *t) { - rtc_fd = open("/dev/rtc", O_RDONLY); + int rtc_fd; + + TFR(rtc_fd = open("/dev/rtc", O_RDONLY)); if (rtc_fd < 0) return -1; if (ioctl(rtc_fd, RTC_IRQP_SET, RTC_FREQ) < 0) { @@ -1019,117 +1293,250 @@ static int start_rtc_timer(void) close(rtc_fd); return -1; } - pit_min_timer_count = PIT_FREQ / RTC_FREQ; + + enable_sigio_timer(rtc_fd); + + t->priv = (void *)(long)rtc_fd; + return 0; } -#else +static void rtc_stop_timer(struct qemu_alarm_timer *t) +{ + int rtc_fd = (long)t->priv; + + close(rtc_fd); +} -static int start_rtc_timer(void) +static int dynticks_start_timer(struct qemu_alarm_timer *t) { - return -1; + struct sigevent ev; + timer_t host_timer; + struct sigaction act; + + 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); + + ev.sigev_value.sival_int = 0; + ev.sigev_notify = SIGEV_SIGNAL; + ev.sigev_signo = SIGALRM; + + if (timer_create(CLOCK_REALTIME, &ev, &host_timer)) { + perror("timer_create"); + + /* disable dynticks */ + fprintf(stderr, "Dynamic Ticks disabled\n"); + + return -1; + } + + t->priv = (void *)host_timer; + + return 0; } -#endif /* !defined(__linux__) */ +static void dynticks_stop_timer(struct qemu_alarm_timer *t) +{ + timer_t host_timer = (timer_t)t->priv; -#endif /* !defined(_WIN32) */ + timer_delete(host_timer); +} -static void init_timer_alarm(void) +static void dynticks_rearm_timer(struct qemu_alarm_timer *t) { -#ifdef _WIN32 - { - int count=0; - TIMECAPS tc; - - ZeroMemory(&tc, sizeof(TIMECAPS)); - timeGetDevCaps(&tc, sizeof(TIMECAPS)); - if (period < tc.wPeriodMin) - period = tc.wPeriodMin; - timeBeginPeriod(period); - timerID = timeSetEvent(1, // interval (ms) - period, // resolution - host_alarm_handler, // function - (DWORD)&count, // user parameter - TIME_PERIODIC | TIME_CALLBACK_FUNCTION); - if( !timerID ) { - perror("failed timer alarm"); - exit(1); - } - host_alarm = CreateEvent(NULL, FALSE, FALSE, NULL); - if (!host_alarm) { - perror("failed CreateEvent"); - exit(1); - } - qemu_add_wait_object(host_alarm, NULL, NULL); + timer_t host_timer = (timer_t)t->priv; + struct itimerspec timeout; + int64_t nearest_delta_us = INT64_MAX; + int64_t current_us; + + if (!active_timers[QEMU_TIMER_REALTIME] && + !active_timers[QEMU_TIMER_VIRTUAL]) + return; + + nearest_delta_us = qemu_next_deadline(); + + /* check whether a timer is already running */ + if (timer_gettime(host_timer, &timeout)) { + perror("gettime"); + fprintf(stderr, "Internal timer error: aborting\n"); + exit(1); } - pit_min_timer_count = ((uint64_t)10000 * PIT_FREQ) / 1000000; -#else - { - struct sigaction act; - struct itimerval itv; - - /* get times() syscall frequency */ - timer_freq = sysconf(_SC_CLK_TCK); - - /* 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); + current_us = timeout.it_value.tv_sec * 1000000 + timeout.it_value.tv_nsec/1000; + if (current_us && current_us <= nearest_delta_us) + return; - itv.it_interval.tv_sec = 0; - itv.it_interval.tv_usec = 999; /* for i386 kernel 2.6 to get 1 ms */ - itv.it_value.tv_sec = 0; - itv.it_value.tv_usec = 10 * 1000; - setitimer(ITIMER_REAL, &itv, NULL); - /* we probe the tick duration of the kernel to inform the user if - the emulated kernel requested a too high timer frequency */ - getitimer(ITIMER_REAL, &itv); + timeout.it_interval.tv_sec = 0; + timeout.it_interval.tv_nsec = 0; /* 0 for one-shot timer */ + timeout.it_value.tv_sec = nearest_delta_us / 1000000; + timeout.it_value.tv_nsec = (nearest_delta_us % 1000000) * 1000; + if (timer_settime(host_timer, 0 /* RELATIVE */, &timeout, NULL)) { + perror("settime"); + fprintf(stderr, "Internal timer error: aborting\n"); + exit(1); + } +} -#if defined(__linux__) - /* XXX: force /dev/rtc usage because even 2.6 kernels may not - have timers with 1 ms resolution. The correct solution will - be to use the POSIX real time timers available in recent - 2.6 kernels */ - if (itv.it_interval.tv_usec > 1000 || 1) { - /* try to use /dev/rtc to have a faster timer */ - if (start_rtc_timer() < 0) - goto use_itimer; - /* disable itimer */ - itv.it_interval.tv_sec = 0; - itv.it_interval.tv_usec = 0; - itv.it_value.tv_sec = 0; - itv.it_value.tv_usec = 0; - setitimer(ITIMER_REAL, &itv, NULL); - - /* use the RTC */ - sigaction(SIGIO, &act, NULL); - fcntl(rtc_fd, F_SETFL, O_ASYNC); - fcntl(rtc_fd, F_SETOWN, getpid()); - } else #endif /* defined(__linux__) */ - { - use_itimer: - pit_min_timer_count = ((uint64_t)itv.it_interval.tv_usec * - PIT_FREQ) / 1000000; - } - } + +static int unix_start_timer(struct qemu_alarm_timer *t) +{ + struct sigaction act; + struct itimerval itv; + int err; + + /* 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); + + itv.it_interval.tv_sec = 0; + /* for i386 kernel 2.6 to get 1 ms */ + itv.it_interval.tv_usec = 999; + itv.it_value.tv_sec = 0; + itv.it_value.tv_usec = 10 * 1000; + + err = setitimer(ITIMER_REAL, &itv, NULL); + if (err) + return -1; + + return 0; } -void quit_timers(void) +static void unix_stop_timer(struct qemu_alarm_timer *t) { + struct itimerval itv; + + memset(&itv, 0, sizeof(itv)); + setitimer(ITIMER_REAL, &itv, NULL); +} + +#endif /* !defined(_WIN32) */ + #ifdef _WIN32 - timeKillEvent(timerID); - timeEndPeriod(period); - if (host_alarm) { - CloseHandle(host_alarm); - host_alarm = NULL; + +static int win32_start_timer(struct qemu_alarm_timer *t) +{ + TIMECAPS tc; + struct qemu_alarm_win32 *data = t->priv; + UINT flags; + + data->host_alarm = CreateEvent(NULL, FALSE, FALSE, NULL); + if (!data->host_alarm) { + perror("Failed CreateEvent"); + return -1; } -#endif + + memset(&tc, 0, sizeof(tc)); + timeGetDevCaps(&tc, sizeof(tc)); + + if (data->period < tc.wPeriodMin) + data->period = tc.wPeriodMin; + + timeBeginPeriod(data->period); + + flags = TIME_CALLBACK_FUNCTION; + if (alarm_has_dynticks(t)) + flags |= TIME_ONESHOT; + else + flags |= TIME_PERIODIC; + + data->timerId = timeSetEvent(1, // interval (ms) + data->period, // resolution + host_alarm_handler, // function + (DWORD)t, // parameter + flags); + + if (!data->timerId) { + perror("Failed to initialize win32 alarm timer"); + + timeEndPeriod(data->period); + CloseHandle(data->host_alarm); + return -1; + } + + qemu_add_wait_object(data->host_alarm, NULL, NULL); + + return 0; +} + +static void win32_stop_timer(struct qemu_alarm_timer *t) +{ + struct qemu_alarm_win32 *data = t->priv; + + timeKillEvent(data->timerId); + timeEndPeriod(data->period); + + CloseHandle(data->host_alarm); +} + +static void win32_rearm_timer(struct qemu_alarm_timer *t) +{ + struct qemu_alarm_win32 *data = t->priv; + uint64_t nearest_delta_us; + + if (!active_timers[QEMU_TIMER_REALTIME] && + !active_timers[QEMU_TIMER_VIRTUAL]) + return; + + nearest_delta_us = qemu_next_deadline(); + nearest_delta_us /= 1000; + + timeKillEvent(data->timerId); + + data->timerId = timeSetEvent(1, + data->period, + host_alarm_handler, + (DWORD)t, + TIME_ONESHOT | TIME_PERIODIC); + + if (!data->timerId) { + perror("Failed to re-arm win32 alarm timer"); + + timeEndPeriod(data->period); + CloseHandle(data->host_alarm); + exit(1); + } +} + +#endif /* _WIN32 */ + +static void init_timer_alarm(void) +{ + struct qemu_alarm_timer *t; + int i, err = -1; + + for (i = 0; alarm_timers[i].name; i++) { + t = &alarm_timers[i]; + + err = t->start(t); + if (!err) + break; + } + + if (err) { + fprintf(stderr, "Unable to find any suitable alarm timer.\n"); + fprintf(stderr, "Terminating\n"); + exit(1); + } + + alarm_timer = t; +} + +void quit_timers(void) +{ + alarm_timer->stop(alarm_timer); + alarm_timer = NULL; } /***********************************************************/ @@ -1199,8 +1606,8 @@ void qemu_chr_send_event(CharDriverState *s, int event) s->chr_send_event(s, event); } -void qemu_chr_add_handlers(CharDriverState *s, - IOCanRWHandler *fd_can_read, +void qemu_chr_add_handlers(CharDriverState *s, + IOCanRWHandler *fd_can_read, IOReadHandler *fd_read, IOEventHandler *fd_event, void *opaque) @@ -1212,7 +1619,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; @@ -1340,11 +1747,12 @@ static int mux_proc_byte(CharDriverState *chr, MuxDriver *d, int ch) if (bs_table[i]) bdrv_commit(bs_table[i]); } + if (mtd_bdrv) + bdrv_commit(mtd_bdrv); } break; case 'b': - if (chr->chr_event) - chr->chr_event(chr->opaque, CHR_EVENT_BREAK); + qemu_chr_event(chr, CHR_EVENT_BREAK); break; case 'c': /* Switch to the next registered device */ @@ -1466,7 +1874,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); @@ -1556,7 +1964,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; @@ -1580,7 +1988,7 @@ static void fd_chr_update_read_handler(CharDriverState *chr) if (s->fd_in >= 0) { if (nographic && s->fd_in == 0) { } else { - qemu_set_fd_handler2(s->fd_in, fd_chr_read_poll, + qemu_set_fd_handler2(s->fd_in, fd_chr_read_poll, fd_chr_read, NULL, chr); } } @@ -1615,7 +2023,7 @@ static CharDriverState *qemu_chr_open_file_out(const char *file_out) { int fd_out; - fd_out = open(file_out, O_WRONLY | O_TRUNC | O_CREAT | O_BINARY, 0666); + TFR(fd_out = open(file_out, O_WRONLY | O_TRUNC | O_CREAT | O_BINARY, 0666)); if (fd_out < 0) return NULL; return qemu_chr_open_fd(-1, fd_out); @@ -1628,14 +2036,14 @@ static CharDriverState *qemu_chr_open_pipe(const char *filename) snprintf(filename_in, 256, "%s.in", filename); snprintf(filename_out, 256, "%s.out", filename); - fd_in = open(filename_in, O_RDWR | O_BINARY); - fd_out = open(filename_out, O_RDWR | O_BINARY); + TFR(fd_in = open(filename_in, O_RDWR | O_BINARY)); + TFR(fd_out = open(filename_out, O_RDWR | O_BINARY)); if (fd_in < 0 || fd_out < 0) { if (fd_in >= 0) close(fd_in); if (fd_out >= 0) close(fd_out); - fd_in = fd_out = open(filename, O_RDWR | O_BINARY); + TFR(fd_in = fd_out = open(filename, O_RDWR | O_BINARY)); if (fd_in < 0) return NULL; } @@ -1717,7 +2125,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); @@ -1739,18 +2147,20 @@ static CharDriverState *qemu_chr_open_stdio(void) return chr; } -#if defined(__linux__) +#if defined(__linux__) || defined(__sun__) 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); @@ -1762,14 +2172,14 @@ static CharDriverState *qemu_chr_open_pty(void) return qemu_chr_open_fd(master_fd, master_fd); } -static void tty_serial_init(int fd, int speed, +static void tty_serial_init(int fd, int speed, int parity, int data_bits, int stop_bits) { struct termios tty; speed_t spd; #if 0 - printf("tty_serial_init: speed=%d parity=%c data=%d stop=%d\n", + printf("tty_serial_init: speed=%d parity=%c data=%d stop=%d\n", speed, parity, data_bits, stop_bits); #endif tcgetattr (fd, &tty); @@ -1850,19 +2260,19 @@ 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: { QEMUSerialSetParams *ssp = arg; - tty_serial_init(s->fd_in, ssp->speed, ssp->parity, + tty_serial_init(s->fd_in, ssp->speed, ssp->parity, ssp->data_bits, ssp->stop_bits); } break; @@ -1884,19 +2294,26 @@ static CharDriverState *qemu_chr_open_tty(const char *filename) CharDriverState *chr; int fd; - fd = open(filename, O_RDWR | O_NONBLOCK); - if (fd < 0) - return NULL; + TFR(fd = open(filename, O_RDWR | O_NONBLOCK)); fcntl(fd, F_SETFL, O_NONBLOCK); tty_serial_init(fd, 115200, 'N', 8, 1); chr = qemu_chr_open_fd(fd, fd); - if (!chr) + if (!chr) { + close(fd); return NULL; + } chr->chr_ioctl = tty_serial_ioctl; qemu_chr_reset(chr); return chr; } +#else /* ! __linux__ && ! __sun__ */ +static CharDriverState *qemu_chr_open_pty(void) +{ + return NULL; +} +#endif /* __linux__ || __sun__ */ +#if defined(__linux__) typedef struct { int fd; int mode; @@ -2007,7 +2424,7 @@ static CharDriverState *qemu_chr_open_pp(const char *filename) ParallelCharDriver *drv; int fd; - fd = open(filename, O_RDWR); + TFR(fd = open(filename, O_RDWR)); if (fd < 0) return NULL; @@ -2039,17 +2456,10 @@ static CharDriverState *qemu_chr_open_pp(const char *filename) return chr; } +#endif /* __linux__ */ -#else -static CharDriverState *qemu_chr_open_pty(void) -{ - return NULL; -} -#endif - -#endif /* !defined(_WIN32) */ +#else /* _WIN32 */ -#ifdef _WIN32 typedef struct { int max_size; HANDLE hcom, hrecv, hsend; @@ -2096,7 +2506,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"); @@ -2115,12 +2525,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); @@ -2142,7 +2552,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; @@ -2203,7 +2613,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); @@ -2227,7 +2637,7 @@ static void win_chr_read(CharDriverState *chr) s->len = s->max_size; if (s->len == 0) return; - + win_chr_readfile(chr); } @@ -2237,7 +2647,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; @@ -2252,7 +2662,7 @@ static CharDriverState *qemu_chr_open_win(const char *filename) { CharDriverState *chr; WinCharState *s; - + chr = qemu_mallocz(sizeof(CharDriverState)); if (!chr) return NULL; @@ -2297,7 +2707,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); @@ -2310,7 +2720,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 | @@ -2369,7 +2779,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); @@ -2398,11 +2808,16 @@ static CharDriverState *qemu_chr_open_win_file(HANDLE fd_out) qemu_chr_reset(chr); return chr; } - + +static CharDriverState *qemu_chr_open_win_con(const char *filename) +{ + return qemu_chr_open_win_file(GetStdHandle(STD_OUTPUT_HANDLE)); +} + 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) @@ -2410,7 +2825,7 @@ static CharDriverState *qemu_chr_open_win_file_out(const char *file_out) return qemu_chr_open_win_file(fd_out); } -#endif +#endif /* !_WIN32 */ /***********************************************************/ /* UDP Net console */ @@ -2734,7 +3149,7 @@ static void tcp_chr_close(CharDriverState *chr) qemu_free(s); } -static CharDriverState *qemu_chr_open_tcp(const char *host_str, +static CharDriverState *qemu_chr_open_tcp(const char *host_str, int is_telnet, int is_unix) { @@ -2797,8 +3212,8 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str, else #endif fd = socket(PF_INET, SOCK_STREAM, 0); - - if (fd < 0) + + if (fd < 0) goto fail; if (!is_waitconnect) @@ -2828,7 +3243,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; @@ -2849,6 +3264,10 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str, if (err == EINTR || err == EWOULDBLOCK) { } else if (err == EINPROGRESS) { break; +#ifdef _WIN32 + } else if (err == WSAEALREADY) { + break; +#endif } else { goto fail; } @@ -2864,7 +3283,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); @@ -2885,10 +3304,12 @@ CharDriverState *qemu_chr_open(const char *filename) const char *p; if (!strcmp(filename, "vc")) { - return text_console_init(&display_state); + return text_console_init(&display_state, 0); + } else if (strstart(filename, "vc:", &p)) { + return text_console_init(&display_state, p); } else if (!strcmp(filename, "null")) { return qemu_chr_open_null(); - } else + } else if (strstart(filename, "tcp:", &p)) { return qemu_chr_open_tcp(p, 0, 0); } else @@ -2919,23 +3340,27 @@ CharDriverState *qemu_chr_open(const char *filename) return qemu_chr_open_pty(); } else if (!strcmp(filename, "stdio")) { return qemu_chr_open_stdio(); - } else -#endif + } else #if defined(__linux__) if (strstart(filename, "/dev/parport", NULL)) { return qemu_chr_open_pp(filename); - } else + } else +#endif +#if defined(__linux__) || defined(__sun__) if (strstart(filename, "/dev/", NULL)) { return qemu_chr_open_tty(filename); - } else + } else #endif -#ifdef _WIN32 +#else /* !_WIN32 */ if (strstart(filename, "COM", NULL)) { return qemu_chr_open_win(filename); } else if (strstart(filename, "pipe:", &p)) { return qemu_chr_open_win_pipe(p); } else + if (strstart(filename, "con:", NULL)) { + return qemu_chr_open_win_con(filename); + } else if (strstart(filename, "file:", &p)) { return qemu_chr_open_win_file_out(p); } @@ -2986,10 +3411,10 @@ static int parse_macaddr(uint8_t *macaddr, const char *p) for(i = 0; i < 6; i++) { macaddr[i] = strtol(p, (char **)&p, 16); if (i == 5) { - if (*p != '\0') + if (*p != '\0') return -1; } else { - if (*p != ':') + if (*p != ':') return -1; p++; } @@ -3155,11 +3580,11 @@ int qemu_can_send_packet(VLANClientState *vc1) for(vc = vlan->first_client; vc != NULL; vc = vc->next) { if (vc != vc1) { - if (vc->fd_can_read && !vc->fd_can_read(vc->opaque)) - return 0; + if (vc->fd_can_read && vc->fd_can_read(vc->opaque)) + return 1; } } - return 1; + return 0; } void qemu_send_packet(VLANClientState *vc1, const uint8_t *buf, int size) @@ -3216,7 +3641,7 @@ static int net_slirp_init(VLANState *vlan) slirp_inited = 1; slirp_init(); } - slirp_vc = qemu_new_vlan_client(vlan, + slirp_vc = qemu_new_vlan_client(vlan, slirp_receive, NULL, NULL); snprintf(slirp_vc->info_str, sizeof(slirp_vc->info_str), "user redirector"); return 0; @@ -3229,7 +3654,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(); @@ -3259,11 +3684,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); @@ -3273,7 +3698,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]; @@ -3292,7 +3717,7 @@ static void smb_exit(void) break; if (strcmp(de->d_name, ".") != 0 && strcmp(de->d_name, "..") != 0) { - snprintf(filename, sizeof(filename), "%s/%s", + snprintf(filename, sizeof(filename), "%s/%s", smb_dir, de->d_name); unlink(filename); } @@ -3320,13 +3745,13 @@ 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); exit(1); } - fprintf(f, + fprintf(f, "[global]\n" "private dir=%s\n" "smb ports=0\n" @@ -3352,7 +3777,7 @@ 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); } @@ -3416,14 +3841,14 @@ static TAPState *net_tap_fd_init(VLANState *vlan, int fd) return s; } -#ifdef _BSD +#if defined (_BSD) || defined (__FreeBSD_kernel__) static int tap_open(char *ifname, int ifname_size) { int fd; char *dev; struct stat s; - fd = open("/dev/tap", O_RDWR); + TFR(fd = open("/dev/tap", O_RDWR)); if (fd < 0) { fprintf(stderr, "warning: could not open /dev/tap: no virtual network emulation\n"); return -1; @@ -3438,10 +3863,10 @@ static int tap_open(char *ifname, int ifname_size) } #elif defined(__sun__) #define TUNNEWPPA (('T'<<16) | 0x0001) -/* - * Allocate TAP device, returns opened fd. +/* + * 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; @@ -3458,8 +3883,8 @@ int tap_alloc(char *dev) memset(&ifr, 0x0, sizeof(ifr)); if( *dev ){ - ptr = dev; - while( *ptr && !isdigit((int)*ptr) ) ptr++; + ptr = dev; + while( *ptr && !isdigit((int)*ptr) ) ptr++; ppa = atoi(ptr); } @@ -3467,12 +3892,14 @@ int tap_alloc(char *dev) if( ip_fd ) close(ip_fd); - if( (ip_fd = open("/dev/udp", O_RDWR, 0)) < 0){ + TFR(ip_fd = open("/dev/udp", O_RDWR, 0)); + if (ip_fd < 0) { syslog(LOG_ERR, "Can't open /dev/ip (actually /dev/udp)"); return -1; } - if( (tap_fd = open("/dev/tap", O_RDWR, 0)) < 0){ + TFR(tap_fd = open("/dev/tap", O_RDWR, 0)); + if (tap_fd < 0) { syslog(LOG_ERR, "Can't open /dev/tap"); return -1; } @@ -3485,7 +3912,8 @@ int tap_alloc(char *dev) if ((ppa = ioctl (tap_fd, I_STR, &strioc_ppa)) < 0) syslog (LOG_ERR, "Can't assign new interface"); - if( (if_fd = open("/dev/tap", O_RDWR, 0)) < 0){ + TFR(if_fd = open("/dev/tap", O_RDWR, 0)); + if (if_fd < 0) { syslog(LOG_ERR, "Can't open /dev/tap (2)"); return -1; } @@ -3517,7 +3945,8 @@ int tap_alloc(char *dev) if (ioctl (ip_fd, I_PUSH, "arp") < 0) syslog (LOG_ERR, "Can't push ARP module (3)\n"); /* Open arp_fd */ - if ((arp_fd = open ("/dev/tap", O_RDWR, 0)) < 0) + TFR(arp_fd = open ("/dev/tap", O_RDWR, 0)); + if (arp_fd < 0) syslog (LOG_ERR, "Can't open %s\n", "/dev/tap"); /* Set ifname to arp */ @@ -3572,8 +4001,8 @@ static int tap_open(char *ifname, int ifname_size) { struct ifreq ifr; int fd, ret; - - fd = open("/dev/net/tun", O_RDWR); + + 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"); return -1; @@ -3609,7 +4038,7 @@ static int net_tap_init(VLANState *vlan, const char *ifname1, pstrcpy(ifname, sizeof(ifname), ifname1); else ifname[0] = '\0'; - fd = tap_open(ifname, sizeof(ifname)); + TFR(fd = tap_open(ifname, sizeof(ifname))); if (fd < 0) return -1; @@ -3620,6 +4049,14 @@ static int net_tap_init(VLANState *vlan, const char *ifname1, pid = fork(); if (pid >= 0) { if (pid == 0) { + int open_max = sysconf (_SC_OPEN_MAX), i; + for (i = 0; i < open_max; i++) + if (i != STDIN_FILENO && + i != STDOUT_FILENO && + i != STDERR_FILENO && + i != fd) + close(i); + parg = args; *parg++ = (char *)setup_script; *parg++ = ifname; @@ -3639,7 +4076,7 @@ static int net_tap_init(VLANState *vlan, const char *ifname1, s = net_tap_fd_init(vlan, fd); if (!s) return -1; - snprintf(s->vc->info_str, sizeof(s->vc->info_str), + snprintf(s->vc->info_str, sizeof(s->vc->info_str), "tap: ifname=%s setup_script=%s", ifname, setup_script); return 0; } @@ -3676,7 +4113,7 @@ static void net_socket_receive(void *opaque, const uint8_t *buf, int size) static void net_socket_receive_dgram(void *opaque, const uint8_t *buf, int size) { NetSocketState *s = opaque; - sendto(s->fd, buf, size, 0, + sendto(s->fd, buf, size, 0, (struct sockaddr *)&s->dgram_dst, sizeof(s->dgram_dst)); } @@ -3690,7 +4127,7 @@ static void net_socket_send(void *opaque) size = recv(s->fd, buf1, sizeof(buf1), 0); if (size < 0) { err = socket_error(); - if (err != EWOULDBLOCK) + if (err != EWOULDBLOCK) goto eoc; } else if (size == 0) { /* end of connection */ @@ -3742,7 +4179,7 @@ static void net_socket_send_dgram(void *opaque) int size; size = recv(s->fd, s->buf, sizeof(s->buf), 0); - if (size < 0) + if (size < 0) return; if (size == 0) { /* end of connection */ @@ -3759,7 +4196,7 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr) int val, ret; if (!IN_MULTICAST(ntohl(mcastaddr->sin_addr.s_addr))) { fprintf(stderr, "qemu: error: specified mcastaddr \"%s\" (0x%08x) does not contain a multicast address\n", - inet_ntoa(mcastaddr->sin_addr), + inet_ntoa(mcastaddr->sin_addr), (int)ntohl(mcastaddr->sin_addr.s_addr)); return -1; @@ -3771,7 +4208,7 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr) } val = 1; - ret=setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, + ret=setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(val)); if (ret < 0) { perror("setsockopt(SOL_SOCKET, SO_REUSEADDR)"); @@ -3783,12 +4220,12 @@ 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); - ret = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, + ret = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const char *)&imr, sizeof(struct ip_mreq)); if (ret < 0) { perror("setsockopt(IP_ADD_MEMBERSHIP)"); @@ -3797,7 +4234,7 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr) /* Force mcast msgs to loopback (eg. several QEMUs in same host */ val = 1; - ret=setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, + ret=setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, (const char *)&val, sizeof(val)); if (ret < 0) { perror("setsockopt(SOL_IP, IP_MULTICAST_LOOP)"); @@ -3807,12 +4244,12 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr) socket_set_nonblock(fd); return fd; fail: - if (fd >= 0) + if (fd >= 0) closesocket(fd); return -1; } -static NetSocketState *net_socket_fd_init_dgram(VLANState *vlan, int fd, +static NetSocketState *net_socket_fd_init_dgram(VLANState *vlan, int fd, int is_connected) { struct sockaddr_in saddr; @@ -3821,7 +4258,7 @@ static NetSocketState *net_socket_fd_init_dgram(VLANState *vlan, int fd, NetSocketState *s; /* fd passed: multicast: "learn" dgram_dst address from bound address and save it - * Because this may be "shared" socket from a "master" process, datagrams would be recv() + * Because this may be "shared" socket from a "master" process, datagrams would be recv() * by ONLY ONE process: we must "clone" this dgram socket --jjo */ @@ -3843,7 +4280,7 @@ static NetSocketState *net_socket_fd_init_dgram(VLANState *vlan, int fd, /* clone newfd to fd, close newfd */ dup2(newfd, fd); close(newfd); - + } else { fprintf(stderr, "qemu: error: init_dgram: fd=%d failed getsockname(): %s\n", fd, strerror(errno)); @@ -3863,7 +4300,7 @@ static NetSocketState *net_socket_fd_init_dgram(VLANState *vlan, int fd, if (is_connected) s->dgram_dst=saddr; snprintf(s->vc->info_str, sizeof(s->vc->info_str), - "socket: fd=%d (%s mcast=%s:%d)", + "socket: fd=%d (%s mcast=%s:%d)", fd, is_connected? "cloned" : "", inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port)); return s; @@ -3875,7 +4312,7 @@ static void net_socket_connect(void *opaque) qemu_set_fd_handler(s->fd, net_socket_send, NULL, s); } -static NetSocketState *net_socket_fd_init_stream(VLANState *vlan, int fd, +static NetSocketState *net_socket_fd_init_stream(VLANState *vlan, int fd, int is_connected) { NetSocketState *s; @@ -3883,7 +4320,7 @@ static NetSocketState *net_socket_fd_init_stream(VLANState *vlan, int fd, if (!s) return NULL; s->fd = fd; - s->vc = qemu_new_vlan_client(vlan, + s->vc = qemu_new_vlan_client(vlan, net_socket_receive, NULL, s); snprintf(s->vc->info_str, sizeof(s->vc->info_str), "socket: fd=%d", fd); @@ -3895,13 +4332,13 @@ static NetSocketState *net_socket_fd_init_stream(VLANState *vlan, int fd, return s; } -static NetSocketState *net_socket_fd_init(VLANState *vlan, int fd, +static NetSocketState *net_socket_fd_init(VLANState *vlan, int fd, int is_connected) { int so_type=-1, optlen=sizeof(so_type); if(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&so_type, &optlen)< 0) { - fprintf(stderr, "qemu: error: setsockopt(SO_TYPE) for fd=%d failed\n", fd); + fprintf(stderr, "qemu: error: getsockopt(SO_TYPE) for fd=%d failed\n", fd); return NULL; } switch(so_type) { @@ -3919,7 +4356,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; @@ -3934,12 +4371,12 @@ static void net_socket_accept(void *opaque) break; } } - s1 = net_socket_fd_init(s->vlan, fd, 1); + s1 = net_socket_fd_init(s->vlan, fd, 1); if (!s1) { closesocket(fd); } else { snprintf(s1->vc->info_str, sizeof(s1->vc->info_str), - "socket: connection from %s:%d", + "socket: connection from %s:%d", inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port)); } } @@ -3952,7 +4389,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; @@ -3967,7 +4404,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"); @@ -4008,6 +4445,10 @@ static int net_socket_connect_init(VLANState *vlan, const char *host_str) if (err == EINTR || err == EWOULDBLOCK) { } else if (err == EINPROGRESS) { break; +#ifdef _WIN32 + } else if (err == WSAEALREADY) { + break; +#endif } else { perror("connect"); closesocket(fd); @@ -4022,7 +4463,7 @@ static int net_socket_connect_init(VLANState *vlan, const char *host_str) if (!s) return -1; snprintf(s->vc->info_str, sizeof(s->vc->info_str), - "socket: connect to %s:%d", + "socket: connect to %s:%d", inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port)); return 0; } @@ -4046,9 +4487,9 @@ 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", + "socket: mcast=%s:%d", inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port)); return 0; @@ -4150,6 +4591,7 @@ static int net_client_init(const char *str) } nd->vlan = vlan; nb_nics++; + vlan->nb_guest_devs++; ret = 0; } else if (!strcmp(device, "none")) { @@ -4162,6 +4604,7 @@ static int net_client_init(const char *str) if (get_param_value(buf, sizeof(buf), "hostname", p)) { pstrcpy(slirp_hostname, sizeof(slirp_hostname), buf); } + vlan->nb_host_devs++; ret = net_slirp_init(vlan); } else #endif @@ -4172,6 +4615,7 @@ static int net_client_init(const char *str) fprintf(stderr, "tap: no interface name\n"); return -1; } + vlan->nb_host_devs++; ret = tap_win32_init(vlan, ifname); } else #else @@ -4179,6 +4623,7 @@ static int net_client_init(const char *str) char ifname[64]; char setup_script[1024]; int fd; + vlan->nb_host_devs++; if (get_param_value(buf, sizeof(buf), "fd", p) > 0) { fd = strtol(buf, NULL, 0); ret = -1; @@ -4212,6 +4657,7 @@ static int net_client_init(const char *str) fprintf(stderr, "Unknown socket options: %s\n", p); return -1; } + vlan->nb_host_devs++; } else { fprintf(stderr, "Unknown network device: %s\n", device); @@ -4220,7 +4666,7 @@ static int net_client_init(const char *str) if (ret < 0) { fprintf(stderr, "Could not initialize device '%s'\n", device); } - + return ret; } @@ -4267,9 +4713,13 @@ static int usb_device_add(const char *devname) } else if (!strcmp(devname, "mouse")) { dev = usb_mouse_init(); } else if (!strcmp(devname, "tablet")) { - dev = usb_tablet_init(); + dev = usb_tablet_init(); + } else if (!strcmp(devname, "keyboard")) { + dev = usb_keyboard_init(); } else if (strstart(devname, "disk:", &p)) { dev = usb_msd_init(p); + } else if (!strcmp(devname, "wacom-tablet")) { + dev = usb_wacom_init(); } else { return -1; } @@ -4310,7 +4760,7 @@ static int usb_device_del(const char *devname) return -1; p = strchr(devname, '.'); - if (!p) + if (!p) return -1; bus_num = strtoul(devname, NULL, 0); addr = strtoul(p + 1, NULL, 0); @@ -4340,7 +4790,7 @@ void do_usb_add(const char *devname) { int ret; ret = usb_device_add(devname); - if (ret < 0) + if (ret < 0) term_printf("Could not add USB device '%s'\n", devname); } @@ -4348,7 +4798,7 @@ void do_usb_del(const char *devname) { int ret; ret = usb_device_del(devname); - if (ret < 0) + if (ret < 0) term_printf("Could not remove USB device '%s'\n", devname); } @@ -4368,62 +4818,64 @@ void usb_info(void) if (!dev) continue; switch(dev->speed) { - case USB_SPEED_LOW: - speed_str = "1.5"; + case USB_SPEED_LOW: + speed_str = "1.5"; break; - case USB_SPEED_FULL: - speed_str = "12"; + case USB_SPEED_FULL: + speed_str = "12"; break; - case USB_SPEED_HIGH: - speed_str = "480"; + case USB_SPEED_HIGH: + speed_str = "480"; break; default: - speed_str = "?"; + speed_str = "?"; break; } - term_printf(" Device %d.%d, Speed %s Mb/s, Product %s\n", + term_printf(" Device %d.%d, Speed %s Mb/s, Product %s\n", 0, dev->addr, speed_str, dev->devname); } } /***********************************************************/ -/* pid file */ - -static char *pid_filename; +/* PCMCIA/Cardbus */ -/* Remove PID file. Called on normal exit */ +static struct pcmcia_socket_entry_s { + struct pcmcia_socket_s *socket; + struct pcmcia_socket_entry_s *next; +} *pcmcia_sockets = 0; -static void remove_pidfile(void) +void pcmcia_socket_register(struct pcmcia_socket_s *socket) { - unlink (pid_filename); + struct pcmcia_socket_entry_s *entry; + + entry = qemu_malloc(sizeof(struct pcmcia_socket_entry_s)); + entry->socket = socket; + entry->next = pcmcia_sockets; + pcmcia_sockets = entry; } -static void create_pidfile(const char *filename) +void pcmcia_socket_unregister(struct pcmcia_socket_s *socket) { - struct stat pidstat; - FILE *f; + struct pcmcia_socket_entry_s *entry, **ptr; - /* Try to write our PID to the named file */ - if (stat(filename, &pidstat) < 0) { - if (errno == ENOENT) { - if ((f = fopen (filename, "w")) == NULL) { - perror("Opening pidfile"); - exit(1); - } - fprintf(f, "%d\n", getpid()); - fclose(f); - pid_filename = qemu_strdup(filename); - if (!pid_filename) { - fprintf(stderr, "Could not save PID filename"); - exit(1); - } - atexit(remove_pidfile); + ptr = &pcmcia_sockets; + for (entry = *ptr; entry; ptr = &entry->next, entry = *ptr) + if (entry->socket == socket) { + *ptr = entry->next; + qemu_free(entry); } - } else { - fprintf(stderr, "%s already exists. Remove it and try again.\n", - filename); - exit(1); - } +} + +void pcmcia_info(void) +{ + struct pcmcia_socket_entry_s *iter; + if (!pcmcia_sockets) + term_printf("No PCMCIA sockets\n"); + + for (iter = pcmcia_sockets; iter; iter = iter->next) + term_printf("%s: %s\n", iter->socket->slot_string, + iter->socket->attached ? iter->socket->card_string : + "Empty"); } /***********************************************************/ @@ -4439,10 +4891,12 @@ static void dumb_resize(DisplayState *ds, int w, int h) static void dumb_refresh(DisplayState *ds) { +#if defined(CONFIG_SDL) vga_hw_update(); +#endif } -void dumb_display_init(DisplayState *ds) +static void dumb_display_init(DisplayState *ds) { ds->data = NULL; ds->linesize = 0; @@ -4473,10 +4927,10 @@ static IOHandlerRecord *first_io_handler; /* XXX: fd_read_poll should be suppressed, but an API change is necessary in the character devices to suppress fd_can_read(). */ -int qemu_set_fd_handler2(int fd, - IOCanRWHandler *fd_read_poll, - IOHandler *fd_read, - IOHandler *fd_write, +int qemu_set_fd_handler2(int fd, + IOCanRWHandler *fd_read_poll, + IOHandler *fd_read, + IOHandler *fd_write, void *opaque) { IOHandlerRecord **pioh, *ioh; @@ -4514,9 +4968,9 @@ int qemu_set_fd_handler2(int fd, return 0; } -int qemu_set_fd_handler(int fd, - IOHandler *fd_read, - IOHandler *fd_write, +int qemu_set_fd_handler(int fd, + IOHandler *fd_read, + IOHandler *fd_write, void *opaque) { return qemu_set_fd_handler2(fd, NULL, fd_read, fd_write, opaque); @@ -4570,7 +5024,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; @@ -4597,7 +5051,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--; @@ -4671,7 +5125,7 @@ void qemu_fflush(QEMUFile *f) fseek(f->outfile, f->buf_offset, SEEK_SET); fwrite(f->buf, 1, f->buf_index, f->outfile); } else { - bdrv_pwrite(f->bs, f->base_offset + f->buf_offset, + bdrv_pwrite(f->bs, f->base_offset + f->buf_offset, f->buf, f->buf_index); } f->buf_offset += f->buf_index; @@ -4691,7 +5145,7 @@ static void qemu_fill_buffer(QEMUFile *f) if (len < 0) len = 0; } else { - len = bdrv_pread(f->bs, f->base_offset + f->buf_offset, + len = bdrv_pread(f->bs, f->base_offset + f->buf_offset, f->buf, IO_BUF_SIZE); if (len < 0) len = 0; @@ -4851,8 +5305,8 @@ typedef struct SaveStateEntry { static SaveStateEntry *first_se; -int register_savevm(const char *idstr, - int instance_id, +int register_savevm(const char *idstr, + int instance_id, int version_id, SaveStateHandler *save_state, LoadStateHandler *load_state, @@ -4905,7 +5359,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 */ @@ -4929,7 +5383,7 @@ static SaveStateEntry *find_se(const char *idstr, int instance_id) SaveStateEntry *se; for(se = first_se; se != NULL; se = se->next) { - if (!strcmp(se->idstr, idstr) && + if (!strcmp(se->idstr, idstr) && instance_id == se->instance_id) return se; } @@ -4943,7 +5397,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; @@ -4965,18 +5419,18 @@ int qemu_loadvm_state(QEMUFile *f) version_id = qemu_get_be32(f); record_len = qemu_get_be32(f); #if 0 - printf("idstr=%s instance=0x%x version=%d len=%d\n", + printf("idstr=%s instance=0x%x version=%d len=%d\n", idstr, instance_id, version_id, record_len); #endif cur_pos = qemu_ftell(f); se = find_se(idstr, instance_id); if (!se) { - fprintf(stderr, "qemu: warning: instance 0x%x of device '%s' not present in current VM\n", + fprintf(stderr, "qemu: warning: instance 0x%x of device '%s' not present in current VM\n", instance_id, idstr); } else { ret = se->load_state(f, se->opaque, version_id); if (ret < 0) { - fprintf(stderr, "qemu: warning: error while loading state for instance 0x%x of device '%s'\n", + fprintf(stderr, "qemu: warning: error while loading state for instance 0x%x of device '%s'\n", instance_id, idstr); } } @@ -5027,7 +5481,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) @@ -5069,7 +5523,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); @@ -5097,13 +5551,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) { @@ -5117,7 +5571,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++) { @@ -5156,7 +5610,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(); @@ -5196,7 +5650,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) { @@ -5223,7 +5677,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)) { @@ -5303,14 +5757,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; @@ -5318,7 +5772,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); @@ -5329,7 +5783,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 { @@ -5356,16 +5810,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]); @@ -5433,7 +5887,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. */ @@ -5441,7 +5895,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); @@ -5472,7 +5926,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; @@ -5487,23 +5941,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]); @@ -5524,7 +5978,7 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id) qemu_get_be64s(f, &env->fmask); qemu_get_be64s(f, &env->kernelgsbase); #endif - if (version_id >= 4) + if (version_id >= 4) qemu_get_be32s(f, &env->smbase); /* XXX: compute hflags from scratch, except for CPL and IIF */ @@ -5632,13 +6086,146 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id) #elif defined(TARGET_ARM) -/* ??? Need to implement these. */ void cpu_save(QEMUFile *f, void *opaque) { + int i; + CPUARMState *env = (CPUARMState *)opaque; + + for (i = 0; i < 16; i++) { + qemu_put_be32(f, env->regs[i]); + } + qemu_put_be32(f, cpsr_read(env)); + qemu_put_be32(f, env->spsr); + for (i = 0; i < 6; i++) { + qemu_put_be32(f, env->banked_spsr[i]); + qemu_put_be32(f, env->banked_r13[i]); + qemu_put_be32(f, env->banked_r14[i]); + } + for (i = 0; i < 5; i++) { + qemu_put_be32(f, env->usr_regs[i]); + qemu_put_be32(f, env->fiq_regs[i]); + } + qemu_put_be32(f, env->cp15.c0_cpuid); + qemu_put_be32(f, env->cp15.c0_cachetype); + 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_data); + qemu_put_be32(f, env->cp15.c2_insn); + qemu_put_be32(f, env->cp15.c3); + qemu_put_be32(f, env->cp15.c5_insn); + qemu_put_be32(f, env->cp15.c5_data); + for (i = 0; i < 8; i++) { + qemu_put_be32(f, env->cp15.c6_region[i]); + } + qemu_put_be32(f, env->cp15.c6_insn); + qemu_put_be32(f, env->cp15.c6_data); + qemu_put_be32(f, env->cp15.c9_insn); + 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.c15_cpar); + + qemu_put_be32(f, env->features); + + if (arm_feature(env, ARM_FEATURE_VFP)) { + for (i = 0; i < 16; i++) { + CPU_DoubleU u; + u.d = env->vfp.regs[i]; + qemu_put_be32(f, u.l.upper); + qemu_put_be32(f, u.l.lower); + } + for (i = 0; i < 16; i++) { + qemu_put_be32(f, env->vfp.xregs[i]); + } + + /* 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_IWMMXT)) { + for (i = 0; i < 16; i++) { + qemu_put_be64(f, env->iwmmxt.regs[i]); + } + for (i = 0; i < 16; i++) { + qemu_put_be32(f, env->iwmmxt.cregs[i]); + } + } } int cpu_load(QEMUFile *f, void *opaque, int version_id) { + CPUARMState *env = (CPUARMState *)opaque; + int i; + + if (version_id != 0) + return -EINVAL; + + for (i = 0; i < 16; i++) { + env->regs[i] = qemu_get_be32(f); + } + cpsr_write(env, qemu_get_be32(f), 0xffffffff); + env->spsr = qemu_get_be32(f); + for (i = 0; i < 6; i++) { + env->banked_spsr[i] = qemu_get_be32(f); + env->banked_r13[i] = qemu_get_be32(f); + env->banked_r14[i] = qemu_get_be32(f); + } + for (i = 0; i < 5; i++) { + env->usr_regs[i] = qemu_get_be32(f); + env->fiq_regs[i] = qemu_get_be32(f); + } + env->cp15.c0_cpuid = qemu_get_be32(f); + env->cp15.c0_cachetype = qemu_get_be32(f); + 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_data = qemu_get_be32(f); + env->cp15.c2_insn = qemu_get_be32(f); + env->cp15.c3 = qemu_get_be32(f); + env->cp15.c5_insn = qemu_get_be32(f); + env->cp15.c5_data = qemu_get_be32(f); + for (i = 0; i < 8; i++) { + env->cp15.c6_region[i] = qemu_get_be32(f); + } + env->cp15.c6_insn = qemu_get_be32(f); + env->cp15.c6_data = qemu_get_be32(f); + env->cp15.c9_insn = 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.c15_cpar = qemu_get_be32(f); + + env->features = qemu_get_be32(f); + + if (arm_feature(env, ARM_FEATURE_VFP)) { + 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; + } + for (i = 0; i < 16; i++) { + env->vfp.xregs[i] = 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_IWMMXT)) { + for (i = 0; i < 16; i++) { + env->iwmmxt.regs[i] = qemu_get_be64(f); + } + for (i = 0; i < 16; i++) { + env->iwmmxt.cregs[i] = qemu_get_be32(f); + } + } + return 0; } @@ -5701,7 +6288,7 @@ static int ram_compress_open(RamCompressState *s, QEMUFile *f) memset(s, 0, sizeof(*s)); s->f = f; ret = deflateInit2(&s->zstream, 1, - Z_DEFLATED, 15, + Z_DEFLATED, 15, 9, Z_DEFAULT_STRATEGY); if (ret != Z_OK) return -1; @@ -5812,7 +6399,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; @@ -5827,7 +6414,7 @@ static void ram_save(QEMUFile *f, void *opaque) sector_num = -1; for(j = 0; j < MAX_DISKS; j++) { if (bs_table[j]) { - sector_num = bdrv_hash_find(bs_table[j], + sector_num = bdrv_hash_find(bs_table[j], phys_ram_base + i, BDRV_HASH_BLOCK_SIZE); if (sector_num >= 0) break; @@ -5839,7 +6426,7 @@ static void ram_save(QEMUFile *f, void *opaque) buf[1] = j; cpu_to_be64wu((uint64_t *)(buf + 2), sector_num); ram_compress_buf(s, buf, 10); - } else + } else #endif { // normal_compress: @@ -5875,7 +6462,7 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id) fprintf(stderr, "Error while reading ram block address=0x%08x", i); goto error; } - } else + } else #if 0 if (buf[0] == 1) { int bs_index; @@ -5888,13 +6475,13 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id) fprintf(stderr, "Invalid block device index %d\n", bs_index); goto error; } - if (bdrv_read(bs_table[bs_index], sector_num, phys_ram_base + i, + if (bdrv_read(bs_table[bs_index], sector_num, phys_ram_base + i, BDRV_HASH_BLOCK_SIZE / 512) < 0) { - fprintf(stderr, "Error while reading sector %d:%" PRId64 "\n", + fprintf(stderr, "Error while reading sector %d:%" PRId64 "\n", bs_index, sector_num); goto error; } - } else + } else #endif { error: @@ -6013,8 +6600,9 @@ QEMUMachine *find_machine(const char *name) void gui_update(void *opaque) { - display_state.dpy_refresh(&display_state); - qemu_mod_timer(gui_timer, GUI_REFRESH_INTERVAL + qemu_get_clock(rt_clock)); + DisplayState *ds = opaque; + ds->dpy_refresh(ds); + qemu_mod_timer(ds->gui_timer, GUI_REFRESH_INTERVAL + qemu_get_clock(rt_clock)); } struct vm_change_state_entry { @@ -6077,10 +6665,11 @@ void vm_start(void) cpu_enable_ticks(); vm_running = 1; vm_state_notify(1); + qemu_rearm_alarm_timer(alarm_timer); } } -void vm_stop(int reason) +void vm_stop(int reason) { if (vm_running) { cpu_disable_ticks(); @@ -6161,6 +6750,9 @@ void main_loop_wait(int timeout) IOHandlerRecord *ioh; fd_set rfds, wfds, xfds; int ret, nfds; +#ifdef _WIN32 + int ret2, i; +#endif struct timeval tv; PollingEntry *pe; @@ -6171,18 +6763,33 @@ void main_loop_wait(int timeout) ret |= pe->func(pe->opaque); } #ifdef _WIN32 - if (ret == 0 && timeout > 0) { + 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) { + if (w->func[i]) + w->func[i](w->opaque[i]); + } else if (ret2 == WAIT_TIMEOUT) { + } else { + err = GetLastError(); + fprintf(stderr, "WaitForSingleObject error %d %d\n", i, err); + } + } } else if (ret == WAIT_TIMEOUT) { } else { err = GetLastError(); - fprintf(stderr, "Wait error %d %d\n", ret, err); + fprintf(stderr, "WaitForMultipleObjects error %d %d\n", ret, err); } } #endif @@ -6208,7 +6815,7 @@ void main_loop_wait(int timeout) nfds = ioh->fd; } } - + tv.tv_sec = 0; #ifdef _WIN32 tv.tv_usec = 0; @@ -6225,12 +6832,10 @@ void main_loop_wait(int timeout) IOHandlerRecord **pioh; for(ioh = first_io_handler; ioh != NULL; ioh = ioh->next) { - if (ioh->deleted) - continue; - if (FD_ISSET(ioh->fd, &rfds)) { + if (!ioh->deleted && ioh->fd_read && FD_ISSET(ioh->fd, &rfds)) { ioh->fd_read(ioh->opaque); } - if (FD_ISSET(ioh->fd, &wfds)) { + if (!ioh->deleted && ioh->fd_write && FD_ISSET(ioh->fd, &wfds)) { ioh->fd_write(ioh->opaque); } } @@ -6242,7 +6847,7 @@ void main_loop_wait(int timeout) if (ioh->deleted) { *pioh = ioh->next; qemu_free(ioh); - } else + } else pioh = &ioh->next; } } @@ -6257,18 +6862,22 @@ void main_loop_wait(int timeout) } #endif qemu_aio_poll(); - qemu_bh_poll(); if (vm_running) { - qemu_run_timers(&active_timers[QEMU_TIMER_VIRTUAL], + qemu_run_timers(&active_timers[QEMU_TIMER_VIRTUAL], qemu_get_clock(vm_clock)); /* run dma transfers, if any */ DMA_run(); } - + /* real time timers */ - qemu_run_timers(&active_timers[QEMU_TIMER_REALTIME], + qemu_run_timers(&active_timers[QEMU_TIMER_REALTIME], qemu_get_clock(rt_clock)); + + /* Check bottom-halves last in case any of the earlier events triggered + them. */ + qemu_bh_poll(); + } static CPUState *cur_cpu; @@ -6349,7 +6958,7 @@ int main_loop(void) return ret; } -void help(void) +static void help(int exitcode) { printf("QEMU PC emulator version " QEMU_VERSION ", Copyright (c) 2003-2007 Fabrice Bellard\n" "usage: %s [options] [disk_image]\n" @@ -6363,10 +6972,14 @@ void help(void) "-hda/-hdb file use 'file' as IDE hard disk 0/1 image\n" "-hdc/-hdd file use 'file' as IDE hard disk 2/3 image\n" "-cdrom file use 'file' as IDE cdrom image (cdrom is ide1 master)\n" + "-mtdblock file use 'file' as on-board Flash memory image\n" + "-sd file use 'file' as SecureDigital card image\n" + "-pflash file use 'file' as a parallel flash image\n" "-boot [a|c|d|n] boot on floppy (a), hard disk (c), CD-ROM (d), or network (n)\n" "-snapshot write to temporary files instead of disk image files\n" #ifdef CONFIG_SDL "-no-frame open SDL window without a frame and window decorations\n" + "-alt-grab use Ctrl-Alt-Shift to grab mouse (instead of Ctrl-Alt)\n" "-no-quit disable SDL window close capability\n" #endif #ifdef TARGET_I386 @@ -6375,6 +6988,7 @@ void help(void) "-m megs set virtual RAM size to megs MB [default=%d]\n" "-smp n set the number of CPUs to 'n' [default=1]\n" "-nographic disable graphical output and redirect serial I/Os to console\n" + "-portrait rotate graphical output 90 deg left (only PXA LCD)\n" #ifndef _WIN32 "-k language use keyboard layout (for example \"fr\" for French)\n" #endif @@ -6395,6 +7009,7 @@ void help(void) #if defined(TARGET_PPC) || defined(TARGET_SPARC) "-g WxH[xDEPTH] Set the initial graphical resolution and depth\n" #endif + "-name string set the name of the guest\n" "\n" "Network options:\n" "-net nic[,vlan=n][,macaddr=addr][,model=type]\n" @@ -6467,6 +7082,11 @@ void help(void) "-daemonize daemonize QEMU after initializing\n" #endif "-option-rom rom load a file, rom, into the option ROM space\n" +#ifdef TARGET_SPARC + "-prom-env variable=value set OpenBIOS nvram variables\n" +#endif + "-clock force the use of the given methods for timer alarm.\n" + " To see what timers are available use -clock help\n" "\n" "During emulation, the following keys are useful:\n" "ctrl-alt-f toggle full screen\n" @@ -6482,7 +7102,7 @@ void help(void) #endif DEFAULT_GDBSTUB_PORT, "/tmp/qemu.log"); - exit(1); + exit(exitcode); } #define HAS_ARG 0x0001 @@ -6499,6 +7119,9 @@ enum { QEMU_OPTION_hdc, QEMU_OPTION_hdd, QEMU_OPTION_cdrom, + QEMU_OPTION_mtdblock, + QEMU_OPTION_sd, + QEMU_OPTION_pflash, QEMU_OPTION_boot, QEMU_OPTION_snapshot, #ifdef TARGET_I386 @@ -6506,6 +7129,7 @@ enum { #endif QEMU_OPTION_m, QEMU_OPTION_nographic, + QEMU_OPTION_portrait, #ifdef HAS_AUDIO QEMU_OPTION_audio_help, QEMU_OPTION_soundhw, @@ -6531,6 +7155,7 @@ enum { QEMU_OPTION_k, QEMU_OPTION_localtime, QEMU_OPTION_cirrusvga, + QEMU_OPTION_vmsvga, QEMU_OPTION_g, QEMU_OPTION_std_vga, QEMU_OPTION_echr, @@ -6540,6 +7165,7 @@ enum { QEMU_OPTION_loadvm, QEMU_OPTION_full_screen, QEMU_OPTION_no_frame, + QEMU_OPTION_alt_grab, QEMU_OPTION_no_quit, QEMU_OPTION_pidfile, QEMU_OPTION_no_kqemu, @@ -6551,9 +7177,14 @@ enum { QEMU_OPTION_vnc, QEMU_OPTION_no_acpi, QEMU_OPTION_no_reboot, + QEMU_OPTION_show_cursor, QEMU_OPTION_daemonize, QEMU_OPTION_option_rom, - QEMU_OPTION_semihosting + QEMU_OPTION_semihosting, + QEMU_OPTION_name, + QEMU_OPTION_prom_env, + QEMU_OPTION_old_param, + QEMU_OPTION_clock, }; typedef struct QEMUOption { @@ -6575,6 +7206,9 @@ const QEMUOption qemu_options[] = { { "hdc", HAS_ARG, QEMU_OPTION_hdc }, { "hdd", HAS_ARG, QEMU_OPTION_hdd }, { "cdrom", HAS_ARG, QEMU_OPTION_cdrom }, + { "mtdblock", HAS_ARG, QEMU_OPTION_mtdblock }, + { "sd", HAS_ARG, QEMU_OPTION_sd }, + { "pflash", HAS_ARG, QEMU_OPTION_pflash }, { "boot", HAS_ARG, QEMU_OPTION_boot }, { "snapshot", 0, QEMU_OPTION_snapshot }, #ifdef TARGET_I386 @@ -6582,6 +7216,7 @@ const QEMUOption qemu_options[] = { #endif { "m", HAS_ARG, QEMU_OPTION_m }, { "nographic", 0, QEMU_OPTION_nographic }, + { "portrait", 0, QEMU_OPTION_portrait }, { "k", HAS_ARG, QEMU_OPTION_k }, #ifdef HAS_AUDIO { "audio-help", 0, QEMU_OPTION_audio_help }, @@ -6618,14 +7253,15 @@ const QEMUOption qemu_options[] = { #endif { "localtime", 0, QEMU_OPTION_localtime }, { "std-vga", 0, QEMU_OPTION_std_vga }, - { "echr", 1, QEMU_OPTION_echr }, - { "monitor", 1, QEMU_OPTION_monitor }, - { "serial", 1, QEMU_OPTION_serial }, - { "parallel", 1, QEMU_OPTION_parallel }, + { "echr", HAS_ARG, QEMU_OPTION_echr }, + { "monitor", HAS_ARG, QEMU_OPTION_monitor }, + { "serial", HAS_ARG, QEMU_OPTION_serial }, + { "parallel", HAS_ARG, QEMU_OPTION_parallel }, { "loadvm", HAS_ARG, QEMU_OPTION_loadvm }, { "full-screen", 0, QEMU_OPTION_full_screen }, #ifdef CONFIG_SDL { "no-frame", 0, QEMU_OPTION_no_frame }, + { "alt-grab", 0, QEMU_OPTION_alt_grab }, { "no-quit", 0, QEMU_OPTION_no_quit }, #endif { "pidfile", HAS_ARG, QEMU_OPTION_pidfile }, @@ -6637,13 +7273,23 @@ const QEMUOption qemu_options[] = { /* temporary options */ { "usb", 0, QEMU_OPTION_usb }, { "cirrusvga", 0, QEMU_OPTION_cirrusvga }, + { "vmwarevga", 0, QEMU_OPTION_vmsvga }, { "no-acpi", 0, QEMU_OPTION_no_acpi }, { "no-reboot", 0, QEMU_OPTION_no_reboot }, + { "show-cursor", 0, QEMU_OPTION_show_cursor }, { "daemonize", 0, QEMU_OPTION_daemonize }, { "option-rom", HAS_ARG, QEMU_OPTION_option_rom }, -#if defined(TARGET_ARM) +#if defined(TARGET_ARM) || defined(TARGET_M68K) { "semihosting", 0, QEMU_OPTION_semihosting }, #endif + { "name", HAS_ARG, QEMU_OPTION_name }, +#if defined(TARGET_SPARC) + { "prom-env", HAS_ARG, QEMU_OPTION_prom_env }, +#endif +#if defined(TARGET_ARM) + { "old-param", 0, QEMU_OPTION_old_param }, +#endif + { "clock", HAS_ARG, QEMU_OPTION_clock }, { NULL }, }; @@ -6658,6 +7304,24 @@ static uint8_t *signal_stack; /* password input */ +int qemu_key_check(BlockDriverState *bs, const char *name) +{ + char password[256]; + int i; + + if (!bdrv_is_encrypted(bs)) + return 0; + + term_printf("%s is encrypted.\n", name); + for(i = 0; i < 3; i++) { + monitor_readline("Password: ", 1, password, sizeof(password)); + if (bdrv_set_key(bs, password) == 0) + return 0; + term_printf("invalid password\n"); + } + return -EPERM; +} + static BlockDriverState *get_bdrv(int index) { BlockDriverState *bs; @@ -6675,21 +7339,12 @@ static BlockDriverState *get_bdrv(int index) static void read_passwords(void) { BlockDriverState *bs; - int i, j; - char password[256]; + int i; for(i = 0; i < 6; i++) { bs = get_bdrv(i); - if (bs && bdrv_is_encrypted(bs)) { - term_printf("%s is encrypted.\n", bdrv_get_device_name(bs)); - for(j = 0; j < 3; j++) { - monitor_readline("Password: ", - 1, password, sizeof(password)); - if (bdrv_set_key(bs, password) == 0) - break; - term_printf("invalid password\n"); - } - } + if (bs) + qemu_key_check(bs, bdrv_get_device_name(bs)); } } @@ -6703,22 +7358,37 @@ void register_machines(void) qemu_register_machine(&heathrow_machine); qemu_register_machine(&core99_machine); qemu_register_machine(&prep_machine); + qemu_register_machine(&ref405ep_machine); + qemu_register_machine(&taihu_machine); #elif defined(TARGET_MIPS) qemu_register_machine(&mips_machine); qemu_register_machine(&mips_malta_machine); + qemu_register_machine(&mips_pica61_machine); #elif defined(TARGET_SPARC) #ifdef TARGET_SPARC64 qemu_register_machine(&sun4u_machine); #else - qemu_register_machine(&sun4m_machine); + qemu_register_machine(&ss5_machine); + qemu_register_machine(&ss10_machine); #endif #elif defined(TARGET_ARM) qemu_register_machine(&integratorcp_machine); qemu_register_machine(&versatilepb_machine); qemu_register_machine(&versatileab_machine); qemu_register_machine(&realview_machine); + qemu_register_machine(&akitapda_machine); + qemu_register_machine(&spitzpda_machine); + qemu_register_machine(&borzoipda_machine); + qemu_register_machine(&terrierpda_machine); + qemu_register_machine(&palmte_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); #else #error unsupported CPU #endif @@ -6726,6 +7396,7 @@ void register_machines(void) #ifdef HAS_AUDIO struct soundhw soundhw[] = { +#ifdef HAS_AUDIO_CHOICE #ifdef TARGET_I386 { "pcspk", @@ -6774,6 +7445,7 @@ struct soundhw soundhw[] = { 0, { .init_pci = es1370_init } }, +#endif { NULL, NULL, 0, 0, { NULL } } }; @@ -6853,10 +7525,13 @@ int main(int argc, char **argv) int use_gdbstub; const char *gdbstub_port; #endif - int i, cdrom_index; + int i, cdrom_index, pflash_index; int snapshot, linux_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; DisplayState *ds = &display_state; int cyls, heads, secs, translation; @@ -6876,6 +7551,8 @@ int main(int argc, char **argv) char usb_devices[MAX_USB_CMDLINE][128]; int usb_devices_index; int fds[2]; + const char *pid_file = NULL; + VLANState *vlan; LIST_INIT (&vm_change_state_head); #ifndef _WIN32 @@ -6916,6 +7593,11 @@ int main(int argc, char **argv) fd_filename[i] = NULL; for(i = 0; i < MAX_DISKS; i++) hd_filename[i] = NULL; + for(i = 0; i < MAX_PFLASH; i++) + pflash_filename[i] = NULL; + pflash_index = 0; + sd_filename = NULL; + mtd_filename = NULL; ram_size = DEFAULT_RAM_SIZE * 1024 * 1024; vga_ram_size = VGA_RAM_SIZE; #ifdef CONFIG_GDBSTUB @@ -6939,19 +7621,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) @@ -6969,7 +7651,7 @@ int main(int argc, char **argv) popt = qemu_options; for(;;) { if (!popt->name) { - fprintf(stderr, "%s: invalid option -- '%s'\n", + fprintf(stderr, "%s: invalid option -- '%s'\n", argv[0], r); exit(1); } @@ -6996,21 +7678,25 @@ int main(int argc, char **argv) printf("Supported machines are:\n"); for(m = first_machine; m != NULL; m = m->next) { printf("%-10s %s%s\n", - m->name, m->desc, + m->name, m->desc, m == first_machine ? " (default)" : ""); } - exit(1); + exit(*optarg != '?'); } break; case QEMU_OPTION_cpu: /* hw initialization will check this */ - if (optarg[0] == '?') { + 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); #endif - exit(1); + exit(0); } else { cpu_model = optarg; } @@ -7030,6 +7716,19 @@ int main(int argc, char **argv) cdrom_index = -1; } break; + case QEMU_OPTION_mtdblock: + mtd_filename = optarg; + break; + case QEMU_OPTION_sd: + sd_filename = optarg; + break; + case QEMU_OPTION_pflash: + if (pflash_index >= MAX_PFLASH) { + fprintf(stderr, "qemu: too many parallel flash images\n"); + exit(1); + } + pflash_filename[pflash_index++] = optarg; + break; case QEMU_OPTION_snapshot: snapshot = 1; break; @@ -7071,9 +7770,13 @@ int main(int argc, char **argv) break; case QEMU_OPTION_nographic: pstrcpy(serial_devices[0], sizeof(serial_devices[0]), "stdio"); + pstrcpy(parallel_devices[0], sizeof(parallel_devices[0]), "null"); pstrcpy(monitor_device, sizeof(monitor_device), "stdio"); nographic = 1; break; + case QEMU_OPTION_portrait: + graphic_rotate = 1; + break; case QEMU_OPTION_kernel: kernel_filename = optarg; break; @@ -7087,7 +7790,7 @@ int main(int argc, char **argv) break; case QEMU_OPTION_boot: boot_device = optarg[0]; - if (boot_device != 'a' && + if (boot_device != 'a' && #if defined(TARGET_SPARC) || defined(TARGET_I386) // Network boot boot_device != 'n' && @@ -7134,7 +7837,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 @@ -7147,12 +7850,12 @@ int main(int argc, char **argv) break; #endif case QEMU_OPTION_h: - help(); + help(0); break; case QEMU_OPTION_m: ram_size = atoi(optarg) * 1024 * 1024; if (ram_size <= 0) - help(); + help(1); if (ram_size > PHYS_RAM_MAX_SIZE) { fprintf(stderr, "qemu: at most %d MB RAM can be simulated\n", PHYS_RAM_MAX_SIZE / (1024 * 1024)); @@ -7163,7 +7866,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"); @@ -7197,9 +7900,15 @@ int main(int argc, char **argv) break; case QEMU_OPTION_cirrusvga: cirrus_vga_enabled = 1; + vmsvga_enabled = 0; + break; + case QEMU_OPTION_vmsvga: + cirrus_vga_enabled = 0; + vmsvga_enabled = 1; break; case QEMU_OPTION_std_vga: cirrus_vga_enabled = 0; + vmsvga_enabled = 0; break; case QEMU_OPTION_g: { @@ -7221,7 +7930,7 @@ int main(int argc, char **argv) if (*p == 'x') { p++; depth = strtol(p, (char **)&p, 10); - if (depth != 8 && depth != 15 && depth != 16 && + if (depth != 8 && depth != 15 && depth != 16 && depth != 24 && depth != 32) goto graphic_error; } else if (*p == '\0') { @@ -7229,7 +7938,7 @@ int main(int argc, char **argv) } else { goto graphic_error; } - + graphic_width = w; graphic_height = h; graphic_depth = depth; @@ -7251,7 +7960,7 @@ int main(int argc, char **argv) fprintf(stderr, "qemu: too many serial ports\n"); exit(1); } - pstrcpy(serial_devices[serial_device_index], + pstrcpy(serial_devices[serial_device_index], sizeof(serial_devices[0]), optarg); serial_device_index++; break; @@ -7260,7 +7969,7 @@ int main(int argc, char **argv) fprintf(stderr, "qemu: too many parallel ports\n"); exit(1); } - pstrcpy(parallel_devices[parallel_device_index], + pstrcpy(parallel_devices[parallel_device_index], sizeof(parallel_devices[0]), optarg); parallel_device_index++; break; @@ -7274,12 +7983,15 @@ int main(int argc, char **argv) case QEMU_OPTION_no_frame: no_frame = 1; break; + case QEMU_OPTION_alt_grab: + alt_grab = 1; + break; case QEMU_OPTION_no_quit: no_quit = 1; break; #endif case QEMU_OPTION_pidfile: - create_pidfile(optarg); + pid_file = optarg; break; #ifdef TARGET_I386 case QEMU_OPTION_win2k_hack: @@ -7324,6 +8036,9 @@ int main(int argc, char **argv) case QEMU_OPTION_no_reboot: no_reboot = 1; break; + case QEMU_OPTION_show_cursor: + cursor_hide = 0; + break; case QEMU_OPTION_daemonize: daemonize = 1; break; @@ -7338,6 +8053,26 @@ int main(int argc, char **argv) case QEMU_OPTION_semihosting: semihosting_enabled = 1; break; + case QEMU_OPTION_name: + qemu_name = optarg; + break; +#ifdef TARGET_SPARC + case QEMU_OPTION_prom_env: + if (nb_prom_envs >= MAX_PROM_ENVS) { + fprintf(stderr, "Too many prom variables\n"); + exit(1); + } + prom_envs[nb_prom_envs] = optarg; + nb_prom_envs++; + break; +#endif +#ifdef TARGET_ARM + case QEMU_OPTION_old_param: + old_param = 1; +#endif + case QEMU_OPTION_clock: + configure_alarms(optarg); + break; } } } @@ -7362,16 +8097,19 @@ int main(int argc, char **argv) close(fds[1]); again: - len = read(fds[0], &status, 1); - if (len == -1 && (errno == EINTR)) - goto again; - - if (len != 1 || status != 0) - exit(1); - else - exit(0); + len = read(fds[0], &status, 1); + if (len == -1 && (errno == EINTR)) + goto again; + + if (len != 1) + exit(1); + else if (status == 1) { + fprintf(stderr, "Could not acquire pidfile\n"); + exit(1); + } else + exit(0); } else if (pid < 0) - exit(1); + exit(1); setsid(); @@ -7390,6 +8128,15 @@ int main(int argc, char **argv) } #endif + if (pid_file && qemu_create_pidfile(pid_file) != 0) { + if (daemonize) { + uint8_t status = 1; + write(fds[1], &status, 1); + } else + fprintf(stderr, "Could not acquire pid file\n"); + exit(1); + } + #ifdef USE_KQEMU if (smp_cpus > 1) kqemu_allowed = 0; @@ -7398,10 +8145,10 @@ int main(int argc, char **argv) if (!linux_boot && boot_device != 'n' && - hd_filename[0] == '\0' && + hd_filename[0] == '\0' && (cdrom_index >= 0 && hd_filename[cdrom_index] == '\0') && fd_filename[0] == '\0') - help(); + help(1); /* boot to floppy or the default cd if no hard disk defined yet */ if (hd_filename[0] == '\0' && boot_device == 'c') { @@ -7412,7 +8159,7 @@ int main(int argc, char **argv) } setvbuf(stdout, NULL, _IOLBF, 0); - + init_timers(); init_timer_alarm(); qemu_aio_init(); @@ -7435,6 +8182,18 @@ int main(int argc, char **argv) if (net_client_init(net_clients[i]) < 0) exit(1); } + for(vlan = first_vlan; vlan != NULL; vlan = vlan->next) { + if (vlan->nb_guest_devs == 0 && vlan->nb_host_devs == 0) + continue; + if (vlan->nb_guest_devs == 0) { + fprintf(stderr, "Invalid vlan (%d) with no nics\n", vlan->id); + exit(1); + } + if (vlan->nb_host_devs == 0) + fprintf(stderr, + "Warning: vlan %d is not connected to host network\n", + vlan->id); + } #ifdef TARGET_I386 if (boot_device == 'n') { @@ -7454,7 +8213,6 @@ int main(int argc, char **argv) fprintf(stderr, "No valid PXE rom found for network device\n"); exit(1); } - boot_device = 'c'; /* to prevent confusion by the BIOS */ } #endif @@ -7506,7 +8264,7 @@ int main(int argc, char **argv) fd_table[i] = bdrv_new(buf); bdrv_set_type_hint(fd_table[i], BDRV_TYPE_FLOPPY); } - if (fd_filename[i] != '\0') { + if (fd_filename[i][0] != '\0') { if (bdrv_open(fd_table[i], fd_filename[i], snapshot ? BDRV_O_SNAPSHOT : 0) < 0) { fprintf(stderr, "qemu: could not open floppy disk image '%s'\n", @@ -7517,23 +8275,67 @@ int main(int argc, char **argv) } } + /* Open the virtual parallel flash block devices */ + for(i = 0; i < MAX_PFLASH; i++) { + if (pflash_filename[i]) { + if (!pflash_table[i]) { + char buf[64]; + snprintf(buf, sizeof(buf), "fl%c", i + 'a'); + pflash_table[i] = bdrv_new(buf); + } + if (bdrv_open(pflash_table[i], pflash_filename[i], + snapshot ? BDRV_O_SNAPSHOT : 0) < 0) { + fprintf(stderr, "qemu: could not open flash image '%s'\n", + pflash_filename[i]); + exit(1); + } + } + } + + sd_bdrv = bdrv_new ("sd"); + /* FIXME: This isn't really a floppy, but it's a reasonable + approximation. */ + bdrv_set_type_hint(sd_bdrv, BDRV_TYPE_FLOPPY); + if (sd_filename) { + if (bdrv_open(sd_bdrv, sd_filename, + snapshot ? BDRV_O_SNAPSHOT : 0) < 0) { + fprintf(stderr, "qemu: could not open SD card image %s\n", + sd_filename); + } else + qemu_key_check(sd_bdrv, sd_filename); + } + + if (mtd_filename) { + mtd_bdrv = bdrv_new ("mtd"); + if (bdrv_open(mtd_bdrv, mtd_filename, + snapshot ? BDRV_O_SNAPSHOT : 0) < 0 || + qemu_key_check(mtd_bdrv, mtd_filename)) { + fprintf(stderr, "qemu: could not open Flash image %s\n", + mtd_filename); + bdrv_delete(mtd_bdrv); + mtd_bdrv = 0; + } + } + register_savevm("timer", 0, 2, timer_save, timer_load, NULL); register_savevm("ram", 0, 2, ram_save, ram_load, NULL); init_ioports(); /* terminal init */ + memset(&display_state, 0, sizeof(display_state)); if (nographic) { + /* nearly nothing to do */ dumb_display_init(ds); } else if (vnc_display != NULL) { - vnc_display_init(ds, vnc_display); + vnc_display_init(ds); + if (vnc_display_open(ds, vnc_display) < 0) + exit(1); } else { #if defined(CONFIG_SDL) sdl_display_init(ds, full_screen, no_frame); #elif defined(CONFIG_COCOA) cocoa_display_init(ds, full_screen); -#else - dumb_display_init(ds); #endif } @@ -7564,11 +8366,11 @@ int main(int argc, char **argv) if (devname[0] != '\0' && strcmp(devname, "none")) { serial_hds[i] = qemu_chr_open(devname); if (!serial_hds[i]) { - fprintf(stderr, "qemu: could not open serial device '%s'\n", + fprintf(stderr, "qemu: could not open serial device '%s'\n", devname); exit(1); } - if (!strcmp(devname, "vc")) + if (strstart(devname, "vc", 0)) qemu_chr_printf(serial_hds[i], "serial%d console\r\n", i); } } @@ -7578,11 +8380,11 @@ int main(int argc, char **argv) if (devname[0] != '\0' && strcmp(devname, "none")) { parallel_hds[i] = qemu_chr_open(devname); if (!parallel_hds[i]) { - fprintf(stderr, "qemu: could not open parallel device '%s'\n", + fprintf(stderr, "qemu: could not open parallel device '%s'\n", devname); exit(1); } - if (!strcmp(devname, "vc")) + if (strstart(devname, "vc", 0)) qemu_chr_printf(parallel_hds[i], "parallel%d console\r\n", i); } } @@ -7601,8 +8403,10 @@ int main(int argc, char **argv) } } - gui_timer = qemu_new_timer(rt_clock, gui_update, NULL); - qemu_mod_timer(gui_timer, qemu_get_clock(rt_clock)); + if (display_state.dpy_refresh) { + display_state.gui_timer = qemu_new_timer(rt_clock, gui_update, &display_state); + qemu_mod_timer(display_state.gui_timer, qemu_get_clock(rt_clock)); + } #ifdef CONFIG_GDBSTUB if (use_gdbstub) { @@ -7613,8 +8417,9 @@ int main(int argc, char **argv) gdbstub_port); exit(1); } - } else + } #endif + if (loadvm) do_loadvm(loadvm); @@ -7639,7 +8444,7 @@ int main(int argc, char **argv) if (len != 1) exit(1); - fd = open("/dev/null", O_RDWR); + TFR(fd = open("/dev/null", O_RDWR)); if (fd == -1) exit(1);