blob: 97c3aa3ce9a9c3d102cc151002124d97e4e825bf [file] [log] [blame]
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001/*
2 * QEMU System Emulator
3 *
4 * Copyright (c) 2003-2008 Fabrice Bellard
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080024#include <unistd.h>
25#include <fcntl.h>
26#include <signal.h>
27#include <time.h>
28#include <errno.h>
29#include <sys/time.h>
30#include <zlib.h>
31
David 'Digit' Turner2c538c82010-05-10 16:48:20 -070032/* Needed early for CONFIG_BSD etc. */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070033#include "config-host.h"
34
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080035#ifndef _WIN32
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070036#include <libgen.h>
37#include <pwd.h>
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080038#include <sys/times.h>
39#include <sys/wait.h>
40#include <termios.h>
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080041#include <sys/mman.h>
42#include <sys/ioctl.h>
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070043#include <sys/resource.h>
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080044#include <sys/socket.h>
45#include <netinet/in.h>
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070046#include <net/if.h>
47#if defined(__NetBSD__)
48#include <net/if_tap.h>
49#endif
50#ifdef __linux__
51#include <linux/if_tun.h>
52#endif
53#include <arpa/inet.h>
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080054#include <dirent.h>
55#include <netdb.h>
56#include <sys/select.h>
David 'Digit' Turner2c538c82010-05-10 16:48:20 -070057#ifdef CONFIG_BSD
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080058#include <sys/stat.h>
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070059#if defined(__FreeBSD__) || defined(__DragonFly__)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080060#include <libutil.h>
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070061#else
62#include <util.h>
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080063#endif
64#elif defined (__GLIBC__) && defined (__FreeBSD_kernel__)
65#include <freebsd/stdlib.h>
66#else
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070067#ifdef __linux__
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080068#include <pty.h>
69#include <malloc.h>
70#include <linux/rtc.h>
71
72/* For the benefit of older linux systems which don't supply it,
73 we use a local copy of hpet.h. */
74/* #include <linux/hpet.h> */
75#include "hpet.h"
76
77#include <linux/ppdev.h>
78#include <linux/parport.h>
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070079#endif
80#ifdef __sun__
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080081#include <sys/stat.h>
82#include <sys/ethernet.h>
83#include <sys/sockio.h>
84#include <netinet/arp.h>
85#include <netinet/in.h>
86#include <netinet/in_systm.h>
87#include <netinet/ip.h>
88#include <netinet/ip_icmp.h> // must come after ip.h
89#include <netinet/udp.h>
90#include <netinet/tcp.h>
91#include <net/if.h>
92#include <syslog.h>
93#include <stropts.h>
94#endif
95#endif
96#endif
97
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080098#if defined(__OpenBSD__)
99#include <util.h>
100#endif
101
102#if defined(CONFIG_VDE)
103#include <libvdeplug.h>
104#endif
105
106#ifdef _WIN32
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700107#include <windows.h>
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800108#include <malloc.h>
109#include <sys/timeb.h>
110#include <mmsystem.h>
111#define getopt_long_only getopt_long
112#define memalign(align, size) malloc(size)
113#endif
114
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700115#ifdef CONFIG_SDL
116#ifdef __APPLE__
117#include <SDL.h>
118int qemu_main(int argc, char **argv, char **envp);
119int main(int argc, char **argv)
120{
121 qemu_main(argc, argv, NULL);
122}
123#undef main
124#define main qemu_main
125#endif
126#endif /* CONFIG_SDL */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800127
128#ifdef CONFIG_COCOA
129#undef main
130#define main qemu_main
131#endif /* CONFIG_COCOA */
132
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700133#include "hw/hw.h"
134#include "hw/boards.h"
135#include "hw/usb.h"
136#include "hw/pcmcia.h"
137#include "hw/pc.h"
138#include "hw/audiodev.h"
139#include "hw/isa.h"
140#include "hw/baum.h"
141#include "hw/bt.h"
142#include "hw/watchdog.h"
143#include "hw/smbios.h"
144#include "hw/xen.h"
145#include "bt-host.h"
146#include "net.h"
147#include "monitor.h"
148#include "console.h"
149#include "sysemu.h"
150#include "gdbstub.h"
151#include "qemu-timer.h"
152#include "qemu-char.h"
153#include "cache-utils.h"
154#include "block.h"
155#include "dma.h"
156#include "audio/audio.h"
157#include "migration.h"
158#include "kvm.h"
159#include "balloon.h"
160#include "qemu-option.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800161
162#include "disas.h"
163
164#include "exec-all.h"
165
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700166#include "qemu_socket.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800167
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700168#if defined(CONFIG_SLIRP)
169#include "libslirp.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800170#endif
171
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800172
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700173
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700174#define DEFAULT_RAM_SIZE 128
175
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800176/* Max number of USB devices that can be specified on the commandline. */
177#define MAX_USB_CMDLINE 8
178
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700179/* Max number of bluetooth switches on the commandline. */
180#define MAX_BT_CMDLINE 10
181
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800182/* XXX: use a two level table to limit memory usage */
183#define MAX_IOPORTS 65536
184
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700185static const char *data_dir;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800186const char *bios_name = NULL;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700187static void *ioport_opaque[MAX_IOPORTS];
188static IOPortReadFunc *ioport_read_table[3][MAX_IOPORTS];
189static IOPortWriteFunc *ioport_write_table[3][MAX_IOPORTS];
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800190/* Note: drives_table[MAX_DRIVES] is a dummy block driver if none available
191 to store the VM snapshots */
192DriveInfo drives_table[MAX_DRIVES+1];
193int nb_drives;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700194enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB;
195static DisplayState *display_state;
196DisplayType display_type = DT_DEFAULT;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800197const char* keyboard_layout = NULL;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800198ram_addr_t ram_size;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800199int nb_nics;
200NICInfo nd_table[MAX_NICS];
201int vm_running;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700202static int autostart;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800203static int rtc_utc = 1;
204static int rtc_date_offset = -1; /* -1 means no change */
205int cirrus_vga_enabled = 1;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700206int std_vga_enabled = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800207int vmsvga_enabled = 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700208int xenfb_enabled = 0;
David 'Digit' Turnera7fb77d2010-05-10 23:50:54 -0700209QEMUClock *rtc_clock;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800210#ifdef TARGET_SPARC
211int graphic_width = 1024;
212int graphic_height = 768;
213int graphic_depth = 8;
214#else
215int graphic_width = 800;
216int graphic_height = 600;
217int graphic_depth = 15;
218#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700219static int full_screen = 0;
220#ifdef CONFIG_SDL
221static int no_frame = 0;
222#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800223int no_quit = 0;
224CharDriverState *serial_hds[MAX_SERIAL_PORTS];
225CharDriverState *parallel_hds[MAX_PARALLEL_PORTS];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700226CharDriverState *virtcon_hds[MAX_VIRTIO_CONSOLES];
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800227#ifdef TARGET_I386
228int win2k_install_hack = 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700229int rtc_td_hack = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800230#endif
231int usb_enabled = 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700232int singlestep = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800233int smp_cpus = 1;
234const char *vnc_display;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800235int acpi_enabled = 1;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700236int no_hpet = 0;
237int no_virtio_balloon = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800238int fd_bootchk = 1;
239int no_reboot = 0;
240int no_shutdown = 0;
241int cursor_hide = 1;
242int graphic_rotate = 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700243#ifndef _WIN32
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800244int daemonize = 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700245#endif
246WatchdogTimerModel *watchdog = NULL;
247int watchdog_action = WDT_RESET;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800248const char *option_rom[MAX_OPTION_ROMS];
249int nb_option_roms;
250int semihosting_enabled = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800251#ifdef TARGET_ARM
252int old_param = 0;
253#endif
254const char *qemu_name;
255int alt_grab = 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700256#if defined(TARGET_SPARC) || defined(TARGET_PPC)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800257unsigned int nb_prom_envs = 0;
258const char *prom_envs[MAX_PROM_ENVS];
259#endif
260int nb_drives_opt;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700261struct drive_opt drives_opt[MAX_DRIVES];
262
263int nb_numa_nodes;
264uint64_t node_mem[MAX_NODES];
265uint64_t node_cpumask[MAX_NODES];
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800266
267static CPUState *cur_cpu;
268static CPUState *next_cpu;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700269static int timer_alarm_pending = 1;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700270static QEMUTimer *nographic_timer;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800271
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700272uint8_t qemu_uuid[16];
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800273
274/***********************************************************/
275/* x86 ISA bus support */
276
277target_phys_addr_t isa_mem_base = 0;
278PicState2 *isa_pic;
279
280static IOPortReadFunc default_ioport_readb, default_ioport_readw, default_ioport_readl;
281static IOPortWriteFunc default_ioport_writeb, default_ioport_writew, default_ioport_writel;
282
283static uint32_t ioport_read(int index, uint32_t address)
284{
285 static IOPortReadFunc *default_func[3] = {
286 default_ioport_readb,
287 default_ioport_readw,
288 default_ioport_readl
289 };
290 IOPortReadFunc *func = ioport_read_table[index][address];
291 if (!func)
292 func = default_func[index];
293 return func(ioport_opaque[address], address);
294}
295
296static void ioport_write(int index, uint32_t address, uint32_t data)
297{
298 static IOPortWriteFunc *default_func[3] = {
299 default_ioport_writeb,
300 default_ioport_writew,
301 default_ioport_writel
302 };
303 IOPortWriteFunc *func = ioport_write_table[index][address];
304 if (!func)
305 func = default_func[index];
306 func(ioport_opaque[address], address, data);
307}
308
309static uint32_t default_ioport_readb(void *opaque, uint32_t address)
310{
311#ifdef DEBUG_UNUSED_IOPORT
312 fprintf(stderr, "unused inb: port=0x%04x\n", address);
313#endif
314 return 0xff;
315}
316
317static void default_ioport_writeb(void *opaque, uint32_t address, uint32_t data)
318{
319#ifdef DEBUG_UNUSED_IOPORT
320 fprintf(stderr, "unused outb: port=0x%04x data=0x%02x\n", address, data);
321#endif
322}
323
324/* default is to make two byte accesses */
325static uint32_t default_ioport_readw(void *opaque, uint32_t address)
326{
327 uint32_t data;
328 data = ioport_read(0, address);
329 address = (address + 1) & (MAX_IOPORTS - 1);
330 data |= ioport_read(0, address) << 8;
331 return data;
332}
333
334static void default_ioport_writew(void *opaque, uint32_t address, uint32_t data)
335{
336 ioport_write(0, address, data & 0xff);
337 address = (address + 1) & (MAX_IOPORTS - 1);
338 ioport_write(0, address, (data >> 8) & 0xff);
339}
340
341static uint32_t default_ioport_readl(void *opaque, uint32_t address)
342{
343#ifdef DEBUG_UNUSED_IOPORT
344 fprintf(stderr, "unused inl: port=0x%04x\n", address);
345#endif
346 return 0xffffffff;
347}
348
349static void default_ioport_writel(void *opaque, uint32_t address, uint32_t data)
350{
351#ifdef DEBUG_UNUSED_IOPORT
352 fprintf(stderr, "unused outl: port=0x%04x data=0x%02x\n", address, data);
353#endif
354}
355
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800356
357/***********************************************************/
358void hw_error(const char *fmt, ...)
359{
360 va_list ap;
361 CPUState *env;
362
363 va_start(ap, fmt);
364 fprintf(stderr, "qemu: hardware error: ");
365 vfprintf(stderr, fmt, ap);
366 fprintf(stderr, "\n");
367 for(env = first_cpu; env != NULL; env = env->next_cpu) {
368 fprintf(stderr, "CPU #%d:\n", env->cpu_index);
369#ifdef TARGET_I386
370 cpu_dump_state(env, stderr, fprintf, X86_DUMP_FPU);
371#else
372 cpu_dump_state(env, stderr, fprintf, 0);
373#endif
374 }
375 va_end(ap);
376 abort();
377}
David 'Digit' Turner707c8a82010-12-22 22:35:58 +0100378
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700379/***************/
380/* ballooning */
381
382static QEMUBalloonEvent *qemu_balloon_event;
383void *qemu_balloon_event_opaque;
384
385void qemu_add_balloon_handler(QEMUBalloonEvent *func, void *opaque)
386{
387 qemu_balloon_event = func;
388 qemu_balloon_event_opaque = opaque;
389}
390
391void qemu_balloon(ram_addr_t target)
392{
393 if (qemu_balloon_event)
394 qemu_balloon_event(qemu_balloon_event_opaque, target);
395}
396
397ram_addr_t qemu_balloon_status(void)
398{
399 if (qemu_balloon_event)
400 return qemu_balloon_event(qemu_balloon_event_opaque, 0);
401 return 0;
402}
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800403
404/***********************************************************/
David 'Digit' Turnera7fb77d2010-05-10 23:50:54 -0700405/* real time host monotonic timer */
406
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800407/* compute with 96 bit intermediate result: (a*b)/c */
408uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
409{
410 union {
411 uint64_t ll;
412 struct {
David 'Digit' Turner20894ae2010-05-10 17:07:36 -0700413#ifdef HOST_WORDS_BIGENDIAN
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800414 uint32_t high, low;
415#else
416 uint32_t low, high;
417#endif
418 } l;
419 } u, res;
420 uint64_t rl, rh;
421
422 u.ll = a;
423 rl = (uint64_t)u.l.low * (uint64_t)b;
424 rh = (uint64_t)u.l.high * (uint64_t)b;
425 rh += (rl >> 32);
426 res.l.high = rh / c;
427 res.l.low = (((rh % c) << 32) + (rl & 0xffffffff)) / c;
428 return res.ll;
429}
430
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800431/***********************************************************/
432/* host time/date access */
433void qemu_get_timedate(struct tm *tm, int offset)
434{
435 time_t ti;
436 struct tm *ret;
437
438 time(&ti);
439 ti += offset;
440 if (rtc_date_offset == -1) {
441 if (rtc_utc)
442 ret = gmtime(&ti);
443 else
444 ret = localtime(&ti);
445 } else {
446 ti -= rtc_date_offset;
447 ret = gmtime(&ti);
448 }
449
450 memcpy(tm, ret, sizeof(struct tm));
451}
452
453int qemu_timedate_diff(struct tm *tm)
454{
455 time_t seconds;
456
457 if (rtc_date_offset == -1)
458 if (rtc_utc)
459 seconds = mktimegm(tm);
460 else
461 seconds = mktime(tm);
462 else
463 seconds = mktimegm(tm) + rtc_date_offset;
464
465 return seconds - time(NULL);
466}
467
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800468#ifdef _WIN32
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700469static void socket_cleanup(void)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800470{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700471 WSACleanup();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800472}
473
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700474static int socket_init(void)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800475{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700476 WSADATA Data;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800477 int ret, err;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800478
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700479 ret = WSAStartup(MAKEWORD(2,2), &Data);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800480 if (ret != 0) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700481 err = WSAGetLastError();
482 fprintf(stderr, "WSAStartup: %d\n", err);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800483 return -1;
484 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700485 atexit(socket_cleanup);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800486 return 0;
487}
488#endif
489
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700490int get_param_value(char *buf, int buf_size,
491 const char *tag, const char *str)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800492{
493 const char *p;
494 char option[128];
495
496 p = str;
497 for(;;) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700498 p = get_opt_name(option, sizeof(option), p, '=');
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800499 if (*p != '=')
500 break;
501 p++;
502 if (!strcmp(tag, option)) {
503 (void)get_opt_value(buf, buf_size, p);
504 return strlen(buf);
505 } else {
506 p = get_opt_value(NULL, 0, p);
507 }
508 if (*p != ',')
509 break;
510 p++;
511 }
512 return 0;
513}
514
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700515int check_params(char *buf, int buf_size,
516 const char * const *params, const char *str)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800517{
518 const char *p;
519 int i;
520
521 p = str;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700522 while (*p != '\0') {
523 p = get_opt_name(buf, buf_size, p, '=');
524 if (*p != '=') {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800525 return -1;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700526 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800527 p++;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700528 for (i = 0; params[i] != NULL; i++) {
529 if (!strcmp(params[i], buf)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800530 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700531 }
532 }
533 if (params[i] == NULL) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800534 return -1;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700535 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800536 p = get_opt_value(NULL, 0, p);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700537 if (*p != ',') {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800538 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700539 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800540 p++;
541 }
542 return 0;
543}
544
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700545/***********************************************************/
546/* Bluetooth support */
547static int nb_hcis;
548static int cur_hci;
549static struct HCIInfo *hci_table[MAX_NICS];
550
551static struct bt_vlan_s {
552 struct bt_scatternet_s net;
553 int id;
554 struct bt_vlan_s *next;
555} *first_bt_vlan;
556
557/* find or alloc a new bluetooth "VLAN" */
558static struct bt_scatternet_s *qemu_find_bt_vlan(int id)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800559{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700560 struct bt_vlan_s **pvlan, *vlan;
561 for (vlan = first_bt_vlan; vlan != NULL; vlan = vlan->next) {
562 if (vlan->id == id)
563 return &vlan->net;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800564 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700565 vlan = qemu_mallocz(sizeof(struct bt_vlan_s));
566 vlan->id = id;
567 pvlan = &first_bt_vlan;
568 while (*pvlan != NULL)
569 pvlan = &(*pvlan)->next;
570 *pvlan = vlan;
571 return &vlan->net;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800572}
573
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700574static void null_hci_send(struct HCIInfo *hci, const uint8_t *data, int len)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800575{
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800576}
577
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700578static int null_hci_addr_set(struct HCIInfo *hci, const uint8_t *bd_addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800579{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700580 return -ENOTSUP;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800581}
582
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700583static struct HCIInfo null_hci = {
584 .cmd_send = null_hci_send,
585 .sco_send = null_hci_send,
586 .acl_send = null_hci_send,
587 .bdaddr_set = null_hci_addr_set,
588};
589
590struct HCIInfo *qemu_next_hci(void)
591{
592 if (cur_hci == nb_hcis)
593 return &null_hci;
594
595 return hci_table[cur_hci++];
596}
597
598static struct HCIInfo *hci_init(const char *str)
599{
600 char *endp;
601 struct bt_scatternet_s *vlan = 0;
602
603 if (!strcmp(str, "null"))
604 /* null */
605 return &null_hci;
606 else if (!strncmp(str, "host", 4) && (str[4] == '\0' || str[4] == ':'))
607 /* host[:hciN] */
608 return bt_host_hci(str[4] ? str + 5 : "hci0");
609 else if (!strncmp(str, "hci", 3)) {
610 /* hci[,vlan=n] */
611 if (str[3]) {
612 if (!strncmp(str + 3, ",vlan=", 6)) {
613 vlan = qemu_find_bt_vlan(strtol(str + 9, &endp, 0));
614 if (*endp)
615 vlan = 0;
616 }
617 } else
618 vlan = qemu_find_bt_vlan(0);
619 if (vlan)
620 return bt_new_hci(vlan);
621 }
622
623 fprintf(stderr, "qemu: Unknown bluetooth HCI `%s'.\n", str);
624
625 return 0;
626}
627
628static int bt_hci_parse(const char *str)
629{
630 struct HCIInfo *hci;
631 bdaddr_t bdaddr;
632
633 if (nb_hcis >= MAX_NICS) {
634 fprintf(stderr, "qemu: Too many bluetooth HCIs (max %i).\n", MAX_NICS);
635 return -1;
636 }
637
638 hci = hci_init(str);
639 if (!hci)
640 return -1;
641
642 bdaddr.b[0] = 0x52;
643 bdaddr.b[1] = 0x54;
644 bdaddr.b[2] = 0x00;
645 bdaddr.b[3] = 0x12;
646 bdaddr.b[4] = 0x34;
647 bdaddr.b[5] = 0x56 + nb_hcis;
648 hci->bdaddr_set(hci, bdaddr.b);
649
650 hci_table[nb_hcis++] = hci;
651
652 return 0;
653}
654
655static void bt_vhci_add(int vlan_id)
656{
657 struct bt_scatternet_s *vlan = qemu_find_bt_vlan(vlan_id);
658
659 if (!vlan->slave)
660 fprintf(stderr, "qemu: warning: adding a VHCI to "
661 "an empty scatternet %i\n", vlan_id);
662
663 bt_vhci_init(bt_new_hci(vlan));
664}
665
666static struct bt_device_s *bt_device_add(const char *opt)
667{
668 struct bt_scatternet_s *vlan;
669 int vlan_id = 0;
670 char *endp = strstr(opt, ",vlan=");
671 int len = (endp ? endp - opt : strlen(opt)) + 1;
672 char devname[10];
673
674 pstrcpy(devname, MIN(sizeof(devname), len), opt);
675
676 if (endp) {
677 vlan_id = strtol(endp + 6, &endp, 0);
678 if (*endp) {
679 fprintf(stderr, "qemu: unrecognised bluetooth vlan Id\n");
680 return 0;
681 }
682 }
683
684 vlan = qemu_find_bt_vlan(vlan_id);
685
686 if (!vlan->slave)
687 fprintf(stderr, "qemu: warning: adding a slave device to "
688 "an empty scatternet %i\n", vlan_id);
689
690 if (!strcmp(devname, "keyboard"))
691 return bt_keyboard_init(vlan);
692
693 fprintf(stderr, "qemu: unsupported bluetooth device `%s'\n", devname);
694 return 0;
695}
696
697static int bt_parse(const char *opt)
698{
699 const char *endp, *p;
700 int vlan;
701
702 if (strstart(opt, "hci", &endp)) {
703 if (!*endp || *endp == ',') {
704 if (*endp)
705 if (!strstart(endp, ",vlan=", 0))
706 opt = endp + 1;
707
708 return bt_hci_parse(opt);
709 }
710 } else if (strstart(opt, "vhci", &endp)) {
711 if (!*endp || *endp == ',') {
712 if (*endp) {
713 if (strstart(endp, ",vlan=", &p)) {
714 vlan = strtol(p, (char **) &endp, 0);
715 if (*endp) {
716 fprintf(stderr, "qemu: bad scatternet '%s'\n", p);
717 return 1;
718 }
719 } else {
720 fprintf(stderr, "qemu: bad parameter '%s'\n", endp + 1);
721 return 1;
722 }
723 } else
724 vlan = 0;
725
726 bt_vhci_add(vlan);
727 return 0;
728 }
729 } else if (strstart(opt, "device:", &endp))
730 return !bt_device_add(endp);
731
732 fprintf(stderr, "qemu: bad bluetooth parameter '%s'\n", opt);
733 return 1;
734}
735
736/***********************************************************/
737/* QEMU Block devices */
738
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800739#define HD_ALIAS "index=%d,media=disk"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800740#define CDROM_ALIAS "index=2,media=cdrom"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800741#define FD_ALIAS "index=%d,if=floppy"
742#define PFLASH_ALIAS "if=pflash"
743#define MTD_ALIAS "if=mtd"
744#define SD_ALIAS "index=0,if=sd"
745
David 'Digit' Turnercb42a1b2010-12-23 02:54:08 +0100746static int drive_init_func(QemuOpts *opts, void *opaque)
747{
748 int *use_scsi = opaque;
749 int fatal_error = 0;
750
751 if (drive_init(opts, *use_scsi, &fatal_error) == NULL) {
752 if (fatal_error)
753 return 1;
754 }
755 return 0;
756}
757
758static int drive_enable_snapshot(QemuOpts *opts, void *opaque)
759{
760 if (NULL == qemu_opt_get(opts, "snapshot")) {
761 qemu_opt_set(opts, "snapshot", "on");
762 }
763 return 0;
764}
765
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700766static int drive_opt_get_free_idx(void)
767{
768 int index;
769
770 for (index = 0; index < MAX_DRIVES; index++)
771 if (!drives_opt[index].used) {
772 drives_opt[index].used = 1;
773 return index;
774 }
775
776 return -1;
777}
778
779static int drive_get_free_idx(void)
780{
781 int index;
782
783 for (index = 0; index < MAX_DRIVES; index++)
784 if (!drives_table[index].used) {
785 drives_table[index].used = 1;
786 return index;
787 }
788
789 return -1;
790}
791
792int drive_add(const char *file, const char *fmt, ...)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800793{
794 va_list ap;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700795 int index = drive_opt_get_free_idx();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800796
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700797 if (nb_drives_opt >= MAX_DRIVES || index == -1) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800798 fprintf(stderr, "qemu: too many drives\n");
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700799 return -1;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800800 }
801
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700802 drives_opt[index].file = file;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800803 va_start(ap, fmt);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700804 vsnprintf(drives_opt[index].opt,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800805 sizeof(drives_opt[0].opt), fmt, ap);
806 va_end(ap);
807
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700808 nb_drives_opt++;
809 return index;
810}
811
812void drive_remove(int index)
813{
814 drives_opt[index].used = 0;
815 nb_drives_opt--;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800816}
817
818int drive_get_index(BlockInterfaceType type, int bus, int unit)
819{
820 int index;
821
822 /* seek interface, bus and unit */
823
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700824 for (index = 0; index < MAX_DRIVES; index++)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800825 if (drives_table[index].type == type &&
826 drives_table[index].bus == bus &&
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700827 drives_table[index].unit == unit &&
828 drives_table[index].used)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800829 return index;
830
831 return -1;
832}
833
834int drive_get_max_bus(BlockInterfaceType type)
835{
836 int max_bus;
837 int index;
838
839 max_bus = -1;
840 for (index = 0; index < nb_drives; index++) {
841 if(drives_table[index].type == type &&
842 drives_table[index].bus > max_bus)
843 max_bus = drives_table[index].bus;
844 }
845 return max_bus;
846}
847
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700848const char *drive_get_serial(BlockDriverState *bdrv)
849{
850 int index;
851
852 for (index = 0; index < nb_drives; index++)
853 if (drives_table[index].bdrv == bdrv)
854 return drives_table[index].serial;
855
856 return "\0";
857}
858
859BlockInterfaceErrorAction drive_get_onerror(BlockDriverState *bdrv)
860{
861 int index;
862
863 for (index = 0; index < nb_drives; index++)
864 if (drives_table[index].bdrv == bdrv)
865 return drives_table[index].onerror;
866
867 return BLOCK_ERR_STOP_ENOSPC;
868}
869
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800870static void bdrv_format_print(void *opaque, const char *name)
871{
872 fprintf(stderr, " %s", name);
873}
874
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700875void drive_uninit(BlockDriverState *bdrv)
876{
877 int i;
878
879 for (i = 0; i < MAX_DRIVES; i++)
880 if (drives_table[i].bdrv == bdrv) {
881 drives_table[i].bdrv = NULL;
882 drives_table[i].used = 0;
883 drive_remove(drives_table[i].drive_opt_idx);
884 nb_drives--;
885 break;
886 }
887}
888
889int drive_init(struct drive_opt *arg, int snapshot, void *opaque)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800890{
891 char buf[128];
892 char file[1024];
893 char devname[128];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700894 char serial[21];
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800895 const char *mediastr = "";
896 BlockInterfaceType type;
897 enum { MEDIA_DISK, MEDIA_CDROM } media;
898 int bus_id, unit_id;
899 int cyls, heads, secs, translation;
900 BlockDriverState *bdrv;
901 BlockDriver *drv = NULL;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700902 QEMUMachine *machine = opaque;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800903 int max_devs;
904 int index;
905 int cache;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700906 int bdrv_flags, onerror;
907 int drives_table_idx;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800908 char *str = arg->opt;
909 static const char * const params[] = { "bus", "unit", "if", "index",
910 "cyls", "heads", "secs", "trans",
911 "media", "snapshot", "file",
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700912 "cache", "format", "serial", "werror",
913 NULL };
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800914
915 if (check_params(buf, sizeof(buf), params, str) < 0) {
916 fprintf(stderr, "qemu: unknown parameter '%s' in '%s'\n",
917 buf, str);
918 return -1;
919 }
920
921 file[0] = 0;
922 cyls = heads = secs = 0;
923 bus_id = 0;
924 unit_id = -1;
925 translation = BIOS_ATA_TRANSLATION_AUTO;
926 index = -1;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700927 cache = 3;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800928
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700929 if (machine->use_scsi) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800930 type = IF_SCSI;
931 max_devs = MAX_SCSI_DEVS;
932 pstrcpy(devname, sizeof(devname), "scsi");
933 } else {
934 type = IF_IDE;
935 max_devs = MAX_IDE_DEVS;
936 pstrcpy(devname, sizeof(devname), "ide");
937 }
938 media = MEDIA_DISK;
939
940 /* extract parameters */
941
942 if (get_param_value(buf, sizeof(buf), "bus", str)) {
943 bus_id = strtol(buf, NULL, 0);
944 if (bus_id < 0) {
945 fprintf(stderr, "qemu: '%s' invalid bus id\n", str);
946 return -1;
947 }
948 }
949
950 if (get_param_value(buf, sizeof(buf), "unit", str)) {
951 unit_id = strtol(buf, NULL, 0);
952 if (unit_id < 0) {
953 fprintf(stderr, "qemu: '%s' invalid unit id\n", str);
954 return -1;
955 }
956 }
957
958 if (get_param_value(buf, sizeof(buf), "if", str)) {
959 pstrcpy(devname, sizeof(devname), buf);
960 if (!strcmp(buf, "ide")) {
961 type = IF_IDE;
962 max_devs = MAX_IDE_DEVS;
963 } else if (!strcmp(buf, "scsi")) {
964 type = IF_SCSI;
965 max_devs = MAX_SCSI_DEVS;
966 } else if (!strcmp(buf, "floppy")) {
967 type = IF_FLOPPY;
968 max_devs = 0;
969 } else if (!strcmp(buf, "pflash")) {
970 type = IF_PFLASH;
971 max_devs = 0;
972 } else if (!strcmp(buf, "mtd")) {
973 type = IF_MTD;
974 max_devs = 0;
975 } else if (!strcmp(buf, "sd")) {
976 type = IF_SD;
977 max_devs = 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700978 } else if (!strcmp(buf, "virtio")) {
979 type = IF_VIRTIO;
980 max_devs = 0;
981 } else if (!strcmp(buf, "xen")) {
982 type = IF_XEN;
983 max_devs = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800984 } else {
985 fprintf(stderr, "qemu: '%s' unsupported bus type '%s'\n", str, buf);
986 return -1;
987 }
988 }
989
990 if (get_param_value(buf, sizeof(buf), "index", str)) {
991 index = strtol(buf, NULL, 0);
992 if (index < 0) {
993 fprintf(stderr, "qemu: '%s' invalid index\n", str);
994 return -1;
995 }
996 }
997
998 if (get_param_value(buf, sizeof(buf), "cyls", str)) {
999 cyls = strtol(buf, NULL, 0);
1000 }
1001
1002 if (get_param_value(buf, sizeof(buf), "heads", str)) {
1003 heads = strtol(buf, NULL, 0);
1004 }
1005
1006 if (get_param_value(buf, sizeof(buf), "secs", str)) {
1007 secs = strtol(buf, NULL, 0);
1008 }
1009
1010 if (cyls || heads || secs) {
1011 if (cyls < 1 || cyls > 16383) {
1012 fprintf(stderr, "qemu: '%s' invalid physical cyls number\n", str);
1013 return -1;
1014 }
1015 if (heads < 1 || heads > 16) {
1016 fprintf(stderr, "qemu: '%s' invalid physical heads number\n", str);
1017 return -1;
1018 }
1019 if (secs < 1 || secs > 63) {
1020 fprintf(stderr, "qemu: '%s' invalid physical secs number\n", str);
1021 return -1;
1022 }
1023 }
1024
1025 if (get_param_value(buf, sizeof(buf), "trans", str)) {
1026 if (!cyls) {
1027 fprintf(stderr,
1028 "qemu: '%s' trans must be used with cyls,heads and secs\n",
1029 str);
1030 return -1;
1031 }
1032 if (!strcmp(buf, "none"))
1033 translation = BIOS_ATA_TRANSLATION_NONE;
1034 else if (!strcmp(buf, "lba"))
1035 translation = BIOS_ATA_TRANSLATION_LBA;
1036 else if (!strcmp(buf, "auto"))
1037 translation = BIOS_ATA_TRANSLATION_AUTO;
1038 else {
1039 fprintf(stderr, "qemu: '%s' invalid translation type\n", str);
1040 return -1;
1041 }
1042 }
1043
1044 if (get_param_value(buf, sizeof(buf), "media", str)) {
1045 if (!strcmp(buf, "disk")) {
1046 media = MEDIA_DISK;
1047 } else if (!strcmp(buf, "cdrom")) {
1048 if (cyls || secs || heads) {
1049 fprintf(stderr,
1050 "qemu: '%s' invalid physical CHS format\n", str);
1051 return -1;
1052 }
1053 media = MEDIA_CDROM;
1054 } else {
1055 fprintf(stderr, "qemu: '%s' invalid media\n", str);
1056 return -1;
1057 }
1058 }
1059
1060 if (get_param_value(buf, sizeof(buf), "snapshot", str)) {
1061 if (!strcmp(buf, "on"))
1062 snapshot = 1;
1063 else if (!strcmp(buf, "off"))
1064 snapshot = 0;
1065 else {
1066 fprintf(stderr, "qemu: '%s' invalid snapshot option\n", str);
1067 return -1;
1068 }
1069 }
1070
1071 if (get_param_value(buf, sizeof(buf), "cache", str)) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001072 if (!strcmp(buf, "off") || !strcmp(buf, "none"))
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001073 cache = 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001074 else if (!strcmp(buf, "writethrough"))
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001075 cache = 1;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001076 else if (!strcmp(buf, "writeback"))
1077 cache = 2;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001078 else {
1079 fprintf(stderr, "qemu: invalid cache option\n");
1080 return -1;
1081 }
1082 }
1083
1084 if (get_param_value(buf, sizeof(buf), "format", str)) {
1085 if (strcmp(buf, "?") == 0) {
1086 fprintf(stderr, "qemu: Supported formats:");
1087 bdrv_iterate_format(bdrv_format_print, NULL);
1088 fprintf(stderr, "\n");
1089 return -1;
1090 }
1091 drv = bdrv_find_format(buf);
1092 if (!drv) {
1093 fprintf(stderr, "qemu: '%s' invalid format\n", buf);
1094 return -1;
1095 }
1096 }
1097
1098 if (arg->file == NULL)
1099 get_param_value(file, sizeof(file), "file", str);
1100 else
1101 pstrcpy(file, sizeof(file), arg->file);
1102
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001103 if (!get_param_value(serial, sizeof(serial), "serial", str))
1104 memset(serial, 0, sizeof(serial));
1105
1106 onerror = BLOCK_ERR_STOP_ENOSPC;
1107 if (get_param_value(buf, sizeof(serial), "werror", str)) {
1108 if (type != IF_IDE && type != IF_SCSI && type != IF_VIRTIO) {
1109 fprintf(stderr, "werror is no supported by this format\n");
1110 return -1;
1111 }
1112 if (!strcmp(buf, "ignore"))
1113 onerror = BLOCK_ERR_IGNORE;
1114 else if (!strcmp(buf, "enospc"))
1115 onerror = BLOCK_ERR_STOP_ENOSPC;
1116 else if (!strcmp(buf, "stop"))
1117 onerror = BLOCK_ERR_STOP_ANY;
1118 else if (!strcmp(buf, "report"))
1119 onerror = BLOCK_ERR_REPORT;
1120 else {
1121 fprintf(stderr, "qemu: '%s' invalid write error action\n", buf);
1122 return -1;
1123 }
1124 }
1125
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001126 /* compute bus and unit according index */
1127
1128 if (index != -1) {
1129 if (bus_id != 0 || unit_id != -1) {
1130 fprintf(stderr,
1131 "qemu: '%s' index cannot be used with bus and unit\n", str);
1132 return -1;
1133 }
1134 if (max_devs == 0)
1135 {
1136 unit_id = index;
1137 bus_id = 0;
1138 } else {
1139 unit_id = index % max_devs;
1140 bus_id = index / max_devs;
1141 }
1142 }
1143
1144 /* if user doesn't specify a unit_id,
1145 * try to find the first free
1146 */
1147
1148 if (unit_id == -1) {
1149 unit_id = 0;
1150 while (drive_get_index(type, bus_id, unit_id) != -1) {
1151 unit_id++;
1152 if (max_devs && unit_id >= max_devs) {
1153 unit_id -= max_devs;
1154 bus_id++;
1155 }
1156 }
1157 }
1158
1159 /* check unit id */
1160
1161 if (max_devs && unit_id >= max_devs) {
1162 fprintf(stderr, "qemu: '%s' unit %d too big (max is %d)\n",
1163 str, unit_id, max_devs - 1);
1164 return -1;
1165 }
1166
1167 /*
1168 * ignore multiple definitions
1169 */
1170
1171 if (drive_get_index(type, bus_id, unit_id) != -1)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001172 return -2;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001173
1174 /* init */
1175
1176 if (type == IF_IDE || type == IF_SCSI)
1177 mediastr = (media == MEDIA_CDROM) ? "-cd" : "-hd";
1178 if (max_devs)
1179 snprintf(buf, sizeof(buf), "%s%i%s%i",
1180 devname, bus_id, mediastr, unit_id);
1181 else
1182 snprintf(buf, sizeof(buf), "%s%s%i",
1183 devname, mediastr, unit_id);
1184 bdrv = bdrv_new(buf);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001185 drives_table_idx = drive_get_free_idx();
1186 drives_table[drives_table_idx].bdrv = bdrv;
1187 drives_table[drives_table_idx].type = type;
1188 drives_table[drives_table_idx].bus = bus_id;
1189 drives_table[drives_table_idx].unit = unit_id;
1190 drives_table[drives_table_idx].onerror = onerror;
1191 drives_table[drives_table_idx].drive_opt_idx = arg - drives_opt;
1192 strncpy(drives_table[drives_table_idx].serial, serial, sizeof(serial));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001193 nb_drives++;
1194
1195 switch(type) {
1196 case IF_IDE:
1197 case IF_SCSI:
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001198 case IF_XEN:
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001199 switch(media) {
1200 case MEDIA_DISK:
1201 if (cyls != 0) {
1202 bdrv_set_geometry_hint(bdrv, cyls, heads, secs);
1203 bdrv_set_translation_hint(bdrv, translation);
1204 }
1205 break;
1206 case MEDIA_CDROM:
1207 bdrv_set_type_hint(bdrv, BDRV_TYPE_CDROM);
1208 break;
1209 }
1210 break;
1211 case IF_SD:
1212 /* FIXME: This isn't really a floppy, but it's a reasonable
1213 approximation. */
1214 case IF_FLOPPY:
1215 bdrv_set_type_hint(bdrv, BDRV_TYPE_FLOPPY);
1216 break;
1217 case IF_PFLASH:
1218 case IF_MTD:
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001219 case IF_VIRTIO:
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001220 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001221 case IF_COUNT:
1222 abort();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001223 }
1224 if (!file[0])
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001225 return -2;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001226 bdrv_flags = 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001227 if (snapshot) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001228 bdrv_flags |= BDRV_O_SNAPSHOT;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001229 cache = 2; /* always use write-back with snapshot */
1230 }
1231 if (cache == 0) /* no caching */
1232 bdrv_flags |= BDRV_O_NOCACHE;
1233 else if (cache == 2) /* write-back */
1234 bdrv_flags |= BDRV_O_CACHE_WB;
1235 else if (cache == 3) /* not specified */
1236 bdrv_flags |= BDRV_O_CACHE_DEF;
1237 if (bdrv_open2(bdrv, file, bdrv_flags, drv) < 0) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001238 fprintf(stderr, "qemu: could not open disk image %s\n",
1239 file);
1240 return -1;
1241 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001242 if (bdrv_key_required(bdrv))
1243 autostart = 0;
1244 return drives_table_idx;
1245}
1246
1247static void numa_add(const char *optarg)
1248{
1249 char option[128];
1250 char *endptr;
1251 unsigned long long value, endvalue;
1252 int nodenr;
1253
1254 optarg = get_opt_name(option, 128, optarg, ',') + 1;
1255 if (!strcmp(option, "node")) {
1256 if (get_param_value(option, 128, "nodeid", optarg) == 0) {
1257 nodenr = nb_numa_nodes;
1258 } else {
1259 nodenr = strtoull(option, NULL, 10);
1260 }
1261
1262 if (get_param_value(option, 128, "mem", optarg) == 0) {
1263 node_mem[nodenr] = 0;
1264 } else {
1265 value = strtoull(option, &endptr, 0);
1266 switch (*endptr) {
1267 case 0: case 'M': case 'm':
1268 value <<= 20;
1269 break;
1270 case 'G': case 'g':
1271 value <<= 30;
1272 break;
1273 }
1274 node_mem[nodenr] = value;
1275 }
1276 if (get_param_value(option, 128, "cpus", optarg) == 0) {
1277 node_cpumask[nodenr] = 0;
1278 } else {
1279 value = strtoull(option, &endptr, 10);
1280 if (value >= 64) {
1281 value = 63;
1282 fprintf(stderr, "only 64 CPUs in NUMA mode supported.\n");
1283 } else {
1284 if (*endptr == '-') {
1285 endvalue = strtoull(endptr+1, &endptr, 10);
1286 if (endvalue >= 63) {
1287 endvalue = 62;
1288 fprintf(stderr,
1289 "only 63 CPUs in NUMA mode supported.\n");
1290 }
1291 value = (1 << (endvalue + 1)) - (1 << value);
1292 } else {
1293 value = 1 << value;
1294 }
1295 }
1296 node_cpumask[nodenr] = value;
1297 }
1298 nb_numa_nodes++;
1299 }
1300 return;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001301}
1302
1303/***********************************************************/
1304/* USB devices */
1305
1306static USBPort *used_usb_ports;
1307static USBPort *free_usb_ports;
1308
1309/* ??? Maybe change this to register a hub to keep track of the topology. */
1310void qemu_register_usb_port(USBPort *port, void *opaque, int index,
1311 usb_attachfn attach)
1312{
1313 port->opaque = opaque;
1314 port->index = index;
1315 port->attach = attach;
1316 port->next = free_usb_ports;
1317 free_usb_ports = port;
1318}
1319
1320int usb_device_add_dev(USBDevice *dev)
1321{
1322 USBPort *port;
1323
1324 /* Find a USB port to add the device to. */
1325 port = free_usb_ports;
1326 if (!port->next) {
1327 USBDevice *hub;
1328
1329 /* Create a new hub and chain it on. */
1330 free_usb_ports = NULL;
1331 port->next = used_usb_ports;
1332 used_usb_ports = port;
1333
1334 hub = usb_hub_init(VM_USB_HUB_SIZE);
1335 usb_attach(port, hub);
1336 port = free_usb_ports;
1337 }
1338
1339 free_usb_ports = port->next;
1340 port->next = used_usb_ports;
1341 used_usb_ports = port;
1342 usb_attach(port, dev);
1343 return 0;
1344}
1345
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001346static void usb_msd_password_cb(void *opaque, int err)
1347{
1348 USBDevice *dev = opaque;
1349
1350 if (!err)
1351 usb_device_add_dev(dev);
1352 else
1353 dev->handle_destroy(dev);
1354}
1355
1356static int usb_device_add(const char *devname, int is_hotplug)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001357{
1358 const char *p;
1359 USBDevice *dev;
1360
1361 if (!free_usb_ports)
1362 return -1;
1363
1364 if (strstart(devname, "host:", &p)) {
1365 dev = usb_host_device_open(p);
1366 } else if (!strcmp(devname, "mouse")) {
1367 dev = usb_mouse_init();
1368 } else if (!strcmp(devname, "tablet")) {
1369 dev = usb_tablet_init();
1370 } else if (!strcmp(devname, "keyboard")) {
1371 dev = usb_keyboard_init();
1372 } else if (strstart(devname, "disk:", &p)) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001373 BlockDriverState *bs;
1374
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001375 dev = usb_msd_init(p);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001376 if (!dev)
1377 return -1;
1378 bs = usb_msd_get_bdrv(dev);
1379 if (bdrv_key_required(bs)) {
1380 autostart = 0;
1381 if (is_hotplug) {
1382 monitor_read_bdrv_key_start(cur_mon, bs, usb_msd_password_cb,
1383 dev);
1384 return 0;
1385 }
1386 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001387 } else if (!strcmp(devname, "wacom-tablet")) {
1388 dev = usb_wacom_init();
1389 } else if (strstart(devname, "serial:", &p)) {
1390 dev = usb_serial_init(p);
1391#ifdef CONFIG_BRLAPI
1392 } else if (!strcmp(devname, "braille")) {
1393 dev = usb_baum_init();
1394#endif
1395 } else if (strstart(devname, "net:", &p)) {
1396 int nic = nb_nics;
1397
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001398 if (net_client_init(NULL, "nic", p) < 0)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001399 return -1;
1400 nd_table[nic].model = "usb";
1401 dev = usb_net_init(&nd_table[nic]);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001402 } else if (!strcmp(devname, "bt") || strstart(devname, "bt:", &p)) {
1403 dev = usb_bt_init(devname[2] ? hci_init(p) :
1404 bt_new_hci(qemu_find_bt_vlan(0)));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001405 } else {
1406 return -1;
1407 }
1408 if (!dev)
1409 return -1;
1410
1411 return usb_device_add_dev(dev);
1412}
1413
1414int usb_device_del_addr(int bus_num, int addr)
1415{
1416 USBPort *port;
1417 USBPort **lastp;
1418 USBDevice *dev;
1419
1420 if (!used_usb_ports)
1421 return -1;
1422
1423 if (bus_num != 0)
1424 return -1;
1425
1426 lastp = &used_usb_ports;
1427 port = used_usb_ports;
1428 while (port && port->dev->addr != addr) {
1429 lastp = &port->next;
1430 port = port->next;
1431 }
1432
1433 if (!port)
1434 return -1;
1435
1436 dev = port->dev;
1437 *lastp = port->next;
1438 usb_attach(port, NULL);
1439 dev->handle_destroy(dev);
1440 port->next = free_usb_ports;
1441 free_usb_ports = port;
1442 return 0;
1443}
1444
1445static int usb_device_del(const char *devname)
1446{
1447 int bus_num, addr;
1448 const char *p;
1449
1450 if (strstart(devname, "host:", &p))
1451 return usb_host_device_close(p);
1452
1453 if (!used_usb_ports)
1454 return -1;
1455
1456 p = strchr(devname, '.');
1457 if (!p)
1458 return -1;
1459 bus_num = strtoul(devname, NULL, 0);
1460 addr = strtoul(p + 1, NULL, 0);
1461
1462 return usb_device_del_addr(bus_num, addr);
1463}
1464
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001465void do_usb_add(Monitor *mon, const char *devname)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001466{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001467 usb_device_add(devname, 1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001468}
1469
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001470void do_usb_del(Monitor *mon, const char *devname)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001471{
1472 usb_device_del(devname);
1473}
1474
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001475void usb_info(Monitor *mon)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001476{
1477 USBDevice *dev;
1478 USBPort *port;
1479 const char *speed_str;
1480
1481 if (!usb_enabled) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001482 monitor_printf(mon, "USB support not enabled\n");
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001483 return;
1484 }
1485
1486 for (port = used_usb_ports; port; port = port->next) {
1487 dev = port->dev;
1488 if (!dev)
1489 continue;
1490 switch(dev->speed) {
1491 case USB_SPEED_LOW:
1492 speed_str = "1.5";
1493 break;
1494 case USB_SPEED_FULL:
1495 speed_str = "12";
1496 break;
1497 case USB_SPEED_HIGH:
1498 speed_str = "480";
1499 break;
1500 default:
1501 speed_str = "?";
1502 break;
1503 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001504 monitor_printf(mon, " Device %d.%d, Speed %s Mb/s, Product %s\n",
1505 0, dev->addr, speed_str, dev->devname);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001506 }
1507}
1508
1509/***********************************************************/
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001510/* PCMCIA/Cardbus */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001511
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001512static struct pcmcia_socket_entry_s {
1513 PCMCIASocket *socket;
1514 struct pcmcia_socket_entry_s *next;
1515} *pcmcia_sockets = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001516
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001517void pcmcia_socket_register(PCMCIASocket *socket)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001518{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001519 struct pcmcia_socket_entry_s *entry;
1520
1521 entry = qemu_malloc(sizeof(struct pcmcia_socket_entry_s));
1522 entry->socket = socket;
1523 entry->next = pcmcia_sockets;
1524 pcmcia_sockets = entry;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001525}
1526
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001527void pcmcia_socket_unregister(PCMCIASocket *socket)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001528{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001529 struct pcmcia_socket_entry_s *entry, **ptr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001530
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001531 ptr = &pcmcia_sockets;
1532 for (entry = *ptr; entry; ptr = &entry->next, entry = *ptr)
1533 if (entry->socket == socket) {
1534 *ptr = entry->next;
1535 qemu_free(entry);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001536 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001537}
1538
1539void pcmcia_info(Monitor *mon)
1540{
1541 struct pcmcia_socket_entry_s *iter;
1542
1543 if (!pcmcia_sockets)
1544 monitor_printf(mon, "No PCMCIA sockets\n");
1545
1546 for (iter = pcmcia_sockets; iter; iter = iter->next)
1547 monitor_printf(mon, "%s: %s\n", iter->socket->slot_string,
1548 iter->socket->attached ? iter->socket->card_string :
1549 "Empty");
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001550}
1551
1552/***********************************************************/
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001553/* register display */
1554
1555struct DisplayAllocator default_allocator = {
1556 defaultallocator_create_displaysurface,
1557 defaultallocator_resize_displaysurface,
1558 defaultallocator_free_displaysurface
1559};
1560
1561void register_displaystate(DisplayState *ds)
1562{
1563 DisplayState **s;
1564 s = &display_state;
1565 while (*s != NULL)
1566 s = &(*s)->next;
1567 ds->next = NULL;
1568 *s = ds;
1569}
1570
1571DisplayState *get_displaystate(void)
1572{
1573 return display_state;
1574}
1575
1576DisplayAllocator *register_displayallocator(DisplayState *ds, DisplayAllocator *da)
1577{
1578 if(ds->allocator == &default_allocator) ds->allocator = da;
1579 return ds->allocator;
1580}
1581
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001582/* dumb display */
1583
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001584static void dumb_display_init(void)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001585{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001586 DisplayState *ds = qemu_mallocz(sizeof(DisplayState));
1587 ds->allocator = &default_allocator;
1588 ds->surface = qemu_create_displaysurface(ds, 640, 480);
1589 register_displaystate(ds);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001590}
1591
1592/***********************************************************/
1593/* I/O handling */
1594
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001595typedef struct IOHandlerRecord {
1596 int fd;
David Turner4143d8f2010-09-10 11:05:02 +02001597 IOCanReadHandler *fd_read_poll;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001598 IOHandler *fd_read;
1599 IOHandler *fd_write;
1600 int deleted;
1601 void *opaque;
1602 /* temporary data */
1603 struct pollfd *ufd;
David Turner025c32f2010-09-10 14:52:42 +02001604 QLIST_ENTRY(IOHandlerRecord) next;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001605} IOHandlerRecord;
1606
David Turner025c32f2010-09-10 14:52:42 +02001607static QLIST_HEAD(, IOHandlerRecord) io_handlers =
1608 QLIST_HEAD_INITIALIZER(io_handlers);
1609
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001610
1611/* XXX: fd_read_poll should be suppressed, but an API change is
1612 necessary in the character devices to suppress fd_can_read(). */
1613int qemu_set_fd_handler2(int fd,
David Turner4143d8f2010-09-10 11:05:02 +02001614 IOCanReadHandler *fd_read_poll,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001615 IOHandler *fd_read,
1616 IOHandler *fd_write,
1617 void *opaque)
1618{
David Turner025c32f2010-09-10 14:52:42 +02001619 IOHandlerRecord *ioh;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001620
1621 if (!fd_read && !fd_write) {
David Turner025c32f2010-09-10 14:52:42 +02001622 QLIST_FOREACH(ioh, &io_handlers, next) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001623 if (ioh->fd == fd) {
1624 ioh->deleted = 1;
1625 break;
1626 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001627 }
1628 } else {
David Turner025c32f2010-09-10 14:52:42 +02001629 QLIST_FOREACH(ioh, &io_handlers, next) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001630 if (ioh->fd == fd)
1631 goto found;
1632 }
1633 ioh = qemu_mallocz(sizeof(IOHandlerRecord));
David Turner025c32f2010-09-10 14:52:42 +02001634 QLIST_INSERT_HEAD(&io_handlers, ioh, next);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001635 found:
1636 ioh->fd = fd;
1637 ioh->fd_read_poll = fd_read_poll;
1638 ioh->fd_read = fd_read;
1639 ioh->fd_write = fd_write;
1640 ioh->opaque = opaque;
1641 ioh->deleted = 0;
1642 }
1643 return 0;
1644}
1645
1646int qemu_set_fd_handler(int fd,
1647 IOHandler *fd_read,
1648 IOHandler *fd_write,
1649 void *opaque)
1650{
1651 return qemu_set_fd_handler2(fd, NULL, fd_read, fd_write, opaque);
1652}
1653
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001654#ifdef _WIN32
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001655/***********************************************************/
1656/* Polling handling */
1657
1658typedef struct PollingEntry {
1659 PollingFunc *func;
1660 void *opaque;
1661 struct PollingEntry *next;
1662} PollingEntry;
1663
1664static PollingEntry *first_polling_entry;
1665
1666int qemu_add_polling_cb(PollingFunc *func, void *opaque)
1667{
1668 PollingEntry **ppe, *pe;
1669 pe = qemu_mallocz(sizeof(PollingEntry));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001670 pe->func = func;
1671 pe->opaque = opaque;
1672 for(ppe = &first_polling_entry; *ppe != NULL; ppe = &(*ppe)->next);
1673 *ppe = pe;
1674 return 0;
1675}
1676
1677void qemu_del_polling_cb(PollingFunc *func, void *opaque)
1678{
1679 PollingEntry **ppe, *pe;
1680 for(ppe = &first_polling_entry; *ppe != NULL; ppe = &(*ppe)->next) {
1681 pe = *ppe;
1682 if (pe->func == func && pe->opaque == opaque) {
1683 *ppe = pe->next;
1684 qemu_free(pe);
1685 break;
1686 }
1687 }
1688}
1689
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001690/***********************************************************/
1691/* Wait objects support */
1692typedef struct WaitObjects {
1693 int num;
1694 HANDLE events[MAXIMUM_WAIT_OBJECTS + 1];
1695 WaitObjectFunc *func[MAXIMUM_WAIT_OBJECTS + 1];
1696 void *opaque[MAXIMUM_WAIT_OBJECTS + 1];
1697} WaitObjects;
1698
1699static WaitObjects wait_objects = {0};
1700
1701int qemu_add_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque)
1702{
1703 WaitObjects *w = &wait_objects;
1704
1705 if (w->num >= MAXIMUM_WAIT_OBJECTS)
1706 return -1;
1707 w->events[w->num] = handle;
1708 w->func[w->num] = func;
1709 w->opaque[w->num] = opaque;
1710 w->num++;
1711 return 0;
1712}
1713
1714void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque)
1715{
1716 int i, found;
1717 WaitObjects *w = &wait_objects;
1718
1719 found = 0;
1720 for (i = 0; i < w->num; i++) {
1721 if (w->events[i] == handle)
1722 found = 1;
1723 if (found) {
1724 w->events[i] = w->events[i + 1];
1725 w->func[i] = w->func[i + 1];
1726 w->opaque[i] = w->opaque[i + 1];
1727 }
1728 }
1729 if (found)
1730 w->num--;
1731}
1732#endif
1733
1734/***********************************************************/
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001735/* ram save/restore */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001736
1737static int ram_get_page(QEMUFile *f, uint8_t *buf, int len)
1738{
1739 int v;
1740
1741 v = qemu_get_byte(f);
1742 switch(v) {
1743 case 0:
1744 if (qemu_get_buffer(f, buf, len) != len)
1745 return -EIO;
1746 break;
1747 case 1:
1748 v = qemu_get_byte(f);
1749 memset(buf, v, len);
1750 break;
1751 default:
1752 return -EINVAL;
1753 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001754
1755 if (qemu_file_has_error(f))
1756 return -EIO;
1757
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001758 return 0;
1759}
1760
1761static int ram_load_v1(QEMUFile *f, void *opaque)
1762{
1763 int ret;
1764 ram_addr_t i;
1765
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001766 if (qemu_get_be32(f) != last_ram_offset)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001767 return -EINVAL;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001768 for(i = 0; i < last_ram_offset; i+= TARGET_PAGE_SIZE) {
1769 ret = ram_get_page(f, qemu_get_ram_ptr(i), TARGET_PAGE_SIZE);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001770 if (ret)
1771 return ret;
1772 }
1773 return 0;
1774}
1775
1776#define BDRV_HASH_BLOCK_SIZE 1024
1777#define IOBUF_SIZE 4096
1778#define RAM_CBLOCK_MAGIC 0xfabe
1779
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001780typedef struct RamDecompressState {
1781 z_stream zstream;
1782 QEMUFile *f;
1783 uint8_t buf[IOBUF_SIZE];
1784} RamDecompressState;
1785
1786static int ram_decompress_open(RamDecompressState *s, QEMUFile *f)
1787{
1788 int ret;
1789 memset(s, 0, sizeof(*s));
1790 s->f = f;
1791 ret = inflateInit(&s->zstream);
1792 if (ret != Z_OK)
1793 return -1;
1794 return 0;
1795}
1796
1797static int ram_decompress_buf(RamDecompressState *s, uint8_t *buf, int len)
1798{
1799 int ret, clen;
1800
1801 s->zstream.avail_out = len;
1802 s->zstream.next_out = buf;
1803 while (s->zstream.avail_out > 0) {
1804 if (s->zstream.avail_in == 0) {
1805 if (qemu_get_be16(s->f) != RAM_CBLOCK_MAGIC)
1806 return -1;
1807 clen = qemu_get_be16(s->f);
1808 if (clen > IOBUF_SIZE)
1809 return -1;
1810 qemu_get_buffer(s->f, s->buf, clen);
1811 s->zstream.avail_in = clen;
1812 s->zstream.next_in = s->buf;
1813 }
1814 ret = inflate(&s->zstream, Z_PARTIAL_FLUSH);
1815 if (ret != Z_OK && ret != Z_STREAM_END) {
1816 return -1;
1817 }
1818 }
1819 return 0;
1820}
1821
1822static void ram_decompress_close(RamDecompressState *s)
1823{
1824 inflateEnd(&s->zstream);
1825}
1826
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001827#define RAM_SAVE_FLAG_FULL 0x01
1828#define RAM_SAVE_FLAG_COMPRESS 0x02
1829#define RAM_SAVE_FLAG_MEM_SIZE 0x04
1830#define RAM_SAVE_FLAG_PAGE 0x08
1831#define RAM_SAVE_FLAG_EOS 0x10
1832
1833static int is_dup_page(uint8_t *page, uint8_t ch)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001834{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001835 uint32_t val = ch << 24 | ch << 16 | ch << 8 | ch;
1836 uint32_t *array = (uint32_t *)page;
1837 int i;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001838
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001839 for (i = 0; i < (TARGET_PAGE_SIZE / 4); i++) {
1840 if (array[i] != val)
1841 return 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001842 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001843
1844 return 1;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001845}
1846
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001847static int ram_save_block(QEMUFile *f)
1848{
1849 static ram_addr_t current_addr = 0;
1850 ram_addr_t saved_addr = current_addr;
1851 ram_addr_t addr = 0;
1852 int found = 0;
1853
1854 while (addr < last_ram_offset) {
1855 if (cpu_physical_memory_get_dirty(current_addr, MIGRATION_DIRTY_FLAG)) {
1856 uint8_t *p;
1857
1858 cpu_physical_memory_reset_dirty(current_addr,
1859 current_addr + TARGET_PAGE_SIZE,
1860 MIGRATION_DIRTY_FLAG);
1861
1862 p = qemu_get_ram_ptr(current_addr);
1863
1864 if (is_dup_page(p, *p)) {
1865 qemu_put_be64(f, current_addr | RAM_SAVE_FLAG_COMPRESS);
1866 qemu_put_byte(f, *p);
1867 } else {
1868 qemu_put_be64(f, current_addr | RAM_SAVE_FLAG_PAGE);
1869 qemu_put_buffer(f, p, TARGET_PAGE_SIZE);
1870 }
1871
1872 found = 1;
1873 break;
1874 }
1875 addr += TARGET_PAGE_SIZE;
1876 current_addr = (saved_addr + addr) % last_ram_offset;
1877 }
1878
1879 return found;
1880}
1881
David 'Digit' Turnera7fb77d2010-05-10 23:50:54 -07001882static uint64_t bytes_transferred;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001883
1884static ram_addr_t ram_save_remaining(void)
1885{
1886 ram_addr_t addr;
1887 ram_addr_t count = 0;
1888
1889 for (addr = 0; addr < last_ram_offset; addr += TARGET_PAGE_SIZE) {
1890 if (cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG))
1891 count++;
1892 }
1893
1894 return count;
1895}
1896
1897uint64_t ram_bytes_remaining(void)
1898{
1899 return ram_save_remaining() * TARGET_PAGE_SIZE;
1900}
1901
1902uint64_t ram_bytes_transferred(void)
1903{
1904 return bytes_transferred;
1905}
1906
1907uint64_t ram_bytes_total(void)
1908{
1909 return last_ram_offset;
1910}
1911
1912static int ram_save_live(QEMUFile *f, int stage, void *opaque)
1913{
1914 ram_addr_t addr;
1915 uint64_t bytes_transferred_last;
1916 double bwidth = 0;
1917 uint64_t expected_time = 0;
1918
1919 if (cpu_physical_sync_dirty_bitmap(0, TARGET_PHYS_ADDR_MAX) != 0) {
1920 qemu_file_set_error(f);
1921 return 0;
1922 }
1923
1924 if (stage == 1) {
David 'Digit' Turnera7fb77d2010-05-10 23:50:54 -07001925 bytes_transferred = 0;
1926
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001927 /* Make sure all dirty bits are set */
1928 for (addr = 0; addr < last_ram_offset; addr += TARGET_PAGE_SIZE) {
1929 if (!cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG))
1930 cpu_physical_memory_set_dirty(addr);
1931 }
1932
1933 /* Enable dirty memory tracking */
1934 cpu_physical_memory_set_dirty_tracking(1);
1935
1936 qemu_put_be64(f, last_ram_offset | RAM_SAVE_FLAG_MEM_SIZE);
1937 }
1938
1939 bytes_transferred_last = bytes_transferred;
David 'Digit' Turnera7fb77d2010-05-10 23:50:54 -07001940 bwidth = qemu_get_clock_ns(rt_clock);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001941
1942 while (!qemu_file_rate_limit(f)) {
1943 int ret;
1944
1945 ret = ram_save_block(f);
1946 bytes_transferred += ret * TARGET_PAGE_SIZE;
1947 if (ret == 0) /* no more blocks */
1948 break;
1949 }
1950
David 'Digit' Turnera7fb77d2010-05-10 23:50:54 -07001951 bwidth = qemu_get_clock_ns(rt_clock) - bwidth;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001952 bwidth = (bytes_transferred - bytes_transferred_last) / bwidth;
1953
1954 /* if we haven't transferred anything this round, force expected_time to a
1955 * a very high value, but without crashing */
1956 if (bwidth == 0)
1957 bwidth = 0.000001;
1958
1959 /* try transferring iterative blocks of memory */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001960 if (stage == 3) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001961 /* flush all remaining blocks regardless of rate limiting */
1962 while (ram_save_block(f) != 0) {
1963 bytes_transferred += TARGET_PAGE_SIZE;
1964 }
1965 cpu_physical_memory_set_dirty_tracking(0);
1966 }
1967
1968 qemu_put_be64(f, RAM_SAVE_FLAG_EOS);
1969
1970 expected_time = ram_save_remaining() * TARGET_PAGE_SIZE / bwidth;
1971
1972 return (stage == 2) && (expected_time <= migrate_max_downtime());
1973}
1974
1975static int ram_load_dead(QEMUFile *f, void *opaque)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001976{
1977 RamDecompressState s1, *s = &s1;
1978 uint8_t buf[10];
1979 ram_addr_t i;
1980
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001981 if (ram_decompress_open(s, f) < 0)
1982 return -EINVAL;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001983 for(i = 0; i < last_ram_offset; i+= BDRV_HASH_BLOCK_SIZE) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001984 if (ram_decompress_buf(s, buf, 1) < 0) {
1985 fprintf(stderr, "Error while reading ram block header\n");
1986 goto error;
1987 }
1988 if (buf[0] == 0) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001989 if (ram_decompress_buf(s, qemu_get_ram_ptr(i),
1990 BDRV_HASH_BLOCK_SIZE) < 0) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001991 fprintf(stderr, "Error while reading ram block address=0x%08" PRIx64, (uint64_t)i);
1992 goto error;
1993 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001994 } else {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001995 error:
1996 printf("Error block header\n");
1997 return -EINVAL;
1998 }
1999 }
2000 ram_decompress_close(s);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002001
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002002 return 0;
2003}
2004
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002005static int ram_load(QEMUFile *f, void *opaque, int version_id)
2006{
2007 ram_addr_t addr;
2008 int flags;
2009
2010 if (version_id == 1)
2011 return ram_load_v1(f, opaque);
2012
2013 if (version_id == 2) {
2014 if (qemu_get_be32(f) != last_ram_offset)
2015 return -EINVAL;
2016 return ram_load_dead(f, opaque);
2017 }
2018
2019 if (version_id != 3)
2020 return -EINVAL;
2021
2022 do {
2023 addr = qemu_get_be64(f);
2024
2025 flags = addr & ~TARGET_PAGE_MASK;
2026 addr &= TARGET_PAGE_MASK;
2027
2028 if (flags & RAM_SAVE_FLAG_MEM_SIZE) {
2029 if (addr != last_ram_offset)
2030 return -EINVAL;
2031 }
2032
2033 if (flags & RAM_SAVE_FLAG_FULL) {
2034 if (ram_load_dead(f, opaque) < 0)
2035 return -EINVAL;
2036 }
David 'Digit' Turner707c8a82010-12-22 22:35:58 +01002037
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002038 if (flags & RAM_SAVE_FLAG_COMPRESS) {
2039 uint8_t ch = qemu_get_byte(f);
2040 memset(qemu_get_ram_ptr(addr), ch, TARGET_PAGE_SIZE);
2041 } else if (flags & RAM_SAVE_FLAG_PAGE)
2042 qemu_get_buffer(f, qemu_get_ram_ptr(addr), TARGET_PAGE_SIZE);
2043 } while (!(flags & RAM_SAVE_FLAG_EOS));
2044
2045 return 0;
2046}
2047
2048void qemu_service_io(void)
2049{
2050 qemu_notify_event();
2051}
2052
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002053/***********************************************************/
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002054/* machine registration */
2055
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002056static QEMUMachine *first_machine = NULL;
2057QEMUMachine *current_machine = NULL;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002058
2059int qemu_register_machine(QEMUMachine *m)
2060{
2061 QEMUMachine **pm;
2062 pm = &first_machine;
2063 while (*pm != NULL)
2064 pm = &(*pm)->next;
2065 m->next = NULL;
2066 *pm = m;
2067 return 0;
2068}
2069
2070static QEMUMachine *find_machine(const char *name)
2071{
2072 QEMUMachine *m;
2073
2074 for(m = first_machine; m != NULL; m = m->next) {
2075 if (!strcmp(m->name, name))
2076 return m;
2077 }
2078 return NULL;
2079}
2080
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002081static QEMUMachine *find_default_machine(void)
2082{
2083 QEMUMachine *m;
2084
2085 for(m = first_machine; m != NULL; m = m->next) {
2086 if (m->is_default) {
2087 return m;
2088 }
2089 }
2090 return NULL;
2091}
2092
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002093/***********************************************************/
2094/* main execution loop */
2095
2096static void gui_update(void *opaque)
2097{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002098 uint64_t interval = GUI_REFRESH_INTERVAL;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002099 DisplayState *ds = opaque;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002100 DisplayChangeListener *dcl = ds->listeners;
2101
2102 dpy_refresh(ds);
2103
2104 while (dcl != NULL) {
2105 if (dcl->gui_timer_interval &&
2106 dcl->gui_timer_interval < interval)
2107 interval = dcl->gui_timer_interval;
2108 dcl = dcl->next;
2109 }
2110 qemu_mod_timer(ds->gui_timer, interval + qemu_get_clock(rt_clock));
2111}
2112
2113static void nographic_update(void *opaque)
2114{
2115 uint64_t interval = GUI_REFRESH_INTERVAL;
2116
2117 qemu_mod_timer(nographic_timer, interval + qemu_get_clock(rt_clock));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002118}
2119
2120struct vm_change_state_entry {
2121 VMChangeStateHandler *cb;
2122 void *opaque;
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002123 QLIST_ENTRY (vm_change_state_entry) entries;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002124};
2125
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002126static QLIST_HEAD(vm_change_state_head, vm_change_state_entry) vm_change_state_head;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002127
2128VMChangeStateEntry *qemu_add_vm_change_state_handler(VMChangeStateHandler *cb,
2129 void *opaque)
2130{
2131 VMChangeStateEntry *e;
2132
2133 e = qemu_mallocz(sizeof (*e));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002134
2135 e->cb = cb;
2136 e->opaque = opaque;
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002137 QLIST_INSERT_HEAD(&vm_change_state_head, e, entries);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002138 return e;
2139}
2140
2141void qemu_del_vm_change_state_handler(VMChangeStateEntry *e)
2142{
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002143 QLIST_REMOVE (e, entries);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002144 qemu_free (e);
2145}
2146
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002147static void vm_state_notify(int running, int reason)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002148{
2149 VMChangeStateEntry *e;
2150
2151 for (e = vm_change_state_head.lh_first; e; e = e->entries.le_next) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002152 e->cb(e->opaque, running, reason);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002153 }
2154}
2155
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002156static void resume_all_vcpus(void);
2157static void pause_all_vcpus(void);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002158
2159void vm_start(void)
2160{
2161 if (!vm_running) {
2162 cpu_enable_ticks();
2163 vm_running = 1;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002164 vm_state_notify(1, 0);
David Turner6a9ef172010-09-09 22:54:36 +02002165 //qemu_rearm_alarm_timer(alarm_timer);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002166 resume_all_vcpus();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002167 }
2168}
2169
2170/* reset/shutdown handler */
2171
2172typedef struct QEMUResetEntry {
David Turner025c32f2010-09-10 14:52:42 +02002173 QTAILQ_ENTRY(QEMUResetEntry) entry;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002174 QEMUResetHandler *func;
2175 void *opaque;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002176} QEMUResetEntry;
2177
David Turner025c32f2010-09-10 14:52:42 +02002178static QTAILQ_HEAD(reset_handlers, QEMUResetEntry) reset_handlers =
2179 QTAILQ_HEAD_INITIALIZER(reset_handlers);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002180static int reset_requested;
2181static int shutdown_requested;
2182static int powerdown_requested;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002183static int debug_requested;
2184static int vmstop_requested;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002185
2186int qemu_shutdown_requested(void)
2187{
2188 int r = shutdown_requested;
2189 shutdown_requested = 0;
2190 return r;
2191}
2192
2193int qemu_reset_requested(void)
2194{
2195 int r = reset_requested;
2196 reset_requested = 0;
2197 return r;
2198}
2199
2200int qemu_powerdown_requested(void)
2201{
2202 int r = powerdown_requested;
2203 powerdown_requested = 0;
2204 return r;
2205}
2206
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002207static int qemu_debug_requested(void)
2208{
2209 int r = debug_requested;
2210 debug_requested = 0;
2211 return r;
2212}
2213
2214static int qemu_vmstop_requested(void)
2215{
2216 int r = vmstop_requested;
2217 vmstop_requested = 0;
2218 return r;
2219}
2220
David Turner025c32f2010-09-10 14:52:42 +02002221void qemu_register_reset(QEMUResetHandler *func, void *opaque)
2222{
2223 QEMUResetEntry *re = qemu_mallocz(sizeof(QEMUResetEntry));
2224
2225 re->func = func;
2226 re->opaque = opaque;
2227 QTAILQ_INSERT_TAIL(&reset_handlers, re, entry);
2228}
2229
2230void qemu_unregister_reset(QEMUResetHandler *func, void *opaque)
2231{
2232 QEMUResetEntry *re;
2233
2234 QTAILQ_FOREACH(re, &reset_handlers, entry) {
2235 if (re->func == func && re->opaque == opaque) {
2236 QTAILQ_REMOVE(&reset_handlers, re, entry);
2237 qemu_free(re);
2238 return;
2239 }
2240 }
2241}
2242
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002243static void do_vm_stop(int reason)
2244{
2245 if (vm_running) {
2246 cpu_disable_ticks();
2247 vm_running = 0;
2248 pause_all_vcpus();
2249 vm_state_notify(0, reason);
2250 }
2251}
2252
2253void qemu_register_reset(QEMUResetHandler *func, int order, void *opaque)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002254{
2255 QEMUResetEntry **pre, *re;
2256
2257 pre = &first_reset_entry;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002258 while (*pre != NULL && (*pre)->order >= order) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002259 pre = &(*pre)->next;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002260 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002261 re = qemu_mallocz(sizeof(QEMUResetEntry));
2262 re->func = func;
2263 re->opaque = opaque;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002264 re->order = order;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002265 re->next = NULL;
2266 *pre = re;
2267}
2268
2269void qemu_system_reset(void)
2270{
2271 QEMUResetEntry *re;
2272
2273 /* reset all devices */
David Turner025c32f2010-09-10 14:52:42 +02002274 QTAILQ_FOREACH_SAFE(re, &reset_handlers, entry, nre) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002275 re->func(re->opaque);
2276 }
2277}
2278
2279void qemu_system_reset_request(void)
2280{
2281 if (no_reboot) {
2282 shutdown_requested = 1;
2283 } else {
2284 reset_requested = 1;
2285 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002286 qemu_notify_event();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002287}
2288
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002289void qemu_system_shutdown_request(void)
2290{
2291 shutdown_requested = 1;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002292 qemu_notify_event();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002293}
2294
2295void qemu_system_powerdown_request(void)
2296{
2297 powerdown_requested = 1;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002298 qemu_notify_event();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002299}
2300
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002301#ifdef CONFIG_IOTHREAD
2302static void qemu_system_vmstop_request(int reason)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002303{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002304 vmstop_requested = reason;
2305 qemu_notify_event();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002306}
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002307#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002308
2309#ifndef _WIN32
2310static int io_thread_fd = -1;
2311
2312static void qemu_event_increment(void)
2313{
2314 static const char byte = 0;
2315
2316 if (io_thread_fd == -1)
2317 return;
2318
2319 write(io_thread_fd, &byte, sizeof(byte));
2320}
2321
2322static void qemu_event_read(void *opaque)
2323{
2324 int fd = (unsigned long)opaque;
2325 ssize_t len;
2326
2327 /* Drain the notify pipe */
2328 do {
2329 char buffer[512];
2330 len = read(fd, buffer, sizeof(buffer));
2331 } while ((len == -1 && errno == EINTR) || len > 0);
2332}
2333
2334static int qemu_event_init(void)
2335{
2336 int err;
2337 int fds[2];
2338
2339 err = pipe(fds);
2340 if (err == -1)
2341 return -errno;
2342
2343 err = fcntl_setfl(fds[0], O_NONBLOCK);
2344 if (err < 0)
2345 goto fail;
2346
2347 err = fcntl_setfl(fds[1], O_NONBLOCK);
2348 if (err < 0)
2349 goto fail;
2350
2351 qemu_set_fd_handler2(fds[0], NULL, qemu_event_read, NULL,
2352 (void *)(unsigned long)fds[0]);
2353
2354 io_thread_fd = fds[1];
2355 return 0;
2356
2357fail:
2358 close(fds[0]);
2359 close(fds[1]);
2360 return err;
2361}
2362#else
2363HANDLE qemu_event_handle;
2364
2365static void dummy_event_handler(void *opaque)
2366{
2367}
2368
2369static int qemu_event_init(void)
2370{
2371 qemu_event_handle = CreateEvent(NULL, FALSE, FALSE, NULL);
2372 if (!qemu_event_handle) {
2373 perror("Failed CreateEvent");
2374 return -1;
2375 }
2376 qemu_add_wait_object(qemu_event_handle, dummy_event_handler, NULL);
2377 return 0;
2378}
2379
2380static void qemu_event_increment(void)
2381{
2382 SetEvent(qemu_event_handle);
2383}
2384#endif
2385
2386static int cpu_can_run(CPUState *env)
2387{
2388 if (env->stop)
2389 return 0;
2390 if (env->stopped)
2391 return 0;
David 'Digit' Turnera7fb77d2010-05-10 23:50:54 -07002392 if (!vm_running)
2393 return 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002394 return 1;
2395}
2396
2397#ifndef CONFIG_IOTHREAD
2398static int qemu_init_main_loop(void)
2399{
2400 return qemu_event_init();
2401}
2402
2403void qemu_init_vcpu(void *_env)
2404{
2405 CPUState *env = _env;
2406
2407 if (kvm_enabled())
2408 kvm_init_vcpu(env);
2409 return;
2410}
2411
2412int qemu_cpu_self(void *env)
2413{
2414 return 1;
2415}
2416
2417static void resume_all_vcpus(void)
2418{
2419}
2420
2421static void pause_all_vcpus(void)
2422{
2423}
2424
2425void qemu_cpu_kick(void *env)
2426{
2427 return;
2428}
2429
2430void qemu_notify_event(void)
2431{
2432 CPUState *env = cpu_single_env;
2433
2434 if (env) {
2435 cpu_exit(env);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002436 }
2437}
2438
2439#define qemu_mutex_lock_iothread() do { } while (0)
2440#define qemu_mutex_unlock_iothread() do { } while (0)
2441
2442void vm_stop(int reason)
2443{
2444 do_vm_stop(reason);
2445}
2446
2447#else /* CONFIG_IOTHREAD */
2448
2449#include "qemu-thread.h"
2450
2451QemuMutex qemu_global_mutex;
2452static QemuMutex qemu_fair_mutex;
2453
2454static QemuThread io_thread;
2455
2456static QemuThread *tcg_cpu_thread;
2457static QemuCond *tcg_halt_cond;
2458
2459static int qemu_system_ready;
2460/* cpu creation */
2461static QemuCond qemu_cpu_cond;
2462/* system init */
2463static QemuCond qemu_system_cond;
2464static QemuCond qemu_pause_cond;
2465
2466static void block_io_signals(void);
2467static void unblock_io_signals(void);
2468static int tcg_has_work(void);
2469
2470static int qemu_init_main_loop(void)
2471{
2472 int ret;
2473
2474 ret = qemu_event_init();
2475 if (ret)
2476 return ret;
2477
2478 qemu_cond_init(&qemu_pause_cond);
2479 qemu_mutex_init(&qemu_fair_mutex);
2480 qemu_mutex_init(&qemu_global_mutex);
2481 qemu_mutex_lock(&qemu_global_mutex);
2482
2483 unblock_io_signals();
2484 qemu_thread_self(&io_thread);
2485
2486 return 0;
2487}
2488
2489static void qemu_wait_io_event(CPUState *env)
2490{
2491 while (!tcg_has_work())
2492 qemu_cond_timedwait(env->halt_cond, &qemu_global_mutex, 1000);
2493
2494 qemu_mutex_unlock(&qemu_global_mutex);
2495
2496 /*
2497 * Users of qemu_global_mutex can be starved, having no chance
2498 * to acquire it since this path will get to it first.
2499 * So use another lock to provide fairness.
2500 */
2501 qemu_mutex_lock(&qemu_fair_mutex);
2502 qemu_mutex_unlock(&qemu_fair_mutex);
2503
2504 qemu_mutex_lock(&qemu_global_mutex);
2505 if (env->stop) {
2506 env->stop = 0;
2507 env->stopped = 1;
2508 qemu_cond_signal(&qemu_pause_cond);
2509 }
2510}
2511
2512static int qemu_cpu_exec(CPUState *env);
2513
2514static void *kvm_cpu_thread_fn(void *arg)
2515{
2516 CPUState *env = arg;
2517
2518 block_io_signals();
2519 qemu_thread_self(env->thread);
2520
2521 /* signal CPU creation */
2522 qemu_mutex_lock(&qemu_global_mutex);
2523 env->created = 1;
2524 qemu_cond_signal(&qemu_cpu_cond);
2525
2526 /* and wait for machine initialization */
2527 while (!qemu_system_ready)
2528 qemu_cond_timedwait(&qemu_system_cond, &qemu_global_mutex, 100);
2529
2530 while (1) {
2531 if (cpu_can_run(env))
2532 qemu_cpu_exec(env);
2533 qemu_wait_io_event(env);
2534 }
2535
2536 return NULL;
2537}
2538
2539static void tcg_cpu_exec(void);
2540
2541static void *tcg_cpu_thread_fn(void *arg)
2542{
2543 CPUState *env = arg;
2544
2545 block_io_signals();
2546 qemu_thread_self(env->thread);
2547
2548 /* signal CPU creation */
2549 qemu_mutex_lock(&qemu_global_mutex);
2550 for (env = first_cpu; env != NULL; env = env->next_cpu)
2551 env->created = 1;
2552 qemu_cond_signal(&qemu_cpu_cond);
2553
2554 /* and wait for machine initialization */
2555 while (!qemu_system_ready)
2556 qemu_cond_timedwait(&qemu_system_cond, &qemu_global_mutex, 100);
2557
2558 while (1) {
2559 tcg_cpu_exec();
2560 qemu_wait_io_event(cur_cpu);
2561 }
2562
2563 return NULL;
2564}
2565
2566void qemu_cpu_kick(void *_env)
2567{
2568 CPUState *env = _env;
2569 qemu_cond_broadcast(env->halt_cond);
2570 if (kvm_enabled())
2571 qemu_thread_signal(env->thread, SIGUSR1);
2572}
2573
2574int qemu_cpu_self(void *env)
2575{
2576 return (cpu_single_env != NULL);
2577}
2578
2579static void cpu_signal(int sig)
2580{
2581 if (cpu_single_env)
2582 cpu_exit(cpu_single_env);
2583}
2584
2585static void block_io_signals(void)
2586{
2587 sigset_t set;
2588 struct sigaction sigact;
2589
2590 sigemptyset(&set);
2591 sigaddset(&set, SIGUSR2);
2592 sigaddset(&set, SIGIO);
2593 sigaddset(&set, SIGALRM);
2594 pthread_sigmask(SIG_BLOCK, &set, NULL);
2595
2596 sigemptyset(&set);
2597 sigaddset(&set, SIGUSR1);
2598 pthread_sigmask(SIG_UNBLOCK, &set, NULL);
2599
2600 memset(&sigact, 0, sizeof(sigact));
2601 sigact.sa_handler = cpu_signal;
2602 sigaction(SIGUSR1, &sigact, NULL);
2603}
2604
2605static void unblock_io_signals(void)
2606{
2607 sigset_t set;
2608
2609 sigemptyset(&set);
2610 sigaddset(&set, SIGUSR2);
2611 sigaddset(&set, SIGIO);
2612 sigaddset(&set, SIGALRM);
2613 pthread_sigmask(SIG_UNBLOCK, &set, NULL);
2614
2615 sigemptyset(&set);
2616 sigaddset(&set, SIGUSR1);
2617 pthread_sigmask(SIG_BLOCK, &set, NULL);
2618}
2619
2620static void qemu_signal_lock(unsigned int msecs)
2621{
2622 qemu_mutex_lock(&qemu_fair_mutex);
2623
2624 while (qemu_mutex_trylock(&qemu_global_mutex)) {
2625 qemu_thread_signal(tcg_cpu_thread, SIGUSR1);
2626 if (!qemu_mutex_timedlock(&qemu_global_mutex, msecs))
2627 break;
2628 }
2629 qemu_mutex_unlock(&qemu_fair_mutex);
2630}
2631
David 'Digit' Turnerc34e8dc2010-09-13 02:47:01 -07002632void qemu_mutex_lock_iothread(void)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002633{
2634 if (kvm_enabled()) {
2635 qemu_mutex_lock(&qemu_fair_mutex);
2636 qemu_mutex_lock(&qemu_global_mutex);
2637 qemu_mutex_unlock(&qemu_fair_mutex);
2638 } else
2639 qemu_signal_lock(100);
2640}
2641
David 'Digit' Turnerc34e8dc2010-09-13 02:47:01 -07002642void qemu_mutex_unlock_iothread(void)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002643{
2644 qemu_mutex_unlock(&qemu_global_mutex);
2645}
2646
2647static int all_vcpus_paused(void)
2648{
2649 CPUState *penv = first_cpu;
2650
2651 while (penv) {
2652 if (!penv->stopped)
2653 return 0;
2654 penv = (CPUState *)penv->next_cpu;
2655 }
2656
2657 return 1;
2658}
2659
2660static void pause_all_vcpus(void)
2661{
2662 CPUState *penv = first_cpu;
2663
2664 while (penv) {
2665 penv->stop = 1;
2666 qemu_thread_signal(penv->thread, SIGUSR1);
2667 qemu_cpu_kick(penv);
2668 penv = (CPUState *)penv->next_cpu;
2669 }
2670
2671 while (!all_vcpus_paused()) {
2672 qemu_cond_timedwait(&qemu_pause_cond, &qemu_global_mutex, 100);
2673 penv = first_cpu;
2674 while (penv) {
2675 qemu_thread_signal(penv->thread, SIGUSR1);
2676 penv = (CPUState *)penv->next_cpu;
2677 }
2678 }
2679}
2680
2681static void resume_all_vcpus(void)
2682{
2683 CPUState *penv = first_cpu;
2684
2685 while (penv) {
2686 penv->stop = 0;
2687 penv->stopped = 0;
2688 qemu_thread_signal(penv->thread, SIGUSR1);
2689 qemu_cpu_kick(penv);
2690 penv = (CPUState *)penv->next_cpu;
2691 }
2692}
2693
2694static void tcg_init_vcpu(void *_env)
2695{
2696 CPUState *env = _env;
2697 /* share a single thread for all cpus with TCG */
2698 if (!tcg_cpu_thread) {
2699 env->thread = qemu_mallocz(sizeof(QemuThread));
2700 env->halt_cond = qemu_mallocz(sizeof(QemuCond));
2701 qemu_cond_init(env->halt_cond);
2702 qemu_thread_create(env->thread, tcg_cpu_thread_fn, env);
2703 while (env->created == 0)
2704 qemu_cond_timedwait(&qemu_cpu_cond, &qemu_global_mutex, 100);
2705 tcg_cpu_thread = env->thread;
2706 tcg_halt_cond = env->halt_cond;
2707 } else {
2708 env->thread = tcg_cpu_thread;
2709 env->halt_cond = tcg_halt_cond;
2710 }
2711}
2712
2713static void kvm_start_vcpu(CPUState *env)
2714{
2715 kvm_init_vcpu(env);
2716 env->thread = qemu_mallocz(sizeof(QemuThread));
2717 env->halt_cond = qemu_mallocz(sizeof(QemuCond));
2718 qemu_cond_init(env->halt_cond);
2719 qemu_thread_create(env->thread, kvm_cpu_thread_fn, env);
2720 while (env->created == 0)
2721 qemu_cond_timedwait(&qemu_cpu_cond, &qemu_global_mutex, 100);
2722}
2723
2724void qemu_init_vcpu(void *_env)
2725{
2726 CPUState *env = _env;
2727
2728 if (kvm_enabled())
2729 kvm_start_vcpu(env);
2730 else
2731 tcg_init_vcpu(env);
2732}
2733
2734void qemu_notify_event(void)
2735{
2736 qemu_event_increment();
2737}
2738
2739void vm_stop(int reason)
2740{
2741 QemuThread me;
2742 qemu_thread_self(&me);
2743
2744 if (!qemu_thread_equal(&me, &io_thread)) {
2745 qemu_system_vmstop_request(reason);
2746 /*
2747 * FIXME: should not return to device code in case
2748 * vm_stop() has been requested.
2749 */
2750 if (cpu_single_env) {
2751 cpu_exit(cpu_single_env);
2752 cpu_single_env->stop = 1;
2753 }
2754 return;
2755 }
2756 do_vm_stop(reason);
2757}
2758
2759#endif
2760
2761
2762#ifdef _WIN32
2763static void host_main_loop_wait(int *timeout)
2764{
2765 int ret, ret2, i;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002766 PollingEntry *pe;
2767
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002768
2769 /* XXX: need to suppress polling by better using win32 events */
2770 ret = 0;
2771 for(pe = first_polling_entry; pe != NULL; pe = pe->next) {
2772 ret |= pe->func(pe->opaque);
2773 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002774 if (ret == 0) {
2775 int err;
2776 WaitObjects *w = &wait_objects;
2777
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002778 ret = WaitForMultipleObjects(w->num, w->events, FALSE, *timeout);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002779 if (WAIT_OBJECT_0 + 0 <= ret && ret <= WAIT_OBJECT_0 + w->num - 1) {
2780 if (w->func[ret - WAIT_OBJECT_0])
2781 w->func[ret - WAIT_OBJECT_0](w->opaque[ret - WAIT_OBJECT_0]);
2782
2783 /* Check for additional signaled events */
2784 for(i = (ret - WAIT_OBJECT_0 + 1); i < w->num; i++) {
2785
2786 /* Check if event is signaled */
2787 ret2 = WaitForSingleObject(w->events[i], 0);
2788 if(ret2 == WAIT_OBJECT_0) {
2789 if (w->func[i])
2790 w->func[i](w->opaque[i]);
2791 } else if (ret2 == WAIT_TIMEOUT) {
2792 } else {
2793 err = GetLastError();
2794 fprintf(stderr, "WaitForSingleObject error %d %d\n", i, err);
2795 }
2796 }
2797 } else if (ret == WAIT_TIMEOUT) {
2798 } else {
2799 err = GetLastError();
2800 fprintf(stderr, "WaitForMultipleObjects error %d %d\n", ret, err);
2801 }
2802 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002803
2804 *timeout = 0;
2805}
2806#else
2807static void host_main_loop_wait(int *timeout)
2808{
2809}
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002810#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002811
2812void main_loop_wait(int timeout)
2813{
2814 IOHandlerRecord *ioh;
2815 fd_set rfds, wfds, xfds;
2816 int ret, nfds;
2817 struct timeval tv;
2818
2819 qemu_bh_update_timeout(&timeout);
2820
2821 host_main_loop_wait(&timeout);
2822
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002823 /* poll any events */
2824 /* XXX: separate device handlers from system ones */
2825 nfds = -1;
2826 FD_ZERO(&rfds);
2827 FD_ZERO(&wfds);
2828 FD_ZERO(&xfds);
David Turner025c32f2010-09-10 14:52:42 +02002829 QLIST_FOREACH(ioh, &io_handlers, next) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002830 if (ioh->deleted)
2831 continue;
2832 if (ioh->fd_read &&
2833 (!ioh->fd_read_poll ||
2834 ioh->fd_read_poll(ioh->opaque) != 0)) {
2835 FD_SET(ioh->fd, &rfds);
2836 if (ioh->fd > nfds)
2837 nfds = ioh->fd;
2838 }
2839 if (ioh->fd_write) {
2840 FD_SET(ioh->fd, &wfds);
2841 if (ioh->fd > nfds)
2842 nfds = ioh->fd;
2843 }
2844 }
2845
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002846 tv.tv_sec = timeout / 1000;
2847 tv.tv_usec = (timeout % 1000) * 1000;
2848
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002849#if defined(CONFIG_SLIRP)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002850 if (slirp_is_inited()) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002851 slirp_select_fill(&nfds, &rfds, &wfds, &xfds);
2852 }
2853#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002854 qemu_mutex_unlock_iothread();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002855 ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002856 qemu_mutex_lock_iothread();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002857 if (ret > 0) {
David Turner025c32f2010-09-10 14:52:42 +02002858 IOHandlerRecord *pioh;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002859
David Turner025c32f2010-09-10 14:52:42 +02002860 QLIST_FOREACH_SAFE(ioh, &io_handlers, next, pioh) {
2861 if (ioh->deleted) {
2862 QLIST_REMOVE(ioh, next);
2863 qemu_free(ioh);
2864 continue;
2865 }
2866 if (ioh->fd_read && FD_ISSET(ioh->fd, &rfds)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002867 ioh->fd_read(ioh->opaque);
2868 }
David Turner025c32f2010-09-10 14:52:42 +02002869 if (ioh->fd_write && FD_ISSET(ioh->fd, &wfds)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002870 ioh->fd_write(ioh->opaque);
2871 }
2872 }
2873
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002874#if defined(CONFIG_SLIRP)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002875 if (slirp_is_inited()) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002876 if (ret < 0) {
2877 FD_ZERO(&rfds);
2878 FD_ZERO(&wfds);
2879 FD_ZERO(&xfds);
2880 }
2881 slirp_select_poll(&rfds, &wfds, &xfds);
2882 }
2883#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002884
David Turner6a9ef172010-09-09 22:54:36 +02002885 qemu_run_all_timers();
David 'Digit' Turnera7fb77d2010-05-10 23:50:54 -07002886
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002887 /* Check bottom-halves last in case any of the earlier events triggered
2888 them. */
2889 qemu_bh_poll();
2890
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002891}
2892
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002893static int qemu_cpu_exec(CPUState *env)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002894{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002895 int ret;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002896#ifdef CONFIG_PROFILER
2897 int64_t ti;
2898#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002899
2900#ifdef CONFIG_PROFILER
2901 ti = profile_getclock();
2902#endif
2903 if (use_icount) {
2904 int64_t count;
2905 int decr;
2906 qemu_icount -= (env->icount_decr.u16.low + env->icount_extra);
2907 env->icount_decr.u16.low = 0;
2908 env->icount_extra = 0;
2909 count = qemu_next_deadline();
2910 count = (count + (1 << icount_time_shift) - 1)
2911 >> icount_time_shift;
2912 qemu_icount += count;
2913 decr = (count > 0xffff) ? 0xffff : count;
2914 count -= decr;
2915 env->icount_decr.u16.low = decr;
2916 env->icount_extra = count;
2917 }
2918 ret = cpu_exec(env);
2919#ifdef CONFIG_PROFILER
2920 qemu_time += profile_getclock() - ti;
2921#endif
2922 if (use_icount) {
2923 /* Fold pending instructions back into the
2924 instruction counter, and clear the interrupt flag. */
2925 qemu_icount -= (env->icount_decr.u16.low
2926 + env->icount_extra);
2927 env->icount_decr.u32 = 0;
2928 env->icount_extra = 0;
2929 }
2930 return ret;
2931}
2932
2933static void tcg_cpu_exec(void)
2934{
2935 int ret = 0;
2936
2937 if (next_cpu == NULL)
2938 next_cpu = first_cpu;
2939 for (; next_cpu != NULL; next_cpu = next_cpu->next_cpu) {
2940 CPUState *env = cur_cpu = next_cpu;
2941
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002942 if (timer_alarm_pending) {
2943 timer_alarm_pending = 0;
2944 break;
2945 }
2946 if (cpu_can_run(env))
2947 ret = qemu_cpu_exec(env);
David 'Digit' Turnera7fb77d2010-05-10 23:50:54 -07002948 else if (env->stop)
2949 break;
2950
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002951 if (ret == EXCP_DEBUG) {
2952 gdb_set_stop_cpu(env);
2953 debug_requested = 1;
2954 break;
2955 }
2956 }
2957}
2958
David 'Digit' Turnerc34e8dc2010-09-13 02:47:01 -07002959#if 0
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002960static int cpu_has_work(CPUState *env)
2961{
2962 if (env->stop)
2963 return 1;
2964 if (env->stopped)
2965 return 0;
2966 if (!env->halted)
2967 return 1;
2968 if (qemu_cpu_has_work(env))
2969 return 1;
2970 return 0;
2971}
2972
2973static int tcg_has_work(void)
2974{
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002975 CPUState *env;
2976
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002977 for (env = first_cpu; env != NULL; env = env->next_cpu)
2978 if (cpu_has_work(env))
2979 return 1;
2980 return 0;
2981}
David 'Digit' Turnerc34e8dc2010-09-13 02:47:01 -07002982#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002983
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002984static int vm_can_run(void)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002985{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002986 if (powerdown_requested)
2987 return 0;
2988 if (reset_requested)
2989 return 0;
2990 if (shutdown_requested)
2991 return 0;
2992 if (debug_requested)
2993 return 0;
2994 return 1;
2995}
2996
2997static void main_loop(void)
2998{
2999 int r;
3000
3001#ifdef CONFIG_IOTHREAD
3002 qemu_system_ready = 1;
3003 qemu_cond_broadcast(&qemu_system_cond);
3004#endif
3005
3006 for (;;) {
3007 do {
3008#ifdef CONFIG_PROFILER
3009 int64_t ti;
3010#endif
3011#ifndef CONFIG_IOTHREAD
3012 tcg_cpu_exec();
3013#endif
3014#ifdef CONFIG_PROFILER
3015 ti = profile_getclock();
3016#endif
3017 main_loop_wait(qemu_calculate_timeout());
3018#ifdef CONFIG_PROFILER
3019 dev_time += profile_getclock() - ti;
3020#endif
3021 } while (vm_can_run());
3022
3023 if (qemu_debug_requested())
3024 vm_stop(EXCP_DEBUG);
3025 if (qemu_shutdown_requested()) {
3026 if (no_shutdown) {
3027 vm_stop(0);
3028 no_shutdown = 0;
3029 } else
3030 break;
3031 }
3032 if (qemu_reset_requested()) {
3033 pause_all_vcpus();
3034 qemu_system_reset();
3035 resume_all_vcpus();
3036 }
3037 if (qemu_powerdown_requested())
3038 qemu_system_powerdown();
3039 if ((r = qemu_vmstop_requested()))
3040 vm_stop(r);
3041 }
3042 pause_all_vcpus();
3043}
3044
3045static void version(void)
3046{
3047 printf("QEMU PC emulator version " QEMU_VERSION QEMU_PKGVERSION ", Copyright (c) 2003-2008 Fabrice Bellard\n");
3048}
3049
3050static void help(int exitcode)
3051{
3052 version();
3053 printf("usage: %s [options] [disk_image]\n"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003054 "\n"
3055 "'disk_image' is a raw hard image image for IDE hard disk 0\n"
3056 "\n"
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003057#define DEF(option, opt_arg, opt_enum, opt_help) \
3058 opt_help
3059#define DEFHEADING(text) stringify(text) "\n"
3060#include "qemu-options.h"
3061#undef DEF
3062#undef DEFHEADING
3063#undef GEN_DOCS
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003064 "\n"
3065 "During emulation, the following keys are useful:\n"
3066 "ctrl-alt-f toggle full screen\n"
3067 "ctrl-alt-n switch to virtual console 'n'\n"
3068 "ctrl-alt toggle mouse and keyboard grab\n"
3069 "\n"
3070 "When using -nographic, press 'ctrl-a h' to get some help.\n"
3071 ,
3072 "qemu",
3073 DEFAULT_RAM_SIZE,
3074#ifndef _WIN32
3075 DEFAULT_NETWORK_SCRIPT,
3076 DEFAULT_NETWORK_DOWN_SCRIPT,
3077#endif
3078 DEFAULT_GDBSTUB_PORT,
3079 "/tmp/qemu.log");
3080 exit(exitcode);
3081}
3082
3083#define HAS_ARG 0x0001
3084
3085enum {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003086#define DEF(option, opt_arg, opt_enum, opt_help) \
3087 opt_enum,
3088#define DEFHEADING(text)
3089#include "qemu-options.h"
3090#undef DEF
3091#undef DEFHEADING
3092#undef GEN_DOCS
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003093};
3094
3095typedef struct QEMUOption {
3096 const char *name;
3097 int flags;
3098 int index;
3099} QEMUOption;
3100
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003101static const QEMUOption qemu_options[] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003102 { "h", 0, QEMU_OPTION_h },
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003103#define DEF(option, opt_arg, opt_enum, opt_help) \
3104 { option, opt_arg, opt_enum },
3105#define DEFHEADING(text)
3106#include "qemu-options.h"
3107#undef DEF
3108#undef DEFHEADING
3109#undef GEN_DOCS
3110 { NULL },
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003111};
3112
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003113#ifdef HAS_AUDIO
3114struct soundhw soundhw[] = {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003115#ifdef HAS_AUDIO_CHOICE
3116#if defined(TARGET_I386) || defined(TARGET_MIPS)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003117 {
3118 "pcspk",
3119 "PC speaker",
3120 0,
3121 1,
3122 { .init_isa = pcspk_audio_init }
3123 },
3124#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003125
3126#ifdef CONFIG_SB16
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003127 {
3128 "sb16",
3129 "Creative Sound Blaster 16",
3130 0,
3131 1,
3132 { .init_isa = SB16_init }
3133 },
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003134#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003135
3136#ifdef CONFIG_CS4231A
3137 {
3138 "cs4231a",
3139 "CS4231A",
3140 0,
3141 1,
3142 { .init_isa = cs4231a_init }
3143 },
3144#endif
3145
3146#ifdef CONFIG_ADLIB
3147 {
3148 "adlib",
3149#ifdef HAS_YMF262
3150 "Yamaha YMF262 (OPL3)",
3151#else
3152 "Yamaha YM3812 (OPL2)",
3153#endif
3154 0,
3155 1,
3156 { .init_isa = Adlib_init }
3157 },
3158#endif
3159
3160#ifdef CONFIG_GUS
3161 {
3162 "gus",
3163 "Gravis Ultrasound GF1",
3164 0,
3165 1,
3166 { .init_isa = GUS_init }
3167 },
3168#endif
3169
3170#ifdef CONFIG_AC97
3171 {
3172 "ac97",
3173 "Intel 82801AA AC97 Audio",
3174 0,
3175 0,
3176 { .init_pci = ac97_init }
3177 },
3178#endif
3179
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003180#ifdef CONFIG_ES1370
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003181 {
3182 "es1370",
3183 "ENSONIQ AudioPCI ES1370",
3184 0,
3185 0,
3186 { .init_pci = es1370_init }
3187 },
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003188#endif
3189
3190#endif /* HAS_AUDIO_CHOICE */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003191
3192 { NULL, NULL, 0, 0, { NULL } }
3193};
3194
3195static void select_soundhw (const char *optarg)
3196{
3197 struct soundhw *c;
3198
3199 if (*optarg == '?') {
3200 show_valid_cards:
3201
3202 printf ("Valid sound card names (comma separated):\n");
3203 for (c = soundhw; c->name; ++c) {
3204 printf ("%-11s %s\n", c->name, c->descr);
3205 }
3206 printf ("\n-soundhw all will enable all of the above\n");
3207 exit (*optarg != '?');
3208 }
3209 else {
3210 size_t l;
3211 const char *p;
3212 char *e;
3213 int bad_card = 0;
3214
3215 if (!strcmp (optarg, "all")) {
3216 for (c = soundhw; c->name; ++c) {
3217 c->enabled = 1;
3218 }
3219 return;
3220 }
3221
3222 p = optarg;
3223 while (*p) {
3224 e = strchr (p, ',');
3225 l = !e ? strlen (p) : (size_t) (e - p);
3226
3227 for (c = soundhw; c->name; ++c) {
3228 if (!strncmp (c->name, p, l)) {
3229 c->enabled = 1;
3230 break;
3231 }
3232 }
3233
3234 if (!c->name) {
3235 if (l > 80) {
3236 fprintf (stderr,
3237 "Unknown sound card name (too big to show)\n");
3238 }
3239 else {
3240 fprintf (stderr, "Unknown sound card name `%.*s'\n",
3241 (int) l, p);
3242 }
3243 bad_card = 1;
3244 }
3245 p += l + (e != NULL);
3246 }
3247
3248 if (bad_card)
3249 goto show_valid_cards;
3250 }
3251}
3252#endif
3253
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003254static void select_vgahw (const char *p)
3255{
3256 const char *opts;
3257
3258 cirrus_vga_enabled = 0;
3259 std_vga_enabled = 0;
3260 vmsvga_enabled = 0;
3261 xenfb_enabled = 0;
3262 if (strstart(p, "std", &opts)) {
3263 std_vga_enabled = 1;
3264 } else if (strstart(p, "cirrus", &opts)) {
3265 cirrus_vga_enabled = 1;
3266 } else if (strstart(p, "vmware", &opts)) {
3267 vmsvga_enabled = 1;
3268 } else if (strstart(p, "xenfb", &opts)) {
3269 xenfb_enabled = 1;
3270 } else if (!strstart(p, "none", &opts)) {
3271 invalid_vga:
3272 fprintf(stderr, "Unknown vga type: %s\n", p);
3273 exit(1);
3274 }
3275 while (*opts) {
3276 const char *nextopt;
3277
3278 if (strstart(opts, ",retrace=", &nextopt)) {
3279 opts = nextopt;
3280 if (strstart(opts, "dumb", &nextopt))
3281 vga_retrace_method = VGA_RETRACE_DUMB;
3282 else if (strstart(opts, "precise", &nextopt))
3283 vga_retrace_method = VGA_RETRACE_PRECISE;
3284 else goto invalid_vga;
3285 } else goto invalid_vga;
3286 opts = nextopt;
3287 }
3288}
3289
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003290#ifdef _WIN32
3291static BOOL WINAPI qemu_ctrl_handler(DWORD type)
3292{
3293 exit(STATUS_CONTROL_C_EXIT);
3294 return TRUE;
3295}
3296#endif
3297
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003298int qemu_uuid_parse(const char *str, uint8_t *uuid)
3299{
3300 int ret;
3301
3302 if(strlen(str) != 36)
3303 return -1;
3304
3305 ret = sscanf(str, UUID_FMT, &uuid[0], &uuid[1], &uuid[2], &uuid[3],
3306 &uuid[4], &uuid[5], &uuid[6], &uuid[7], &uuid[8], &uuid[9],
3307 &uuid[10], &uuid[11], &uuid[12], &uuid[13], &uuid[14], &uuid[15]);
3308
3309 if(ret != 16)
3310 return -1;
3311
3312#ifdef TARGET_I386
3313 smbios_add_field(1, offsetof(struct smbios_type_1, uuid), 16, uuid);
3314#endif
3315
3316 return 0;
3317}
3318
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003319#define MAX_NET_CLIENTS 32
3320
3321#ifndef _WIN32
3322
3323static void termsig_handler(int signal)
3324{
3325 qemu_system_shutdown_request();
3326}
3327
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003328static void sigchld_handler(int signal)
3329{
3330 waitpid(-1, NULL, WNOHANG);
3331}
3332
3333static void sighandler_setup(void)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003334{
3335 struct sigaction act;
3336
3337 memset(&act, 0, sizeof(act));
3338 act.sa_handler = termsig_handler;
3339 sigaction(SIGINT, &act, NULL);
3340 sigaction(SIGHUP, &act, NULL);
3341 sigaction(SIGTERM, &act, NULL);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003342
3343 act.sa_handler = sigchld_handler;
3344 act.sa_flags = SA_NOCLDSTOP;
3345 sigaction(SIGCHLD, &act, NULL);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003346}
3347
3348#endif
3349
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003350#ifdef _WIN32
3351/* Look for support files in the same directory as the executable. */
3352static char *find_datadir(const char *argv0)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003353{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003354 char *p;
3355 char buf[MAX_PATH];
3356 DWORD len;
3357
3358 len = GetModuleFileName(NULL, buf, sizeof(buf) - 1);
3359 if (len == 0) {
3360 return NULL;
3361 }
3362
3363 buf[len] = 0;
3364 p = buf + len - 1;
3365 while (p != buf && *p != '\\')
3366 p--;
3367 *p = 0;
3368 if (access(buf, R_OK) == 0) {
3369 return qemu_strdup(buf);
3370 }
3371 return NULL;
3372}
3373#else /* !_WIN32 */
3374
3375/* Find a likely location for support files using the location of the binary.
3376 For installed binaries this will be "$bindir/../share/qemu". When
3377 running from the build tree this will be "$bindir/../pc-bios". */
3378#define SHARE_SUFFIX "/share/qemu"
3379#define BUILD_SUFFIX "/pc-bios"
3380static char *find_datadir(const char *argv0)
3381{
3382 char *dir;
3383 char *p = NULL;
3384 char *res;
3385#ifdef PATH_MAX
3386 char buf[PATH_MAX];
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003387#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003388 size_t max_len;
3389
3390#if defined(__linux__)
3391 {
3392 int len;
3393 len = readlink("/proc/self/exe", buf, sizeof(buf) - 1);
3394 if (len > 0) {
3395 buf[len] = 0;
3396 p = buf;
3397 }
3398 }
3399#elif defined(__FreeBSD__)
3400 {
3401 int len;
3402 len = readlink("/proc/curproc/file", buf, sizeof(buf) - 1);
3403 if (len > 0) {
3404 buf[len] = 0;
3405 p = buf;
3406 }
3407 }
3408#endif
3409 /* If we don't have any way of figuring out the actual executable
3410 location then try argv[0]. */
3411 if (!p) {
3412#ifdef PATH_MAX
3413 p = buf;
3414#endif
3415 p = realpath(argv0, p);
3416 if (!p) {
3417 return NULL;
3418 }
3419 }
3420 dir = dirname(p);
3421 dir = dirname(dir);
3422
3423 max_len = strlen(dir) +
3424 MAX(strlen(SHARE_SUFFIX), strlen(BUILD_SUFFIX)) + 1;
3425 res = qemu_mallocz(max_len);
3426 snprintf(res, max_len, "%s%s", dir, SHARE_SUFFIX);
3427 if (access(res, R_OK)) {
3428 snprintf(res, max_len, "%s%s", dir, BUILD_SUFFIX);
3429 if (access(res, R_OK)) {
3430 qemu_free(res);
3431 res = NULL;
3432 }
3433 }
3434#ifndef PATH_MAX
3435 free(p);
3436#endif
3437 return res;
3438}
3439#undef SHARE_SUFFIX
3440#undef BUILD_SUFFIX
3441#endif
3442
3443char *qemu_find_file(int type, const char *name)
3444{
3445 int len;
3446 const char *subdir;
3447 char *buf;
3448
3449 /* If name contains path separators then try it as a straight path. */
3450 if ((strchr(name, '/') || strchr(name, '\\'))
3451 && access(name, R_OK) == 0) {
David Turner025c32f2010-09-10 14:52:42 +02003452 return qemu_strdup(name);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003453 }
3454 switch (type) {
3455 case QEMU_FILE_TYPE_BIOS:
3456 subdir = "";
3457 break;
3458 case QEMU_FILE_TYPE_KEYMAP:
3459 subdir = "keymaps/";
3460 break;
3461 default:
3462 abort();
3463 }
3464 len = strlen(data_dir) + strlen(name) + strlen(subdir) + 2;
3465 buf = qemu_mallocz(len);
3466 snprintf(buf, len, "%s/%s%s", data_dir, subdir, name);
3467 if (access(buf, R_OK)) {
3468 qemu_free(buf);
3469 return NULL;
3470 }
3471 return buf;
3472}
3473
3474int main(int argc, char **argv, char **envp)
3475{
3476 const char *gdbstub_dev = NULL;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003477 uint32_t boot_devices_bitmap = 0;
3478 int i;
3479 int snapshot, linux_boot, net_boot;
David Turner6a9ef172010-09-09 22:54:36 +02003480 const char *icount_option = NULL;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003481 const char *initrd_filename;
3482 const char *kernel_filename, *kernel_cmdline;
3483 const char *boot_devices = "";
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003484 DisplayState *ds;
3485 DisplayChangeListener *dcl;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003486 int cyls, heads, secs, translation;
3487 const char *net_clients[MAX_NET_CLIENTS];
3488 int nb_net_clients;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003489 const char *bt_opts[MAX_BT_CMDLINE];
3490 int nb_bt_opts;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003491 int hda_index;
3492 int optind;
3493 const char *r, *optarg;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003494 CharDriverState *monitor_hd = NULL;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003495 const char *monitor_device;
3496 const char *serial_devices[MAX_SERIAL_PORTS];
3497 int serial_device_index;
3498 const char *parallel_devices[MAX_PARALLEL_PORTS];
3499 int parallel_device_index;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003500 const char *virtio_consoles[MAX_VIRTIO_CONSOLES];
3501 int virtio_console_index;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003502 const char *loadvm = NULL;
3503 QEMUMachine *machine;
3504 const char *cpu_model;
3505 const char *usb_devices[MAX_USB_CMDLINE];
3506 int usb_devices_index;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003507#ifndef _WIN32
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003508 int fds[2];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003509#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003510 int tb_size;
3511 const char *pid_file = NULL;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003512 const char *incoming = NULL;
3513#ifndef _WIN32
3514 int fd = 0;
3515 struct passwd *pwd = NULL;
3516 const char *chroot_dir = NULL;
3517 const char *run_as = NULL;
3518#endif
3519 CPUState *env;
3520 int show_vnc_port = 0;
3521
David 'Digit' Turnera7fb77d2010-05-10 23:50:54 -07003522 init_clocks();
3523
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003524 qemu_cache_utils_init(envp);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003525
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003526 QLIST_INIT (&vm_change_state_head);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003527#ifndef _WIN32
3528 {
3529 struct sigaction act;
3530 sigfillset(&act.sa_mask);
3531 act.sa_flags = 0;
3532 act.sa_handler = SIG_IGN;
3533 sigaction(SIGPIPE, &act, NULL);
3534 }
3535#else
3536 SetConsoleCtrlHandler(qemu_ctrl_handler, TRUE);
3537 /* Note: cpu_interrupt() is currently not SMP safe, so we force
3538 QEMU to run on a single CPU */
3539 {
3540 HANDLE h;
3541 DWORD mask, smask;
3542 int i;
3543 h = GetCurrentProcess();
3544 if (GetProcessAffinityMask(h, &mask, &smask)) {
3545 for(i = 0; i < 32; i++) {
3546 if (mask & (1 << i))
3547 break;
3548 }
3549 if (i != 32) {
3550 mask = 1 << i;
3551 SetProcessAffinityMask(h, mask);
3552 }
3553 }
3554 }
3555#endif
3556
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003557 module_call_init(MODULE_INIT_MACHINE);
3558 machine = find_default_machine();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003559 cpu_model = NULL;
3560 initrd_filename = NULL;
3561 ram_size = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003562 snapshot = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003563 kernel_filename = NULL;
3564 kernel_cmdline = "";
3565 cyls = heads = secs = 0;
3566 translation = BIOS_ATA_TRANSLATION_AUTO;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003567 monitor_device = "vc:80Cx24C";
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003568
3569 serial_devices[0] = "vc:80Cx24C";
3570 for(i = 1; i < MAX_SERIAL_PORTS; i++)
3571 serial_devices[i] = NULL;
3572 serial_device_index = 0;
3573
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003574 parallel_devices[0] = "vc:80Cx24C";
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003575 for(i = 1; i < MAX_PARALLEL_PORTS; i++)
3576 parallel_devices[i] = NULL;
3577 parallel_device_index = 0;
3578
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003579 for(i = 0; i < MAX_VIRTIO_CONSOLES; i++)
3580 virtio_consoles[i] = NULL;
3581 virtio_console_index = 0;
3582
3583 for (i = 0; i < MAX_NODES; i++) {
3584 node_mem[i] = 0;
3585 node_cpumask[i] = 0;
3586 }
3587
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003588 usb_devices_index = 0;
3589
3590 nb_net_clients = 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003591 nb_bt_opts = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003592 nb_drives = 0;
3593 nb_drives_opt = 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003594 nb_numa_nodes = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003595 hda_index = -1;
3596
3597 nb_nics = 0;
3598
3599 tb_size = 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003600 autostart= 1;
3601
3602 register_watchdogs();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003603
3604 optind = 1;
3605 for(;;) {
3606 if (optind >= argc)
3607 break;
3608 r = argv[optind];
3609 if (r[0] != '-') {
3610 hda_index = drive_add(argv[optind++], HD_ALIAS, 0);
3611 } else {
3612 const QEMUOption *popt;
3613
3614 optind++;
3615 /* Treat --foo the same as -foo. */
3616 if (r[1] == '-')
3617 r++;
3618 popt = qemu_options;
3619 for(;;) {
3620 if (!popt->name) {
3621 fprintf(stderr, "%s: invalid option -- '%s'\n",
3622 argv[0], r);
3623 exit(1);
3624 }
3625 if (!strcmp(popt->name, r + 1))
3626 break;
3627 popt++;
3628 }
3629 if (popt->flags & HAS_ARG) {
3630 if (optind >= argc) {
3631 fprintf(stderr, "%s: option '%s' requires an argument\n",
3632 argv[0], r);
3633 exit(1);
3634 }
3635 optarg = argv[optind++];
3636 } else {
3637 optarg = NULL;
3638 }
3639
3640 switch(popt->index) {
3641 case QEMU_OPTION_M:
3642 machine = find_machine(optarg);
3643 if (!machine) {
3644 QEMUMachine *m;
3645 printf("Supported machines are:\n");
3646 for(m = first_machine; m != NULL; m = m->next) {
3647 printf("%-10s %s%s\n",
3648 m->name, m->desc,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003649 m->is_default ? " (default)" : "");
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003650 }
3651 exit(*optarg != '?');
3652 }
3653 break;
3654 case QEMU_OPTION_cpu:
3655 /* hw initialization will check this */
3656 if (*optarg == '?') {
3657/* XXX: implement xxx_cpu_list for targets that still miss it */
3658#if defined(cpu_list)
3659 cpu_list(stdout, &fprintf);
3660#endif
3661 exit(0);
3662 } else {
3663 cpu_model = optarg;
3664 }
3665 break;
3666 case QEMU_OPTION_initrd:
3667 initrd_filename = optarg;
3668 break;
3669 case QEMU_OPTION_hda:
3670 if (cyls == 0)
3671 hda_index = drive_add(optarg, HD_ALIAS, 0);
3672 else
3673 hda_index = drive_add(optarg, HD_ALIAS
3674 ",cyls=%d,heads=%d,secs=%d%s",
3675 0, cyls, heads, secs,
3676 translation == BIOS_ATA_TRANSLATION_LBA ?
3677 ",trans=lba" :
3678 translation == BIOS_ATA_TRANSLATION_NONE ?
3679 ",trans=none" : "");
3680 break;
3681 case QEMU_OPTION_hdb:
3682 case QEMU_OPTION_hdc:
3683 case QEMU_OPTION_hdd:
3684 drive_add(optarg, HD_ALIAS, popt->index - QEMU_OPTION_hda);
3685 break;
3686 case QEMU_OPTION_drive:
3687 drive_add(NULL, "%s", optarg);
3688 break;
3689 case QEMU_OPTION_mtdblock:
3690 drive_add(optarg, MTD_ALIAS);
3691 break;
3692 case QEMU_OPTION_sd:
3693 drive_add(optarg, SD_ALIAS);
3694 break;
3695 case QEMU_OPTION_pflash:
3696 drive_add(optarg, PFLASH_ALIAS);
3697 break;
3698 case QEMU_OPTION_snapshot:
3699 snapshot = 1;
3700 break;
3701 case QEMU_OPTION_hdachs:
3702 {
3703 const char *p;
3704 p = optarg;
3705 cyls = strtol(p, (char **)&p, 0);
3706 if (cyls < 1 || cyls > 16383)
3707 goto chs_fail;
3708 if (*p != ',')
3709 goto chs_fail;
3710 p++;
3711 heads = strtol(p, (char **)&p, 0);
3712 if (heads < 1 || heads > 16)
3713 goto chs_fail;
3714 if (*p != ',')
3715 goto chs_fail;
3716 p++;
3717 secs = strtol(p, (char **)&p, 0);
3718 if (secs < 1 || secs > 63)
3719 goto chs_fail;
3720 if (*p == ',') {
3721 p++;
3722 if (!strcmp(p, "none"))
3723 translation = BIOS_ATA_TRANSLATION_NONE;
3724 else if (!strcmp(p, "lba"))
3725 translation = BIOS_ATA_TRANSLATION_LBA;
3726 else if (!strcmp(p, "auto"))
3727 translation = BIOS_ATA_TRANSLATION_AUTO;
3728 else
3729 goto chs_fail;
3730 } else if (*p != '\0') {
3731 chs_fail:
3732 fprintf(stderr, "qemu: invalid physical CHS format\n");
3733 exit(1);
3734 }
3735 if (hda_index != -1)
3736 snprintf(drives_opt[hda_index].opt,
3737 sizeof(drives_opt[hda_index].opt),
3738 HD_ALIAS ",cyls=%d,heads=%d,secs=%d%s",
3739 0, cyls, heads, secs,
3740 translation == BIOS_ATA_TRANSLATION_LBA ?
3741 ",trans=lba" :
3742 translation == BIOS_ATA_TRANSLATION_NONE ?
3743 ",trans=none" : "");
3744 }
3745 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003746 case QEMU_OPTION_numa:
3747 if (nb_numa_nodes >= MAX_NODES) {
3748 fprintf(stderr, "qemu: too many NUMA nodes\n");
3749 exit(1);
3750 }
3751 numa_add(optarg);
3752 break;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003753 case QEMU_OPTION_nographic:
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003754 display_type = DT_NOGRAPHIC;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003755 break;
3756#ifdef CONFIG_CURSES
3757 case QEMU_OPTION_curses:
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003758 display_type = DT_CURSES;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003759 break;
3760#endif
3761 case QEMU_OPTION_portrait:
3762 graphic_rotate = 1;
3763 break;
3764 case QEMU_OPTION_kernel:
3765 kernel_filename = optarg;
3766 break;
3767 case QEMU_OPTION_append:
3768 kernel_cmdline = optarg;
3769 break;
3770 case QEMU_OPTION_cdrom:
3771 drive_add(optarg, CDROM_ALIAS);
3772 break;
3773 case QEMU_OPTION_boot:
3774 boot_devices = optarg;
3775 /* We just do some generic consistency checks */
3776 {
3777 /* Could easily be extended to 64 devices if needed */
3778 const char *p;
David 'Digit' Turner707c8a82010-12-22 22:35:58 +01003779
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003780 boot_devices_bitmap = 0;
3781 for (p = boot_devices; *p != '\0'; p++) {
3782 /* Allowed boot devices are:
3783 * a b : floppy disk drives
3784 * c ... f : IDE disk drives
3785 * g ... m : machine implementation dependant drives
3786 * n ... p : network devices
3787 * It's up to each machine implementation to check
3788 * if the given boot devices match the actual hardware
3789 * implementation and firmware features.
3790 */
3791 if (*p < 'a' || *p > 'q') {
3792 fprintf(stderr, "Invalid boot device '%c'\n", *p);
3793 exit(1);
3794 }
3795 if (boot_devices_bitmap & (1 << (*p - 'a'))) {
3796 fprintf(stderr,
3797 "Boot device '%c' was given twice\n",*p);
3798 exit(1);
3799 }
3800 boot_devices_bitmap |= 1 << (*p - 'a');
3801 }
3802 }
3803 break;
3804 case QEMU_OPTION_fda:
3805 case QEMU_OPTION_fdb:
3806 drive_add(optarg, FD_ALIAS, popt->index - QEMU_OPTION_fda);
3807 break;
3808#ifdef TARGET_I386
3809 case QEMU_OPTION_no_fd_bootchk:
3810 fd_bootchk = 0;
3811 break;
3812#endif
3813 case QEMU_OPTION_net:
3814 if (nb_net_clients >= MAX_NET_CLIENTS) {
3815 fprintf(stderr, "qemu: too many network clients\n");
3816 exit(1);
3817 }
3818 net_clients[nb_net_clients] = optarg;
3819 nb_net_clients++;
3820 break;
3821#ifdef CONFIG_SLIRP
3822 case QEMU_OPTION_tftp:
3823 tftp_prefix = optarg;
3824 break;
3825 case QEMU_OPTION_bootp:
3826 bootp_filename = optarg;
3827 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003828#ifndef _WIN32
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003829 case QEMU_OPTION_smb:
3830 net_slirp_smb(optarg);
3831 break;
3832#endif
3833 case QEMU_OPTION_redir:
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003834 net_slirp_redir(NULL, optarg, NULL);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003835 break;
3836#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003837 case QEMU_OPTION_bt:
3838 if (nb_bt_opts >= MAX_BT_CMDLINE) {
3839 fprintf(stderr, "qemu: too many bluetooth options\n");
3840 exit(1);
3841 }
3842 bt_opts[nb_bt_opts++] = optarg;
3843 break;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003844#ifdef HAS_AUDIO
3845 case QEMU_OPTION_audio_help:
3846 AUD_help ();
3847 exit (0);
3848 break;
3849 case QEMU_OPTION_soundhw:
3850 select_soundhw (optarg);
3851 break;
3852#endif
3853 case QEMU_OPTION_h:
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003854 help(0);
3855 break;
3856 case QEMU_OPTION_version:
3857 version();
3858 exit(0);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003859 break;
3860 case QEMU_OPTION_m: {
3861 uint64_t value;
3862 char *ptr;
3863
3864 value = strtoul(optarg, &ptr, 10);
3865 switch (*ptr) {
3866 case 0: case 'M': case 'm':
3867 value <<= 20;
3868 break;
3869 case 'G': case 'g':
3870 value <<= 30;
3871 break;
3872 default:
3873 fprintf(stderr, "qemu: invalid ram size: %s\n", optarg);
3874 exit(1);
3875 }
3876
3877 /* On 32-bit hosts, QEMU is limited by virtual address space */
David Turner025c32f2010-09-10 14:52:42 +02003878 if (value > (2047 << 20) && HOST_LONG_BITS == 32) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003879 fprintf(stderr, "qemu: at most 2047 MB RAM can be simulated\n");
3880 exit(1);
3881 }
3882 if (value != (uint64_t)(ram_addr_t)value) {
3883 fprintf(stderr, "qemu: ram size too large\n");
3884 exit(1);
3885 }
3886 ram_size = value;
3887 break;
3888 }
3889 case QEMU_OPTION_d:
3890 {
3891 int mask;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003892 const CPULogItem *item;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003893
3894 mask = cpu_str_to_log_mask(optarg);
3895 if (!mask) {
3896 printf("Log items (comma separated):\n");
3897 for(item = cpu_log_items; item->mask != 0; item++) {
3898 printf("%-10s %s\n", item->name, item->help);
3899 }
3900 exit(1);
3901 }
3902 cpu_set_log(mask);
3903 }
3904 break;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003905 case QEMU_OPTION_s:
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003906 gdbstub_dev = "tcp::" DEFAULT_GDBSTUB_PORT;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003907 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003908 case QEMU_OPTION_gdb:
3909 gdbstub_dev = optarg;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003910 break;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003911 case QEMU_OPTION_L:
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003912 data_dir = optarg;
3913 break;
3914 case QEMU_OPTION_bios:
3915 bios_name = optarg;
3916 break;
3917 case QEMU_OPTION_singlestep:
3918 singlestep = 1;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003919 break;
3920 case QEMU_OPTION_S:
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003921 autostart = 0;
3922 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003923#ifndef _WIN32
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003924 case QEMU_OPTION_k:
3925 keyboard_layout = optarg;
3926 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003927#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003928 case QEMU_OPTION_localtime:
3929 rtc_utc = 0;
3930 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003931 case QEMU_OPTION_vga:
3932 select_vgahw (optarg);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003933 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003934#if defined(TARGET_PPC) || defined(TARGET_SPARC)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003935 case QEMU_OPTION_g:
3936 {
3937 const char *p;
3938 int w, h, depth;
3939 p = optarg;
3940 w = strtol(p, (char **)&p, 10);
3941 if (w <= 0) {
3942 graphic_error:
3943 fprintf(stderr, "qemu: invalid resolution or depth\n");
3944 exit(1);
3945 }
3946 if (*p != 'x')
3947 goto graphic_error;
3948 p++;
3949 h = strtol(p, (char **)&p, 10);
3950 if (h <= 0)
3951 goto graphic_error;
3952 if (*p == 'x') {
3953 p++;
3954 depth = strtol(p, (char **)&p, 10);
3955 if (depth != 8 && depth != 15 && depth != 16 &&
3956 depth != 24 && depth != 32)
3957 goto graphic_error;
3958 } else if (*p == '\0') {
3959 depth = graphic_depth;
3960 } else {
3961 goto graphic_error;
3962 }
3963
3964 graphic_width = w;
3965 graphic_height = h;
3966 graphic_depth = depth;
3967 }
3968 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003969#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003970 case QEMU_OPTION_echr:
3971 {
3972 char *r;
3973 term_escape_char = strtol(optarg, &r, 0);
3974 if (r == optarg)
3975 printf("Bad argument to echr\n");
3976 break;
3977 }
3978 case QEMU_OPTION_monitor:
3979 monitor_device = optarg;
3980 break;
3981 case QEMU_OPTION_serial:
3982 if (serial_device_index >= MAX_SERIAL_PORTS) {
3983 fprintf(stderr, "qemu: too many serial ports\n");
3984 exit(1);
3985 }
3986 serial_devices[serial_device_index] = optarg;
3987 serial_device_index++;
3988 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003989 case QEMU_OPTION_watchdog:
3990 i = select_watchdog(optarg);
3991 if (i > 0)
3992 exit (i == 1 ? 1 : 0);
3993 break;
3994 case QEMU_OPTION_watchdog_action:
3995 if (select_watchdog_action(optarg) == -1) {
3996 fprintf(stderr, "Unknown -watchdog-action parameter\n");
3997 exit(1);
3998 }
3999 break;
4000 case QEMU_OPTION_virtiocon:
4001 if (virtio_console_index >= MAX_VIRTIO_CONSOLES) {
4002 fprintf(stderr, "qemu: too many virtio consoles\n");
4003 exit(1);
4004 }
4005 virtio_consoles[virtio_console_index] = optarg;
4006 virtio_console_index++;
4007 break;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004008 case QEMU_OPTION_parallel:
4009 if (parallel_device_index >= MAX_PARALLEL_PORTS) {
4010 fprintf(stderr, "qemu: too many parallel ports\n");
4011 exit(1);
4012 }
4013 parallel_devices[parallel_device_index] = optarg;
4014 parallel_device_index++;
4015 break;
4016 case QEMU_OPTION_loadvm:
4017 loadvm = optarg;
4018 break;
4019 case QEMU_OPTION_full_screen:
4020 full_screen = 1;
4021 break;
4022#ifdef CONFIG_SDL
4023 case QEMU_OPTION_no_frame:
4024 no_frame = 1;
4025 break;
4026 case QEMU_OPTION_alt_grab:
4027 alt_grab = 1;
4028 break;
4029 case QEMU_OPTION_no_quit:
4030 no_quit = 1;
4031 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004032 case QEMU_OPTION_sdl:
4033 display_type = DT_SDL;
4034 break;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004035#endif
4036 case QEMU_OPTION_pidfile:
4037 pid_file = optarg;
4038 break;
4039#ifdef TARGET_I386
4040 case QEMU_OPTION_win2k_hack:
4041 win2k_install_hack = 1;
4042 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004043 case QEMU_OPTION_rtc_td_hack:
4044 rtc_td_hack = 1;
4045 break;
4046 case QEMU_OPTION_acpitable:
4047 if(acpi_table_add(optarg) < 0) {
4048 fprintf(stderr, "Wrong acpi table provided\n");
4049 exit(1);
4050 }
4051 break;
4052 case QEMU_OPTION_smbios:
4053 if(smbios_entry_add(optarg) < 0) {
4054 fprintf(stderr, "Wrong smbios provided\n");
4055 exit(1);
4056 }
4057 break;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004058#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004059#ifdef CONFIG_KQEMU
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004060 case QEMU_OPTION_no_kqemu:
4061 kqemu_allowed = 0;
4062 break;
4063 case QEMU_OPTION_kernel_kqemu:
4064 kqemu_allowed = 2;
4065 break;
4066#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004067#ifdef CONFIG_KVM
4068 case QEMU_OPTION_enable_kvm:
4069 kvm_allowed = 1;
4070#ifdef CONFIG_KQEMU
4071 kqemu_allowed = 0;
4072#endif
4073 break;
4074#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004075 case QEMU_OPTION_usb:
4076 usb_enabled = 1;
4077 break;
4078 case QEMU_OPTION_usbdevice:
4079 usb_enabled = 1;
4080 if (usb_devices_index >= MAX_USB_CMDLINE) {
4081 fprintf(stderr, "Too many USB devices\n");
4082 exit(1);
4083 }
4084 usb_devices[usb_devices_index] = optarg;
4085 usb_devices_index++;
4086 break;
4087 case QEMU_OPTION_smp:
4088 smp_cpus = atoi(optarg);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004089 if (smp_cpus < 1) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004090 fprintf(stderr, "Invalid number of CPUs\n");
4091 exit(1);
4092 }
4093 break;
4094 case QEMU_OPTION_vnc:
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004095 display_type = DT_VNC;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004096 vnc_display = optarg;
4097 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004098#ifdef TARGET_I386
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004099 case QEMU_OPTION_no_acpi:
4100 acpi_enabled = 0;
4101 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004102 case QEMU_OPTION_no_hpet:
4103 no_hpet = 1;
4104 break;
4105 case QEMU_OPTION_no_virtio_balloon:
4106 no_virtio_balloon = 1;
4107 break;
4108#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004109 case QEMU_OPTION_no_reboot:
4110 no_reboot = 1;
4111 break;
4112 case QEMU_OPTION_no_shutdown:
4113 no_shutdown = 1;
4114 break;
4115 case QEMU_OPTION_show_cursor:
4116 cursor_hide = 0;
4117 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004118 case QEMU_OPTION_uuid:
4119 if(qemu_uuid_parse(optarg, qemu_uuid) < 0) {
4120 fprintf(stderr, "Fail to parse UUID string."
4121 " Wrong format.\n");
4122 exit(1);
4123 }
4124 break;
4125#ifndef _WIN32
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004126 case QEMU_OPTION_daemonize:
4127 daemonize = 1;
4128 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004129#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004130 case QEMU_OPTION_option_rom:
4131 if (nb_option_roms >= MAX_OPTION_ROMS) {
4132 fprintf(stderr, "Too many option ROMs\n");
4133 exit(1);
4134 }
4135 option_rom[nb_option_roms] = optarg;
4136 nb_option_roms++;
4137 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004138#if defined(TARGET_ARM) || defined(TARGET_M68K)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004139 case QEMU_OPTION_semihosting:
4140 semihosting_enabled = 1;
4141 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004142#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004143 case QEMU_OPTION_name:
4144 qemu_name = optarg;
4145 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004146#if defined(TARGET_SPARC) || defined(TARGET_PPC)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004147 case QEMU_OPTION_prom_env:
4148 if (nb_prom_envs >= MAX_PROM_ENVS) {
4149 fprintf(stderr, "Too many prom variables\n");
4150 exit(1);
4151 }
4152 prom_envs[nb_prom_envs] = optarg;
4153 nb_prom_envs++;
4154 break;
4155#endif
4156#ifdef TARGET_ARM
4157 case QEMU_OPTION_old_param:
4158 old_param = 1;
4159 break;
4160#endif
4161 case QEMU_OPTION_clock:
4162 configure_alarms(optarg);
4163 break;
4164 case QEMU_OPTION_startdate:
4165 {
4166 struct tm tm;
4167 time_t rtc_start_date;
4168 if (!strcmp(optarg, "now")) {
4169 rtc_date_offset = -1;
4170 } else {
4171 if (sscanf(optarg, "%d-%d-%dT%d:%d:%d",
4172 &tm.tm_year,
4173 &tm.tm_mon,
4174 &tm.tm_mday,
4175 &tm.tm_hour,
4176 &tm.tm_min,
4177 &tm.tm_sec) == 6) {
4178 /* OK */
4179 } else if (sscanf(optarg, "%d-%d-%d",
4180 &tm.tm_year,
4181 &tm.tm_mon,
4182 &tm.tm_mday) == 3) {
4183 tm.tm_hour = 0;
4184 tm.tm_min = 0;
4185 tm.tm_sec = 0;
4186 } else {
4187 goto date_fail;
4188 }
4189 tm.tm_year -= 1900;
4190 tm.tm_mon--;
4191 rtc_start_date = mktimegm(&tm);
4192 if (rtc_start_date == -1) {
4193 date_fail:
4194 fprintf(stderr, "Invalid date format. Valid format are:\n"
4195 "'now' or '2006-06-17T16:01:21' or '2006-06-17'\n");
4196 exit(1);
4197 }
4198 rtc_date_offset = time(NULL) - rtc_start_date;
4199 }
4200 }
4201 break;
4202 case QEMU_OPTION_tb_size:
4203 tb_size = strtol(optarg, NULL, 0);
4204 if (tb_size < 0)
4205 tb_size = 0;
4206 break;
4207 case QEMU_OPTION_icount:
David Turner6a9ef172010-09-09 22:54:36 +02004208 icount_option = optarg;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004209 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004210 case QEMU_OPTION_incoming:
4211 incoming = optarg;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004212 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004213#ifndef _WIN32
4214 case QEMU_OPTION_chroot:
4215 chroot_dir = optarg;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004216 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004217 case QEMU_OPTION_runas:
4218 run_as = optarg;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004219 break;
4220#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004221#ifdef CONFIG_XEN
4222 case QEMU_OPTION_xen_domid:
4223 xen_domid = atoi(optarg);
4224 break;
4225 case QEMU_OPTION_xen_create:
4226 xen_mode = XEN_CREATE;
4227 break;
4228 case QEMU_OPTION_xen_attach:
4229 xen_mode = XEN_ATTACH;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004230 break;
4231#endif
4232 }
4233 }
4234 }
4235
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004236 /* If no data_dir is specified then try to find it relative to the
4237 executable path. */
4238 if (!data_dir) {
4239 data_dir = find_datadir(argv[0]);
4240 }
4241 /* If all else fails use the install patch specified when building. */
4242 if (!data_dir) {
4243 data_dir = CONFIG_QEMU_SHAREDIR;
4244 }
4245
4246#if defined(CONFIG_KVM) && defined(CONFIG_KQEMU)
4247 if (kvm_allowed && kqemu_allowed) {
4248 fprintf(stderr,
4249 "You can not enable both KVM and kqemu at the same time\n");
4250 exit(1);
4251 }
4252#endif
4253
4254 machine->max_cpus = machine->max_cpus ?: 1; /* Default to UP */
4255 if (smp_cpus > machine->max_cpus) {
4256 fprintf(stderr, "Number of SMP cpus requested (%d), exceeds max cpus "
4257 "supported by machine `%s' (%d)\n", smp_cpus, machine->name,
4258 machine->max_cpus);
4259 exit(1);
4260 }
4261
4262 if (display_type == DT_NOGRAPHIC) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004263 if (serial_device_index == 0)
4264 serial_devices[0] = "stdio";
4265 if (parallel_device_index == 0)
4266 parallel_devices[0] = "null";
4267 if (strncmp(monitor_device, "vc", 2) == 0)
4268 monitor_device = "stdio";
4269 }
4270
4271#ifndef _WIN32
4272 if (daemonize) {
4273 pid_t pid;
4274
4275 if (pipe(fds) == -1)
4276 exit(1);
4277
4278 pid = fork();
4279 if (pid > 0) {
4280 uint8_t status;
4281 ssize_t len;
4282
4283 close(fds[1]);
4284
4285 again:
4286 len = read(fds[0], &status, 1);
4287 if (len == -1 && (errno == EINTR))
4288 goto again;
4289
4290 if (len != 1)
4291 exit(1);
4292 else if (status == 1) {
4293 fprintf(stderr, "Could not acquire pidfile\n");
4294 exit(1);
4295 } else
4296 exit(0);
4297 } else if (pid < 0)
4298 exit(1);
4299
4300 setsid();
4301
4302 pid = fork();
4303 if (pid > 0)
4304 exit(0);
4305 else if (pid < 0)
4306 exit(1);
4307
4308 umask(027);
4309
4310 signal(SIGTSTP, SIG_IGN);
4311 signal(SIGTTOU, SIG_IGN);
4312 signal(SIGTTIN, SIG_IGN);
4313 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004314
4315 if (pid_file && qemu_create_pidfile(pid_file) != 0) {
4316 if (daemonize) {
4317 uint8_t status = 1;
4318 write(fds[1], &status, 1);
4319 } else
4320 fprintf(stderr, "Could not acquire pid file\n");
4321 exit(1);
4322 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004323#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004324
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004325#ifdef CONFIG_KQEMU
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004326 if (smp_cpus > 1)
4327 kqemu_allowed = 0;
4328#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004329 if (qemu_init_main_loop()) {
4330 fprintf(stderr, "qemu_init_main_loop failed\n");
4331 exit(1);
4332 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004333 linux_boot = (kernel_filename != NULL);
4334 net_boot = (boot_devices_bitmap >> ('n' - 'a')) & 0xF;
4335
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004336 if (!linux_boot && *kernel_cmdline != '\0') {
4337 fprintf(stderr, "-append only allowed with -kernel option\n");
4338 exit(1);
4339 }
4340
4341 if (!linux_boot && initrd_filename != NULL) {
4342 fprintf(stderr, "-initrd only allowed with -kernel option\n");
4343 exit(1);
4344 }
4345
4346 /* boot to floppy or the default cd if no hard disk defined yet */
4347 if (!boot_devices[0]) {
4348 boot_devices = "cad";
4349 }
4350 setvbuf(stdout, NULL, _IOLBF, 0);
4351
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004352 if (init_timer_alarm() < 0) {
4353 fprintf(stderr, "could not initialize alarm timer\n");
4354 exit(1);
4355 }
David Turner6a9ef172010-09-09 22:54:36 +02004356 configure_icount(icount_option);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004357
4358#ifdef _WIN32
4359 socket_init();
4360#endif
4361
4362 /* init network clients */
4363 if (nb_net_clients == 0) {
4364 /* if no clients, we use a default config */
4365 net_clients[nb_net_clients++] = "nic";
4366#ifdef CONFIG_SLIRP
4367 net_clients[nb_net_clients++] = "user";
4368#endif
4369 }
4370
4371 for(i = 0;i < nb_net_clients; i++) {
4372 if (net_client_parse(net_clients[i]) < 0)
4373 exit(1);
4374 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004375 net_client_check();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004376
4377#ifdef TARGET_I386
4378 /* XXX: this should be moved in the PC machine instantiation code */
4379 if (net_boot != 0) {
4380 int netroms = 0;
4381 for (i = 0; i < nb_nics && i < 4; i++) {
4382 const char *model = nd_table[i].model;
4383 char buf[1024];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004384 char *filename;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004385 if (net_boot & (1 << i)) {
4386 if (model == NULL)
4387 model = "ne2k_pci";
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004388 snprintf(buf, sizeof(buf), "pxe-%s.bin", model);
4389 filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, buf);
4390 if (filename && get_image_size(filename) > 0) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004391 if (nb_option_roms >= MAX_OPTION_ROMS) {
4392 fprintf(stderr, "Too many option ROMs\n");
4393 exit(1);
4394 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004395 option_rom[nb_option_roms] = qemu_strdup(buf);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004396 nb_option_roms++;
4397 netroms++;
4398 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004399 if (filename) {
4400 qemu_free(filename);
4401 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004402 }
4403 }
4404 if (netroms == 0) {
4405 fprintf(stderr, "No valid PXE rom found for network device\n");
4406 exit(1);
4407 }
4408 }
4409#endif
4410
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004411 /* init the bluetooth world */
4412 for (i = 0; i < nb_bt_opts; i++)
4413 if (bt_parse(bt_opts[i]))
4414 exit(1);
4415
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004416 /* init the memory */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004417 if (ram_size == 0)
4418 ram_size = DEFAULT_RAM_SIZE * 1024 * 1024;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004419
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004420#ifdef CONFIG_KQEMU
4421 /* FIXME: This is a nasty hack because kqemu can't cope with dynamic
4422 guest ram allocation. It needs to go away. */
4423 if (kqemu_allowed) {
4424 kqemu_phys_ram_size = ram_size + 8 * 1024 * 1024 + 4 * 1024 * 1024;
4425 kqemu_phys_ram_base = qemu_vmalloc(kqemu_phys_ram_size);
4426 if (!kqemu_phys_ram_base) {
4427 fprintf(stderr, "Could not allocate physical memory\n");
4428 exit(1);
4429 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004430 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004431#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004432
4433 /* init the dynamic translator */
4434 cpu_exec_init_all(tb_size * 1024 * 1024);
4435
4436 bdrv_init();
4437
4438 /* we always create the cdrom drive, even if no disk is there */
4439
4440 if (nb_drives_opt < MAX_DRIVES)
4441 drive_add(NULL, CDROM_ALIAS);
4442
4443 /* we always create at least one floppy */
4444
4445 if (nb_drives_opt < MAX_DRIVES)
4446 drive_add(NULL, FD_ALIAS, 0);
4447
4448 /* we always create one sd slot, even if no card is in it */
4449
David 'Digit' Turnercb42a1b2010-12-23 02:54:08 +01004450 if (nb_drives_opt < MAX_DRIVES) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004451 drive_add(NULL, SD_ALIAS);
David 'Digit' Turnercb42a1b2010-12-23 02:54:08 +01004452 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004453
4454 /* open the virtual block devices */
David 'Digit' Turnercb42a1b2010-12-23 02:54:08 +01004455 if (snapshot)
4456 qemu_opts_foreach(qemu_find_opts("drive"), drive_enable_snapshot, NULL, 0);
4457 if (qemu_opts_foreach(qemu_find_opts("drive"), drive_init_func, &machine->use_scsi, 1) != 0)
4458 exit(1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004459
David Turner6a9ef172010-09-09 22:54:36 +02004460 //register_savevm("timer", 0, 2, timer_save, timer_load, NULL);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004461 register_savevm_live("ram", 0, 3, ram_save_live, NULL, ram_load, NULL);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004462
4463#ifndef _WIN32
4464 /* must be after terminal init, SDL library changes signal handlers */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004465 sighandler_setup();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004466#endif
4467
4468 /* Maintain compatibility with multiple stdio monitors */
4469 if (!strcmp(monitor_device,"stdio")) {
4470 for (i = 0; i < MAX_SERIAL_PORTS; i++) {
4471 const char *devname = serial_devices[i];
4472 if (devname && !strcmp(devname,"mon:stdio")) {
4473 monitor_device = NULL;
4474 break;
4475 } else if (devname && !strcmp(devname,"stdio")) {
4476 monitor_device = NULL;
4477 serial_devices[i] = "mon:stdio";
4478 break;
4479 }
4480 }
4481 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004482
4483 if (nb_numa_nodes > 0) {
4484 int i;
4485
4486 if (nb_numa_nodes > smp_cpus) {
4487 nb_numa_nodes = smp_cpus;
4488 }
4489
4490 /* If no memory size if given for any node, assume the default case
4491 * and distribute the available memory equally across all nodes
4492 */
4493 for (i = 0; i < nb_numa_nodes; i++) {
4494 if (node_mem[i] != 0)
4495 break;
4496 }
4497 if (i == nb_numa_nodes) {
4498 uint64_t usedmem = 0;
4499
4500 /* On Linux, the each node's border has to be 8MB aligned,
4501 * the final node gets the rest.
4502 */
4503 for (i = 0; i < nb_numa_nodes - 1; i++) {
4504 node_mem[i] = (ram_size / nb_numa_nodes) & ~((1 << 23UL) - 1);
4505 usedmem += node_mem[i];
4506 }
4507 node_mem[i] = ram_size - usedmem;
4508 }
4509
4510 for (i = 0; i < nb_numa_nodes; i++) {
4511 if (node_cpumask[i] != 0)
4512 break;
4513 }
4514 /* assigning the VCPUs round-robin is easier to implement, guest OSes
4515 * must cope with this anyway, because there are BIOSes out there in
4516 * real machines which also use this scheme.
4517 */
4518 if (i == nb_numa_nodes) {
4519 for (i = 0; i < smp_cpus; i++) {
4520 node_cpumask[i % nb_numa_nodes] |= 1 << i;
4521 }
4522 }
4523 }
4524
4525 if (kvm_enabled()) {
4526 int ret;
4527
4528 ret = kvm_init(smp_cpus);
4529 if (ret < 0) {
4530 fprintf(stderr, "failed to initialize KVM\n");
4531 exit(1);
4532 }
4533 }
4534
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004535 if (monitor_device) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004536 monitor_hd = qemu_chr_open("monitor", monitor_device, NULL);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004537 if (!monitor_hd) {
4538 fprintf(stderr, "qemu: could not open monitor device '%s'\n", monitor_device);
4539 exit(1);
4540 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004541 }
4542
4543 for(i = 0; i < MAX_SERIAL_PORTS; i++) {
4544 const char *devname = serial_devices[i];
4545 if (devname && strcmp(devname, "none")) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004546 char label[32];
4547 snprintf(label, sizeof(label), "serial%d", i);
4548 serial_hds[i] = qemu_chr_open(label, devname, NULL);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004549 if (!serial_hds[i]) {
4550 fprintf(stderr, "qemu: could not open serial device '%s'\n",
4551 devname);
4552 exit(1);
4553 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004554 }
4555 }
4556
4557 for(i = 0; i < MAX_PARALLEL_PORTS; i++) {
4558 const char *devname = parallel_devices[i];
4559 if (devname && strcmp(devname, "none")) {
4560 char label[32];
4561 snprintf(label, sizeof(label), "parallel%d", i);
4562 parallel_hds[i] = qemu_chr_open(label, devname, NULL);
4563 if (!parallel_hds[i]) {
4564 fprintf(stderr, "qemu: could not open parallel device '%s'\n",
4565 devname);
4566 exit(1);
4567 }
4568 }
4569 }
4570
4571 for(i = 0; i < MAX_VIRTIO_CONSOLES; i++) {
4572 const char *devname = virtio_consoles[i];
4573 if (devname && strcmp(devname, "none")) {
4574 char label[32];
4575 snprintf(label, sizeof(label), "virtcon%d", i);
4576 virtcon_hds[i] = qemu_chr_open(label, devname, NULL);
4577 if (!virtcon_hds[i]) {
4578 fprintf(stderr, "qemu: could not open virtio console '%s'\n",
4579 devname);
4580 exit(1);
4581 }
4582 }
4583 }
4584
4585 module_call_init(MODULE_INIT_DEVICE);
4586
4587 machine->init(ram_size, boot_devices,
4588 kernel_filename, kernel_cmdline, initrd_filename, cpu_model);
4589
4590
4591 for (env = first_cpu; env != NULL; env = env->next_cpu) {
4592 for (i = 0; i < nb_numa_nodes; i++) {
4593 if (node_cpumask[i] & (1 << env->cpu_index)) {
4594 env->numa_node = i;
4595 }
4596 }
4597 }
4598
4599 current_machine = machine;
4600
4601 /* Set KVM's vcpu state to qemu's initial CPUState. */
4602 if (kvm_enabled()) {
4603 int ret;
4604
4605 ret = kvm_sync_vcpus();
4606 if (ret < 0) {
4607 fprintf(stderr, "failed to initialize vcpus\n");
4608 exit(1);
4609 }
4610 }
4611
4612 /* init USB devices */
4613 if (usb_enabled) {
4614 for(i = 0; i < usb_devices_index; i++) {
4615 if (usb_device_add(usb_devices[i], 0) < 0) {
4616 fprintf(stderr, "Warning: could not add USB device %s\n",
4617 usb_devices[i]);
4618 }
4619 }
4620 }
4621
4622 if (!display_state)
4623 dumb_display_init();
4624 /* just use the first displaystate for the moment */
4625 ds = display_state;
4626
4627 if (display_type == DT_DEFAULT) {
4628#if defined(CONFIG_SDL) || defined(CONFIG_COCOA)
4629 display_type = DT_SDL;
4630#else
4631 display_type = DT_VNC;
4632 vnc_display = "localhost:0,to=99";
4633 show_vnc_port = 1;
4634#endif
4635 }
David 'Digit' Turner707c8a82010-12-22 22:35:58 +01004636
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004637
4638 switch (display_type) {
4639 case DT_NOGRAPHIC:
4640 break;
4641#if defined(CONFIG_CURSES)
4642 case DT_CURSES:
4643 curses_display_init(ds, full_screen);
4644 break;
4645#endif
4646#if defined(CONFIG_SDL)
4647 case DT_SDL:
4648 sdl_display_init(ds, full_screen, no_frame);
4649 break;
4650#elif defined(CONFIG_COCOA)
4651 case DT_SDL:
4652 cocoa_display_init(ds, full_screen);
4653 break;
4654#endif
4655 case DT_VNC:
4656 vnc_display_init(ds);
4657 if (vnc_display_open(ds, vnc_display) < 0)
4658 exit(1);
4659
4660 if (show_vnc_port) {
4661 printf("VNC server running on `%s'\n", vnc_display_local_addr(ds));
4662 }
4663 break;
4664 default:
4665 break;
4666 }
4667 dpy_resize(ds);
4668
4669 dcl = ds->listeners;
4670 while (dcl != NULL) {
4671 if (dcl->dpy_refresh != NULL) {
4672 ds->gui_timer = qemu_new_timer(rt_clock, gui_update, ds);
4673 qemu_mod_timer(ds->gui_timer, qemu_get_clock(rt_clock));
4674 }
4675 dcl = dcl->next;
4676 }
4677
4678 if (display_type == DT_NOGRAPHIC || display_type == DT_VNC) {
4679 nographic_timer = qemu_new_timer(rt_clock, nographic_update, NULL);
4680 qemu_mod_timer(nographic_timer, qemu_get_clock(rt_clock));
4681 }
4682
4683 text_consoles_set_display(display_state);
4684 qemu_chr_initial_reset();
4685
4686 if (monitor_device && monitor_hd)
4687 monitor_init(monitor_hd, MONITOR_USE_READLINE | MONITOR_IS_DEFAULT);
4688
4689 for(i = 0; i < MAX_SERIAL_PORTS; i++) {
4690 const char *devname = serial_devices[i];
4691 if (devname && strcmp(devname, "none")) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004692 if (strstart(devname, "vc", 0))
4693 qemu_chr_printf(serial_hds[i], "serial%d console\r\n", i);
4694 }
4695 }
4696
4697 for(i = 0; i < MAX_PARALLEL_PORTS; i++) {
4698 const char *devname = parallel_devices[i];
4699 if (devname && strcmp(devname, "none")) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004700 if (strstart(devname, "vc", 0))
4701 qemu_chr_printf(parallel_hds[i], "parallel%d console\r\n", i);
4702 }
4703 }
4704
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004705 for(i = 0; i < MAX_VIRTIO_CONSOLES; i++) {
4706 const char *devname = virtio_consoles[i];
4707 if (virtcon_hds[i] && devname) {
4708 if (strstart(devname, "vc", 0))
4709 qemu_chr_printf(virtcon_hds[i], "virtio console%d\r\n", i);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004710 }
4711 }
4712
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004713 if (gdbstub_dev && gdbserver_start(gdbstub_dev) < 0) {
4714 fprintf(stderr, "qemu: could not open gdbserver on device '%s'\n",
4715 gdbstub_dev);
4716 exit(1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004717 }
4718
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004719 if (loadvm)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004720 do_loadvm(cur_mon, loadvm);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004721
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004722 if (incoming) {
4723 autostart = 0; /* fixme how to deal with -daemonize */
4724 qemu_start_incoming_migration(incoming);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004725 }
4726
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004727 if (autostart)
4728 vm_start();
4729
4730#ifndef _WIN32
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004731 if (daemonize) {
4732 uint8_t status = 0;
4733 ssize_t len;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004734
4735 again1:
4736 len = write(fds[1], &status, 1);
4737 if (len == -1 && (errno == EINTR))
4738 goto again1;
4739
4740 if (len != 1)
4741 exit(1);
4742
David 'Digit' Turnera7fb77d2010-05-10 23:50:54 -07004743 if (chdir("/")) {
4744 perror("not able to chdir to /");
4745 exit(1);
4746 }
4747 TFR(fd = qemu_open("/dev/null", O_RDWR));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004748 if (fd == -1)
4749 exit(1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004750 }
4751
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004752 if (run_as) {
4753 pwd = getpwnam(run_as);
4754 if (!pwd) {
4755 fprintf(stderr, "User \"%s\" doesn't exist\n", run_as);
4756 exit(1);
4757 }
4758 }
4759
4760 if (chroot_dir) {
4761 if (chroot(chroot_dir) < 0) {
4762 fprintf(stderr, "chroot failed\n");
4763 exit(1);
4764 }
David 'Digit' Turnera7fb77d2010-05-10 23:50:54 -07004765 if (chdir("/")) {
4766 perror("not able to chdir to /");
4767 exit(1);
4768 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004769 }
4770
4771 if (run_as) {
4772 if (setgid(pwd->pw_gid) < 0) {
4773 fprintf(stderr, "Failed to setgid(%d)\n", pwd->pw_gid);
4774 exit(1);
4775 }
4776 if (setuid(pwd->pw_uid) < 0) {
4777 fprintf(stderr, "Failed to setuid(%d)\n", pwd->pw_uid);
4778 exit(1);
4779 }
4780 if (setuid(0) != -1) {
4781 fprintf(stderr, "Dropping privileges failed\n");
4782 exit(1);
4783 }
4784 }
4785
4786 if (daemonize) {
4787 dup2(fd, 0);
4788 dup2(fd, 1);
4789 dup2(fd, 2);
4790
4791 close(fd);
4792 }
4793#endif
4794
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004795 main_loop();
4796 quit_timers();
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004797 net_cleanup();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004798
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004799 return 0;
4800}