blob: 428422221bf7b36432a8b2227693335443806475 [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>
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080037#include <sys/times.h>
38#include <sys/wait.h>
39#include <termios.h>
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080040#include <sys/mman.h>
41#include <sys/ioctl.h>
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070042#include <sys/resource.h>
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080043#include <sys/socket.h>
44#include <netinet/in.h>
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070045#include <net/if.h>
46#if defined(__NetBSD__)
47#include <net/if_tap.h>
48#endif
49#ifdef __linux__
50#include <linux/if_tun.h>
51#endif
52#include <arpa/inet.h>
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080053#include <dirent.h>
54#include <netdb.h>
55#include <sys/select.h>
David 'Digit' Turner2c538c82010-05-10 16:48:20 -070056#ifdef CONFIG_BSD
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080057#include <sys/stat.h>
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070058#if defined(__FreeBSD__) || defined(__DragonFly__)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080059#include <libutil.h>
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070060#else
61#include <util.h>
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080062#endif
63#elif defined (__GLIBC__) && defined (__FreeBSD_kernel__)
64#include <freebsd/stdlib.h>
65#else
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070066#ifdef __linux__
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080067#include <pty.h>
68#include <malloc.h>
69#include <linux/rtc.h>
70
71/* For the benefit of older linux systems which don't supply it,
72 we use a local copy of hpet.h. */
73/* #include <linux/hpet.h> */
David 'Digit' Turner2dbdad52013-12-17 09:24:18 +010074#include "hw/timer/hpet.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080075
76#include <linux/ppdev.h>
77#include <linux/parport.h>
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070078#endif
79#ifdef __sun__
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080080#include <sys/stat.h>
81#include <sys/ethernet.h>
82#include <sys/sockio.h>
83#include <netinet/arp.h>
84#include <netinet/in.h>
85#include <netinet/in_systm.h>
86#include <netinet/ip.h>
87#include <netinet/ip_icmp.h> // must come after ip.h
88#include <netinet/udp.h>
89#include <netinet/tcp.h>
90#include <net/if.h>
91#include <syslog.h>
92#include <stropts.h>
93#endif
94#endif
95#endif
96
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080097#if defined(__OpenBSD__)
98#include <util.h>
99#endif
100
101#if defined(CONFIG_VDE)
102#include <libvdeplug.h>
103#endif
104
105#ifdef _WIN32
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700106#include <windows.h>
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800107#include <malloc.h>
108#include <sys/timeb.h>
109#include <mmsystem.h>
110#define getopt_long_only getopt_long
111#define memalign(align, size) malloc(size)
112#endif
113
David 'Digit' Turner11822842013-12-17 09:16:47 +0100114#include "sysemu/cpus.h"
David 'Digit' Turner34c48ff2013-12-15 00:25:03 +0100115#include "sysemu/arch_init.h"
David 'Digit' Turnerae3098a2011-05-11 16:01:57 +0200116
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700117#ifdef CONFIG_SDL
118#ifdef __APPLE__
119#include <SDL.h>
120int qemu_main(int argc, char **argv, char **envp);
121int main(int argc, char **argv)
122{
123 qemu_main(argc, argv, NULL);
124}
125#undef main
126#define main qemu_main
127#endif
128#endif /* CONFIG_SDL */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800129
130#ifdef CONFIG_COCOA
David 'Digit' Turner8354d2d2011-05-11 00:19:06 +0200131int qemu_main(int argc, char **argv, char **envp);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800132#undef main
133#define main qemu_main
134#endif /* CONFIG_COCOA */
135
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700136#include "hw/hw.h"
137#include "hw/boards.h"
138#include "hw/usb.h"
139#include "hw/pcmcia.h"
David 'Digit' Turner2ec695a2013-12-17 10:03:39 +0100140#include "hw/i386/pc.h"
141#include "hw/isa/isa.h"
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700142#include "hw/baum.h"
143#include "hw/bt.h"
David 'Digit' Turner7821d632013-12-17 11:27:50 +0100144#include "sysemu/watchdog.h"
David 'Digit' Turner73a93a12013-12-17 11:26:01 +0100145#include "hw/i386/smbios.h"
David 'Digit' Turner50319182013-12-17 11:28:54 +0100146#include "hw/xen/xen.h"
David 'Digit' Turner6800f0a2013-12-17 09:12:54 +0100147#include "sysemu/bt.h"
David 'Digit' Turnercc330d42013-12-14 23:26:42 +0100148#include "net/net.h"
David 'Digit' Turner6af67652013-12-14 23:49:32 +0100149#include "monitor/monitor.h"
David 'Digit' Turner1c31e3e2013-12-14 20:07:17 +0100150#include "ui/console.h"
David 'Digit' Turner34c48ff2013-12-15 00:25:03 +0100151#include "sysemu/sysemu.h"
David 'Digit' Turner852088c2013-12-14 23:04:12 +0100152#include "exec/gdbstub.h"
David 'Digit' Turner7a78db72013-12-14 11:46:01 +0100153#include "qemu/timer.h"
David 'Digit' Turnere7216d82013-12-15 00:51:13 +0100154#include "sysemu/char.h"
David 'Digit' Turner37dc41a2013-12-14 14:45:51 +0100155#include "qemu/cache-utils.h"
David 'Digit' Turnere1e03df2013-12-15 00:42:21 +0100156#include "block/block.h"
David 'Digit' Turner34c48ff2013-12-15 00:25:03 +0100157#include "sysemu/dma.h"
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700158#include "audio/audio.h"
David 'Digit' Turner28a09b62013-12-15 00:16:00 +0100159#include "migration/migration.h"
David 'Digit' Turner34c48ff2013-12-15 00:25:03 +0100160#include "sysemu/kvm.h"
161#include "sysemu/balloon.h"
David 'Digit' Turner93e0d9c2013-12-15 01:00:34 +0100162#include "qemu/option.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800163
David 'Digit' Turnercc33b2d2013-12-15 00:09:42 +0100164#include "disas/disas.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800165
David 'Digit' Turner852088c2013-12-14 23:04:12 +0100166#include "exec/exec-all.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800167
David 'Digit' Turnerd0edecb2013-12-17 09:32:26 +0100168#include "qemu/sockets.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800169
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700170#if defined(CONFIG_SLIRP)
171#include "libslirp.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800172#endif
173
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800174
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700175
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700176#define DEFAULT_RAM_SIZE 128
177
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800178/* Max number of USB devices that can be specified on the commandline. */
179#define MAX_USB_CMDLINE 8
180
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700181/* Max number of bluetooth switches on the commandline. */
182#define MAX_BT_CMDLINE 10
183
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800184/* XXX: use a two level table to limit memory usage */
185#define MAX_IOPORTS 65536
186
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700187static const char *data_dir;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800188const char *bios_name = NULL;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700189static void *ioport_opaque[MAX_IOPORTS];
190static IOPortReadFunc *ioport_read_table[3][MAX_IOPORTS];
191static IOPortWriteFunc *ioport_write_table[3][MAX_IOPORTS];
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800192/* Note: drives_table[MAX_DRIVES] is a dummy block driver if none available
193 to store the VM snapshots */
194DriveInfo drives_table[MAX_DRIVES+1];
195int nb_drives;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700196enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700197DisplayType display_type = DT_DEFAULT;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800198const char* keyboard_layout = NULL;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800199ram_addr_t ram_size;
David 'Digit' Turner280afa02011-05-11 17:37:44 +0200200const char *mem_path = NULL;
201#ifdef MAP_POPULATE
202int mem_prealloc = 0; /* force preallocation of physical target memory */
203#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800204int nb_nics;
205NICInfo nd_table[MAX_NICS];
206int vm_running;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700207static int autostart;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800208static int rtc_utc = 1;
209static int rtc_date_offset = -1; /* -1 means no change */
210int cirrus_vga_enabled = 1;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700211int std_vga_enabled = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800212int vmsvga_enabled = 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700213int xenfb_enabled = 0;
David 'Digit' Turnera7fb77d2010-05-10 23:50:54 -0700214QEMUClock *rtc_clock;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700215static int full_screen = 0;
216#ifdef CONFIG_SDL
217static int no_frame = 0;
218#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800219int no_quit = 0;
220CharDriverState *serial_hds[MAX_SERIAL_PORTS];
221CharDriverState *parallel_hds[MAX_PARALLEL_PORTS];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700222CharDriverState *virtcon_hds[MAX_VIRTIO_CONSOLES];
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800223#ifdef TARGET_I386
224int win2k_install_hack = 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700225int rtc_td_hack = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800226#endif
227int usb_enabled = 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700228int singlestep = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800229int smp_cpus = 1;
230const char *vnc_display;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800231int acpi_enabled = 1;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700232int no_hpet = 0;
233int no_virtio_balloon = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800234int fd_bootchk = 1;
235int no_reboot = 0;
236int no_shutdown = 0;
237int cursor_hide = 1;
238int graphic_rotate = 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700239WatchdogTimerModel *watchdog = NULL;
240int watchdog_action = WDT_RESET;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800241const char *option_rom[MAX_OPTION_ROMS];
242int nb_option_roms;
243int semihosting_enabled = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800244#ifdef TARGET_ARM
245int old_param = 0;
246#endif
247const char *qemu_name;
248int alt_grab = 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700249#if defined(TARGET_SPARC) || defined(TARGET_PPC)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800250unsigned int nb_prom_envs = 0;
251const char *prom_envs[MAX_PROM_ENVS];
252#endif
253int nb_drives_opt;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700254struct drive_opt drives_opt[MAX_DRIVES];
255
256int nb_numa_nodes;
257uint64_t node_mem[MAX_NODES];
258uint64_t node_cpumask[MAX_NODES];
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800259
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700260static QEMUTimer *nographic_timer;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800261
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700262uint8_t qemu_uuid[16];
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800263
264/***********************************************************/
265/* x86 ISA bus support */
266
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +0100267hwaddr isa_mem_base = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800268PicState2 *isa_pic;
269
270static IOPortReadFunc default_ioport_readb, default_ioport_readw, default_ioport_readl;
271static IOPortWriteFunc default_ioport_writeb, default_ioport_writew, default_ioport_writel;
272
273static uint32_t ioport_read(int index, uint32_t address)
274{
275 static IOPortReadFunc *default_func[3] = {
276 default_ioport_readb,
277 default_ioport_readw,
278 default_ioport_readl
279 };
280 IOPortReadFunc *func = ioport_read_table[index][address];
281 if (!func)
282 func = default_func[index];
283 return func(ioport_opaque[address], address);
284}
285
286static void ioport_write(int index, uint32_t address, uint32_t data)
287{
288 static IOPortWriteFunc *default_func[3] = {
289 default_ioport_writeb,
290 default_ioport_writew,
291 default_ioport_writel
292 };
293 IOPortWriteFunc *func = ioport_write_table[index][address];
294 if (!func)
295 func = default_func[index];
296 func(ioport_opaque[address], address, data);
297}
298
299static uint32_t default_ioport_readb(void *opaque, uint32_t address)
300{
301#ifdef DEBUG_UNUSED_IOPORT
302 fprintf(stderr, "unused inb: port=0x%04x\n", address);
303#endif
304 return 0xff;
305}
306
307static void default_ioport_writeb(void *opaque, uint32_t address, uint32_t data)
308{
309#ifdef DEBUG_UNUSED_IOPORT
310 fprintf(stderr, "unused outb: port=0x%04x data=0x%02x\n", address, data);
311#endif
312}
313
314/* default is to make two byte accesses */
315static uint32_t default_ioport_readw(void *opaque, uint32_t address)
316{
317 uint32_t data;
318 data = ioport_read(0, address);
319 address = (address + 1) & (MAX_IOPORTS - 1);
320 data |= ioport_read(0, address) << 8;
321 return data;
322}
323
324static void default_ioport_writew(void *opaque, uint32_t address, uint32_t data)
325{
326 ioport_write(0, address, data & 0xff);
327 address = (address + 1) & (MAX_IOPORTS - 1);
328 ioport_write(0, address, (data >> 8) & 0xff);
329}
330
331static uint32_t default_ioport_readl(void *opaque, uint32_t address)
332{
333#ifdef DEBUG_UNUSED_IOPORT
334 fprintf(stderr, "unused inl: port=0x%04x\n", address);
335#endif
336 return 0xffffffff;
337}
338
339static void default_ioport_writel(void *opaque, uint32_t address, uint32_t data)
340{
341#ifdef DEBUG_UNUSED_IOPORT
342 fprintf(stderr, "unused outl: port=0x%04x data=0x%02x\n", address, data);
343#endif
344}
345
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800346
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700347/***************/
348/* ballooning */
349
350static QEMUBalloonEvent *qemu_balloon_event;
351void *qemu_balloon_event_opaque;
352
353void qemu_add_balloon_handler(QEMUBalloonEvent *func, void *opaque)
354{
355 qemu_balloon_event = func;
356 qemu_balloon_event_opaque = opaque;
357}
358
359void qemu_balloon(ram_addr_t target)
360{
361 if (qemu_balloon_event)
362 qemu_balloon_event(qemu_balloon_event_opaque, target);
363}
364
365ram_addr_t qemu_balloon_status(void)
366{
367 if (qemu_balloon_event)
368 return qemu_balloon_event(qemu_balloon_event_opaque, 0);
369 return 0;
370}
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800371
372/***********************************************************/
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800373/* host time/date access */
374void qemu_get_timedate(struct tm *tm, int offset)
375{
376 time_t ti;
377 struct tm *ret;
378
379 time(&ti);
380 ti += offset;
381 if (rtc_date_offset == -1) {
382 if (rtc_utc)
383 ret = gmtime(&ti);
384 else
385 ret = localtime(&ti);
386 } else {
387 ti -= rtc_date_offset;
388 ret = gmtime(&ti);
389 }
390
391 memcpy(tm, ret, sizeof(struct tm));
392}
393
394int qemu_timedate_diff(struct tm *tm)
395{
396 time_t seconds;
397
398 if (rtc_date_offset == -1)
399 if (rtc_utc)
400 seconds = mktimegm(tm);
401 else
402 seconds = mktime(tm);
403 else
404 seconds = mktimegm(tm) + rtc_date_offset;
405
406 return seconds - time(NULL);
407}
408
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800409#ifdef _WIN32
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700410static void socket_cleanup(void)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800411{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700412 WSACleanup();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800413}
414
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700415static int socket_init(void)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800416{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700417 WSADATA Data;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800418 int ret, err;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800419
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700420 ret = WSAStartup(MAKEWORD(2,2), &Data);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800421 if (ret != 0) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700422 err = WSAGetLastError();
423 fprintf(stderr, "WSAStartup: %d\n", err);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800424 return -1;
425 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700426 atexit(socket_cleanup);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800427 return 0;
428}
429#endif
430
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700431int get_param_value(char *buf, int buf_size,
432 const char *tag, const char *str)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800433{
434 const char *p;
435 char option[128];
436
437 p = str;
438 for(;;) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700439 p = get_opt_name(option, sizeof(option), p, '=');
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800440 if (*p != '=')
441 break;
442 p++;
443 if (!strcmp(tag, option)) {
444 (void)get_opt_value(buf, buf_size, p);
445 return strlen(buf);
446 } else {
447 p = get_opt_value(NULL, 0, p);
448 }
449 if (*p != ',')
450 break;
451 p++;
452 }
453 return 0;
454}
455
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700456int check_params(char *buf, int buf_size,
457 const char * const *params, const char *str)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800458{
459 const char *p;
460 int i;
461
462 p = str;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700463 while (*p != '\0') {
464 p = get_opt_name(buf, buf_size, p, '=');
465 if (*p != '=') {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800466 return -1;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700467 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800468 p++;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700469 for (i = 0; params[i] != NULL; i++) {
470 if (!strcmp(params[i], buf)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800471 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700472 }
473 }
474 if (params[i] == NULL) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800475 return -1;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700476 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800477 p = get_opt_value(NULL, 0, p);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700478 if (*p != ',') {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800479 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700480 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800481 p++;
482 }
483 return 0;
484}
485
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700486/***********************************************************/
487/* Bluetooth support */
488static int nb_hcis;
489static int cur_hci;
490static struct HCIInfo *hci_table[MAX_NICS];
491
492static struct bt_vlan_s {
493 struct bt_scatternet_s net;
494 int id;
495 struct bt_vlan_s *next;
496} *first_bt_vlan;
497
498/* find or alloc a new bluetooth "VLAN" */
499static struct bt_scatternet_s *qemu_find_bt_vlan(int id)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800500{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700501 struct bt_vlan_s **pvlan, *vlan;
502 for (vlan = first_bt_vlan; vlan != NULL; vlan = vlan->next) {
503 if (vlan->id == id)
504 return &vlan->net;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800505 }
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100506 vlan = g_malloc0(sizeof(struct bt_vlan_s));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700507 vlan->id = id;
508 pvlan = &first_bt_vlan;
509 while (*pvlan != NULL)
510 pvlan = &(*pvlan)->next;
511 *pvlan = vlan;
512 return &vlan->net;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800513}
514
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700515static void null_hci_send(struct HCIInfo *hci, const uint8_t *data, int len)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800516{
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800517}
518
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700519static int null_hci_addr_set(struct HCIInfo *hci, const uint8_t *bd_addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800520{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700521 return -ENOTSUP;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800522}
523
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700524static struct HCIInfo null_hci = {
525 .cmd_send = null_hci_send,
526 .sco_send = null_hci_send,
527 .acl_send = null_hci_send,
528 .bdaddr_set = null_hci_addr_set,
529};
530
531struct HCIInfo *qemu_next_hci(void)
532{
533 if (cur_hci == nb_hcis)
534 return &null_hci;
535
536 return hci_table[cur_hci++];
537}
538
539static struct HCIInfo *hci_init(const char *str)
540{
541 char *endp;
542 struct bt_scatternet_s *vlan = 0;
543
544 if (!strcmp(str, "null"))
545 /* null */
546 return &null_hci;
547 else if (!strncmp(str, "host", 4) && (str[4] == '\0' || str[4] == ':'))
548 /* host[:hciN] */
549 return bt_host_hci(str[4] ? str + 5 : "hci0");
550 else if (!strncmp(str, "hci", 3)) {
551 /* hci[,vlan=n] */
552 if (str[3]) {
553 if (!strncmp(str + 3, ",vlan=", 6)) {
554 vlan = qemu_find_bt_vlan(strtol(str + 9, &endp, 0));
555 if (*endp)
556 vlan = 0;
557 }
558 } else
559 vlan = qemu_find_bt_vlan(0);
560 if (vlan)
561 return bt_new_hci(vlan);
562 }
563
564 fprintf(stderr, "qemu: Unknown bluetooth HCI `%s'.\n", str);
565
566 return 0;
567}
568
569static int bt_hci_parse(const char *str)
570{
571 struct HCIInfo *hci;
572 bdaddr_t bdaddr;
573
574 if (nb_hcis >= MAX_NICS) {
575 fprintf(stderr, "qemu: Too many bluetooth HCIs (max %i).\n", MAX_NICS);
576 return -1;
577 }
578
579 hci = hci_init(str);
580 if (!hci)
581 return -1;
582
583 bdaddr.b[0] = 0x52;
584 bdaddr.b[1] = 0x54;
585 bdaddr.b[2] = 0x00;
586 bdaddr.b[3] = 0x12;
587 bdaddr.b[4] = 0x34;
588 bdaddr.b[5] = 0x56 + nb_hcis;
589 hci->bdaddr_set(hci, bdaddr.b);
590
591 hci_table[nb_hcis++] = hci;
592
593 return 0;
594}
595
596static void bt_vhci_add(int vlan_id)
597{
598 struct bt_scatternet_s *vlan = qemu_find_bt_vlan(vlan_id);
599
600 if (!vlan->slave)
601 fprintf(stderr, "qemu: warning: adding a VHCI to "
602 "an empty scatternet %i\n", vlan_id);
603
604 bt_vhci_init(bt_new_hci(vlan));
605}
606
607static struct bt_device_s *bt_device_add(const char *opt)
608{
609 struct bt_scatternet_s *vlan;
610 int vlan_id = 0;
611 char *endp = strstr(opt, ",vlan=");
612 int len = (endp ? endp - opt : strlen(opt)) + 1;
613 char devname[10];
614
615 pstrcpy(devname, MIN(sizeof(devname), len), opt);
616
617 if (endp) {
618 vlan_id = strtol(endp + 6, &endp, 0);
619 if (*endp) {
620 fprintf(stderr, "qemu: unrecognised bluetooth vlan Id\n");
621 return 0;
622 }
623 }
624
625 vlan = qemu_find_bt_vlan(vlan_id);
626
627 if (!vlan->slave)
628 fprintf(stderr, "qemu: warning: adding a slave device to "
629 "an empty scatternet %i\n", vlan_id);
630
631 if (!strcmp(devname, "keyboard"))
632 return bt_keyboard_init(vlan);
633
634 fprintf(stderr, "qemu: unsupported bluetooth device `%s'\n", devname);
635 return 0;
636}
637
638static int bt_parse(const char *opt)
639{
640 const char *endp, *p;
641 int vlan;
642
643 if (strstart(opt, "hci", &endp)) {
644 if (!*endp || *endp == ',') {
645 if (*endp)
646 if (!strstart(endp, ",vlan=", 0))
647 opt = endp + 1;
648
649 return bt_hci_parse(opt);
650 }
651 } else if (strstart(opt, "vhci", &endp)) {
652 if (!*endp || *endp == ',') {
653 if (*endp) {
654 if (strstart(endp, ",vlan=", &p)) {
655 vlan = strtol(p, (char **) &endp, 0);
656 if (*endp) {
657 fprintf(stderr, "qemu: bad scatternet '%s'\n", p);
658 return 1;
659 }
660 } else {
661 fprintf(stderr, "qemu: bad parameter '%s'\n", endp + 1);
662 return 1;
663 }
664 } else
665 vlan = 0;
666
667 bt_vhci_add(vlan);
668 return 0;
669 }
670 } else if (strstart(opt, "device:", &endp))
671 return !bt_device_add(endp);
672
673 fprintf(stderr, "qemu: bad bluetooth parameter '%s'\n", opt);
674 return 1;
675}
676
677/***********************************************************/
678/* QEMU Block devices */
679
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800680#define HD_ALIAS "index=%d,media=disk"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800681#define CDROM_ALIAS "index=2,media=cdrom"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800682#define FD_ALIAS "index=%d,if=floppy"
683#define PFLASH_ALIAS "if=pflash"
684#define MTD_ALIAS "if=mtd"
685#define SD_ALIAS "index=0,if=sd"
686
David 'Digit' Turnercb42a1b2010-12-23 02:54:08 +0100687static int drive_init_func(QemuOpts *opts, void *opaque)
688{
689 int *use_scsi = opaque;
690 int fatal_error = 0;
691
692 if (drive_init(opts, *use_scsi, &fatal_error) == NULL) {
693 if (fatal_error)
694 return 1;
695 }
696 return 0;
697}
698
699static int drive_enable_snapshot(QemuOpts *opts, void *opaque)
700{
701 if (NULL == qemu_opt_get(opts, "snapshot")) {
702 qemu_opt_set(opts, "snapshot", "on");
703 }
704 return 0;
705}
706
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700707static int drive_opt_get_free_idx(void)
708{
709 int index;
710
711 for (index = 0; index < MAX_DRIVES; index++)
712 if (!drives_opt[index].used) {
713 drives_opt[index].used = 1;
714 return index;
715 }
716
717 return -1;
718}
719
720static int drive_get_free_idx(void)
721{
722 int index;
723
724 for (index = 0; index < MAX_DRIVES; index++)
725 if (!drives_table[index].used) {
726 drives_table[index].used = 1;
727 return index;
728 }
729
730 return -1;
731}
732
733int drive_add(const char *file, const char *fmt, ...)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800734{
735 va_list ap;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700736 int index = drive_opt_get_free_idx();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800737
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700738 if (nb_drives_opt >= MAX_DRIVES || index == -1) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800739 fprintf(stderr, "qemu: too many drives\n");
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700740 return -1;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800741 }
742
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700743 drives_opt[index].file = file;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800744 va_start(ap, fmt);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700745 vsnprintf(drives_opt[index].opt,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800746 sizeof(drives_opt[0].opt), fmt, ap);
747 va_end(ap);
748
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700749 nb_drives_opt++;
750 return index;
751}
752
753void drive_remove(int index)
754{
755 drives_opt[index].used = 0;
756 nb_drives_opt--;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800757}
758
759int drive_get_index(BlockInterfaceType type, int bus, int unit)
760{
761 int index;
762
763 /* seek interface, bus and unit */
764
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700765 for (index = 0; index < MAX_DRIVES; index++)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800766 if (drives_table[index].type == type &&
767 drives_table[index].bus == bus &&
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700768 drives_table[index].unit == unit &&
769 drives_table[index].used)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800770 return index;
771
772 return -1;
773}
774
775int drive_get_max_bus(BlockInterfaceType type)
776{
777 int max_bus;
778 int index;
779
780 max_bus = -1;
781 for (index = 0; index < nb_drives; index++) {
782 if(drives_table[index].type == type &&
783 drives_table[index].bus > max_bus)
784 max_bus = drives_table[index].bus;
785 }
786 return max_bus;
787}
788
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700789const char *drive_get_serial(BlockDriverState *bdrv)
790{
791 int index;
792
793 for (index = 0; index < nb_drives; index++)
794 if (drives_table[index].bdrv == bdrv)
795 return drives_table[index].serial;
796
797 return "\0";
798}
799
800BlockInterfaceErrorAction drive_get_onerror(BlockDriverState *bdrv)
801{
802 int index;
803
804 for (index = 0; index < nb_drives; index++)
805 if (drives_table[index].bdrv == bdrv)
806 return drives_table[index].onerror;
807
808 return BLOCK_ERR_STOP_ENOSPC;
809}
810
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800811static void bdrv_format_print(void *opaque, const char *name)
812{
813 fprintf(stderr, " %s", name);
814}
815
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700816void drive_uninit(BlockDriverState *bdrv)
817{
818 int i;
819
820 for (i = 0; i < MAX_DRIVES; i++)
821 if (drives_table[i].bdrv == bdrv) {
822 drives_table[i].bdrv = NULL;
823 drives_table[i].used = 0;
824 drive_remove(drives_table[i].drive_opt_idx);
825 nb_drives--;
826 break;
827 }
828}
829
830int drive_init(struct drive_opt *arg, int snapshot, void *opaque)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800831{
832 char buf[128];
833 char file[1024];
834 char devname[128];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700835 char serial[21];
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800836 const char *mediastr = "";
837 BlockInterfaceType type;
838 enum { MEDIA_DISK, MEDIA_CDROM } media;
839 int bus_id, unit_id;
840 int cyls, heads, secs, translation;
841 BlockDriverState *bdrv;
842 BlockDriver *drv = NULL;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700843 QEMUMachine *machine = opaque;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800844 int max_devs;
845 int index;
846 int cache;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700847 int bdrv_flags, onerror;
848 int drives_table_idx;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800849 char *str = arg->opt;
850 static const char * const params[] = { "bus", "unit", "if", "index",
851 "cyls", "heads", "secs", "trans",
852 "media", "snapshot", "file",
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700853 "cache", "format", "serial", "werror",
854 NULL };
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800855
856 if (check_params(buf, sizeof(buf), params, str) < 0) {
857 fprintf(stderr, "qemu: unknown parameter '%s' in '%s'\n",
858 buf, str);
859 return -1;
860 }
861
862 file[0] = 0;
863 cyls = heads = secs = 0;
864 bus_id = 0;
865 unit_id = -1;
866 translation = BIOS_ATA_TRANSLATION_AUTO;
867 index = -1;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700868 cache = 3;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800869
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700870 if (machine->use_scsi) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800871 type = IF_SCSI;
872 max_devs = MAX_SCSI_DEVS;
873 pstrcpy(devname, sizeof(devname), "scsi");
874 } else {
875 type = IF_IDE;
876 max_devs = MAX_IDE_DEVS;
877 pstrcpy(devname, sizeof(devname), "ide");
878 }
879 media = MEDIA_DISK;
880
881 /* extract parameters */
882
883 if (get_param_value(buf, sizeof(buf), "bus", str)) {
884 bus_id = strtol(buf, NULL, 0);
885 if (bus_id < 0) {
886 fprintf(stderr, "qemu: '%s' invalid bus id\n", str);
887 return -1;
888 }
889 }
890
891 if (get_param_value(buf, sizeof(buf), "unit", str)) {
892 unit_id = strtol(buf, NULL, 0);
893 if (unit_id < 0) {
894 fprintf(stderr, "qemu: '%s' invalid unit id\n", str);
895 return -1;
896 }
897 }
898
899 if (get_param_value(buf, sizeof(buf), "if", str)) {
900 pstrcpy(devname, sizeof(devname), buf);
901 if (!strcmp(buf, "ide")) {
902 type = IF_IDE;
903 max_devs = MAX_IDE_DEVS;
904 } else if (!strcmp(buf, "scsi")) {
905 type = IF_SCSI;
906 max_devs = MAX_SCSI_DEVS;
907 } else if (!strcmp(buf, "floppy")) {
908 type = IF_FLOPPY;
909 max_devs = 0;
910 } else if (!strcmp(buf, "pflash")) {
911 type = IF_PFLASH;
912 max_devs = 0;
913 } else if (!strcmp(buf, "mtd")) {
914 type = IF_MTD;
915 max_devs = 0;
916 } else if (!strcmp(buf, "sd")) {
917 type = IF_SD;
918 max_devs = 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700919 } else if (!strcmp(buf, "virtio")) {
920 type = IF_VIRTIO;
921 max_devs = 0;
922 } else if (!strcmp(buf, "xen")) {
923 type = IF_XEN;
924 max_devs = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800925 } else {
926 fprintf(stderr, "qemu: '%s' unsupported bus type '%s'\n", str, buf);
927 return -1;
928 }
929 }
930
931 if (get_param_value(buf, sizeof(buf), "index", str)) {
932 index = strtol(buf, NULL, 0);
933 if (index < 0) {
934 fprintf(stderr, "qemu: '%s' invalid index\n", str);
935 return -1;
936 }
937 }
938
939 if (get_param_value(buf, sizeof(buf), "cyls", str)) {
940 cyls = strtol(buf, NULL, 0);
941 }
942
943 if (get_param_value(buf, sizeof(buf), "heads", str)) {
944 heads = strtol(buf, NULL, 0);
945 }
946
947 if (get_param_value(buf, sizeof(buf), "secs", str)) {
948 secs = strtol(buf, NULL, 0);
949 }
950
951 if (cyls || heads || secs) {
952 if (cyls < 1 || cyls > 16383) {
953 fprintf(stderr, "qemu: '%s' invalid physical cyls number\n", str);
954 return -1;
955 }
956 if (heads < 1 || heads > 16) {
957 fprintf(stderr, "qemu: '%s' invalid physical heads number\n", str);
958 return -1;
959 }
960 if (secs < 1 || secs > 63) {
961 fprintf(stderr, "qemu: '%s' invalid physical secs number\n", str);
962 return -1;
963 }
964 }
965
966 if (get_param_value(buf, sizeof(buf), "trans", str)) {
967 if (!cyls) {
968 fprintf(stderr,
969 "qemu: '%s' trans must be used with cyls,heads and secs\n",
970 str);
971 return -1;
972 }
973 if (!strcmp(buf, "none"))
974 translation = BIOS_ATA_TRANSLATION_NONE;
975 else if (!strcmp(buf, "lba"))
976 translation = BIOS_ATA_TRANSLATION_LBA;
977 else if (!strcmp(buf, "auto"))
978 translation = BIOS_ATA_TRANSLATION_AUTO;
979 else {
980 fprintf(stderr, "qemu: '%s' invalid translation type\n", str);
981 return -1;
982 }
983 }
984
985 if (get_param_value(buf, sizeof(buf), "media", str)) {
986 if (!strcmp(buf, "disk")) {
987 media = MEDIA_DISK;
988 } else if (!strcmp(buf, "cdrom")) {
989 if (cyls || secs || heads) {
990 fprintf(stderr,
991 "qemu: '%s' invalid physical CHS format\n", str);
992 return -1;
993 }
994 media = MEDIA_CDROM;
995 } else {
996 fprintf(stderr, "qemu: '%s' invalid media\n", str);
997 return -1;
998 }
999 }
1000
1001 if (get_param_value(buf, sizeof(buf), "snapshot", str)) {
1002 if (!strcmp(buf, "on"))
1003 snapshot = 1;
1004 else if (!strcmp(buf, "off"))
1005 snapshot = 0;
1006 else {
1007 fprintf(stderr, "qemu: '%s' invalid snapshot option\n", str);
1008 return -1;
1009 }
1010 }
1011
1012 if (get_param_value(buf, sizeof(buf), "cache", str)) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001013 if (!strcmp(buf, "off") || !strcmp(buf, "none"))
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001014 cache = 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001015 else if (!strcmp(buf, "writethrough"))
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001016 cache = 1;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001017 else if (!strcmp(buf, "writeback"))
1018 cache = 2;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001019 else {
1020 fprintf(stderr, "qemu: invalid cache option\n");
1021 return -1;
1022 }
1023 }
1024
1025 if (get_param_value(buf, sizeof(buf), "format", str)) {
1026 if (strcmp(buf, "?") == 0) {
1027 fprintf(stderr, "qemu: Supported formats:");
1028 bdrv_iterate_format(bdrv_format_print, NULL);
1029 fprintf(stderr, "\n");
1030 return -1;
1031 }
1032 drv = bdrv_find_format(buf);
1033 if (!drv) {
1034 fprintf(stderr, "qemu: '%s' invalid format\n", buf);
1035 return -1;
1036 }
1037 }
1038
1039 if (arg->file == NULL)
1040 get_param_value(file, sizeof(file), "file", str);
1041 else
1042 pstrcpy(file, sizeof(file), arg->file);
1043
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001044 if (!get_param_value(serial, sizeof(serial), "serial", str))
1045 memset(serial, 0, sizeof(serial));
1046
1047 onerror = BLOCK_ERR_STOP_ENOSPC;
1048 if (get_param_value(buf, sizeof(serial), "werror", str)) {
1049 if (type != IF_IDE && type != IF_SCSI && type != IF_VIRTIO) {
1050 fprintf(stderr, "werror is no supported by this format\n");
1051 return -1;
1052 }
1053 if (!strcmp(buf, "ignore"))
1054 onerror = BLOCK_ERR_IGNORE;
1055 else if (!strcmp(buf, "enospc"))
1056 onerror = BLOCK_ERR_STOP_ENOSPC;
1057 else if (!strcmp(buf, "stop"))
1058 onerror = BLOCK_ERR_STOP_ANY;
1059 else if (!strcmp(buf, "report"))
1060 onerror = BLOCK_ERR_REPORT;
1061 else {
1062 fprintf(stderr, "qemu: '%s' invalid write error action\n", buf);
1063 return -1;
1064 }
1065 }
1066
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001067 /* compute bus and unit according index */
1068
1069 if (index != -1) {
1070 if (bus_id != 0 || unit_id != -1) {
1071 fprintf(stderr,
1072 "qemu: '%s' index cannot be used with bus and unit\n", str);
1073 return -1;
1074 }
1075 if (max_devs == 0)
1076 {
1077 unit_id = index;
1078 bus_id = 0;
1079 } else {
1080 unit_id = index % max_devs;
1081 bus_id = index / max_devs;
1082 }
1083 }
1084
1085 /* if user doesn't specify a unit_id,
1086 * try to find the first free
1087 */
1088
1089 if (unit_id == -1) {
1090 unit_id = 0;
1091 while (drive_get_index(type, bus_id, unit_id) != -1) {
1092 unit_id++;
1093 if (max_devs && unit_id >= max_devs) {
1094 unit_id -= max_devs;
1095 bus_id++;
1096 }
1097 }
1098 }
1099
1100 /* check unit id */
1101
1102 if (max_devs && unit_id >= max_devs) {
1103 fprintf(stderr, "qemu: '%s' unit %d too big (max is %d)\n",
1104 str, unit_id, max_devs - 1);
1105 return -1;
1106 }
1107
1108 /*
1109 * ignore multiple definitions
1110 */
1111
1112 if (drive_get_index(type, bus_id, unit_id) != -1)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001113 return -2;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001114
1115 /* init */
1116
1117 if (type == IF_IDE || type == IF_SCSI)
1118 mediastr = (media == MEDIA_CDROM) ? "-cd" : "-hd";
1119 if (max_devs)
1120 snprintf(buf, sizeof(buf), "%s%i%s%i",
1121 devname, bus_id, mediastr, unit_id);
1122 else
1123 snprintf(buf, sizeof(buf), "%s%s%i",
1124 devname, mediastr, unit_id);
1125 bdrv = bdrv_new(buf);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001126 drives_table_idx = drive_get_free_idx();
1127 drives_table[drives_table_idx].bdrv = bdrv;
1128 drives_table[drives_table_idx].type = type;
1129 drives_table[drives_table_idx].bus = bus_id;
1130 drives_table[drives_table_idx].unit = unit_id;
1131 drives_table[drives_table_idx].onerror = onerror;
1132 drives_table[drives_table_idx].drive_opt_idx = arg - drives_opt;
1133 strncpy(drives_table[drives_table_idx].serial, serial, sizeof(serial));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001134 nb_drives++;
1135
1136 switch(type) {
1137 case IF_IDE:
1138 case IF_SCSI:
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001139 case IF_XEN:
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001140 switch(media) {
1141 case MEDIA_DISK:
1142 if (cyls != 0) {
1143 bdrv_set_geometry_hint(bdrv, cyls, heads, secs);
1144 bdrv_set_translation_hint(bdrv, translation);
1145 }
1146 break;
1147 case MEDIA_CDROM:
1148 bdrv_set_type_hint(bdrv, BDRV_TYPE_CDROM);
1149 break;
1150 }
1151 break;
1152 case IF_SD:
1153 /* FIXME: This isn't really a floppy, but it's a reasonable
1154 approximation. */
1155 case IF_FLOPPY:
1156 bdrv_set_type_hint(bdrv, BDRV_TYPE_FLOPPY);
1157 break;
1158 case IF_PFLASH:
1159 case IF_MTD:
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001160 case IF_VIRTIO:
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001161 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001162 case IF_COUNT:
1163 abort();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001164 }
1165 if (!file[0])
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001166 return -2;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001167 bdrv_flags = 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001168 if (snapshot) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001169 bdrv_flags |= BDRV_O_SNAPSHOT;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001170 cache = 2; /* always use write-back with snapshot */
1171 }
1172 if (cache == 0) /* no caching */
1173 bdrv_flags |= BDRV_O_NOCACHE;
1174 else if (cache == 2) /* write-back */
1175 bdrv_flags |= BDRV_O_CACHE_WB;
1176 else if (cache == 3) /* not specified */
1177 bdrv_flags |= BDRV_O_CACHE_DEF;
1178 if (bdrv_open2(bdrv, file, bdrv_flags, drv) < 0) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001179 fprintf(stderr, "qemu: could not open disk image %s\n",
1180 file);
1181 return -1;
1182 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001183 if (bdrv_key_required(bdrv))
1184 autostart = 0;
1185 return drives_table_idx;
1186}
1187
1188static void numa_add(const char *optarg)
1189{
1190 char option[128];
1191 char *endptr;
1192 unsigned long long value, endvalue;
1193 int nodenr;
1194
1195 optarg = get_opt_name(option, 128, optarg, ',') + 1;
1196 if (!strcmp(option, "node")) {
1197 if (get_param_value(option, 128, "nodeid", optarg) == 0) {
1198 nodenr = nb_numa_nodes;
1199 } else {
1200 nodenr = strtoull(option, NULL, 10);
1201 }
1202
1203 if (get_param_value(option, 128, "mem", optarg) == 0) {
1204 node_mem[nodenr] = 0;
1205 } else {
1206 value = strtoull(option, &endptr, 0);
1207 switch (*endptr) {
1208 case 0: case 'M': case 'm':
1209 value <<= 20;
1210 break;
1211 case 'G': case 'g':
1212 value <<= 30;
1213 break;
1214 }
1215 node_mem[nodenr] = value;
1216 }
1217 if (get_param_value(option, 128, "cpus", optarg) == 0) {
1218 node_cpumask[nodenr] = 0;
1219 } else {
1220 value = strtoull(option, &endptr, 10);
1221 if (value >= 64) {
1222 value = 63;
1223 fprintf(stderr, "only 64 CPUs in NUMA mode supported.\n");
1224 } else {
1225 if (*endptr == '-') {
1226 endvalue = strtoull(endptr+1, &endptr, 10);
1227 if (endvalue >= 63) {
1228 endvalue = 62;
1229 fprintf(stderr,
1230 "only 63 CPUs in NUMA mode supported.\n");
1231 }
1232 value = (1 << (endvalue + 1)) - (1 << value);
1233 } else {
1234 value = 1 << value;
1235 }
1236 }
1237 node_cpumask[nodenr] = value;
1238 }
1239 nb_numa_nodes++;
1240 }
1241 return;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001242}
1243
1244/***********************************************************/
1245/* USB devices */
1246
1247static USBPort *used_usb_ports;
1248static USBPort *free_usb_ports;
1249
1250/* ??? Maybe change this to register a hub to keep track of the topology. */
1251void qemu_register_usb_port(USBPort *port, void *opaque, int index,
1252 usb_attachfn attach)
1253{
1254 port->opaque = opaque;
1255 port->index = index;
1256 port->attach = attach;
1257 port->next = free_usb_ports;
1258 free_usb_ports = port;
1259}
1260
1261int usb_device_add_dev(USBDevice *dev)
1262{
1263 USBPort *port;
1264
1265 /* Find a USB port to add the device to. */
1266 port = free_usb_ports;
1267 if (!port->next) {
1268 USBDevice *hub;
1269
1270 /* Create a new hub and chain it on. */
1271 free_usb_ports = NULL;
1272 port->next = used_usb_ports;
1273 used_usb_ports = port;
1274
1275 hub = usb_hub_init(VM_USB_HUB_SIZE);
1276 usb_attach(port, hub);
1277 port = free_usb_ports;
1278 }
1279
1280 free_usb_ports = port->next;
1281 port->next = used_usb_ports;
1282 used_usb_ports = port;
1283 usb_attach(port, dev);
1284 return 0;
1285}
1286
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001287static void usb_msd_password_cb(void *opaque, int err)
1288{
1289 USBDevice *dev = opaque;
1290
1291 if (!err)
1292 usb_device_add_dev(dev);
1293 else
1294 dev->handle_destroy(dev);
1295}
1296
1297static int usb_device_add(const char *devname, int is_hotplug)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001298{
1299 const char *p;
1300 USBDevice *dev;
1301
1302 if (!free_usb_ports)
1303 return -1;
1304
1305 if (strstart(devname, "host:", &p)) {
1306 dev = usb_host_device_open(p);
1307 } else if (!strcmp(devname, "mouse")) {
1308 dev = usb_mouse_init();
1309 } else if (!strcmp(devname, "tablet")) {
1310 dev = usb_tablet_init();
1311 } else if (!strcmp(devname, "keyboard")) {
1312 dev = usb_keyboard_init();
1313 } else if (strstart(devname, "disk:", &p)) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001314 BlockDriverState *bs;
1315
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001316 dev = usb_msd_init(p);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001317 if (!dev)
1318 return -1;
1319 bs = usb_msd_get_bdrv(dev);
1320 if (bdrv_key_required(bs)) {
1321 autostart = 0;
1322 if (is_hotplug) {
1323 monitor_read_bdrv_key_start(cur_mon, bs, usb_msd_password_cb,
1324 dev);
1325 return 0;
1326 }
1327 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001328 } else if (!strcmp(devname, "wacom-tablet")) {
1329 dev = usb_wacom_init();
1330 } else if (strstart(devname, "serial:", &p)) {
1331 dev = usb_serial_init(p);
1332#ifdef CONFIG_BRLAPI
1333 } else if (!strcmp(devname, "braille")) {
1334 dev = usb_baum_init();
1335#endif
1336 } else if (strstart(devname, "net:", &p)) {
1337 int nic = nb_nics;
1338
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001339 if (net_client_init(NULL, "nic", p) < 0)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001340 return -1;
1341 nd_table[nic].model = "usb";
1342 dev = usb_net_init(&nd_table[nic]);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001343 } else if (!strcmp(devname, "bt") || strstart(devname, "bt:", &p)) {
1344 dev = usb_bt_init(devname[2] ? hci_init(p) :
1345 bt_new_hci(qemu_find_bt_vlan(0)));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001346 } else {
1347 return -1;
1348 }
1349 if (!dev)
1350 return -1;
1351
1352 return usb_device_add_dev(dev);
1353}
1354
1355int usb_device_del_addr(int bus_num, int addr)
1356{
1357 USBPort *port;
1358 USBPort **lastp;
1359 USBDevice *dev;
1360
1361 if (!used_usb_ports)
1362 return -1;
1363
1364 if (bus_num != 0)
1365 return -1;
1366
1367 lastp = &used_usb_ports;
1368 port = used_usb_ports;
1369 while (port && port->dev->addr != addr) {
1370 lastp = &port->next;
1371 port = port->next;
1372 }
1373
1374 if (!port)
1375 return -1;
1376
1377 dev = port->dev;
1378 *lastp = port->next;
1379 usb_attach(port, NULL);
1380 dev->handle_destroy(dev);
1381 port->next = free_usb_ports;
1382 free_usb_ports = port;
1383 return 0;
1384}
1385
1386static int usb_device_del(const char *devname)
1387{
1388 int bus_num, addr;
1389 const char *p;
1390
1391 if (strstart(devname, "host:", &p))
1392 return usb_host_device_close(p);
1393
1394 if (!used_usb_ports)
1395 return -1;
1396
1397 p = strchr(devname, '.');
1398 if (!p)
1399 return -1;
1400 bus_num = strtoul(devname, NULL, 0);
1401 addr = strtoul(p + 1, NULL, 0);
1402
1403 return usb_device_del_addr(bus_num, addr);
1404}
1405
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001406void do_usb_add(Monitor *mon, const char *devname)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001407{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001408 usb_device_add(devname, 1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001409}
1410
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001411void do_usb_del(Monitor *mon, const char *devname)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001412{
1413 usb_device_del(devname);
1414}
1415
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001416void usb_info(Monitor *mon)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001417{
1418 USBDevice *dev;
1419 USBPort *port;
1420 const char *speed_str;
1421
1422 if (!usb_enabled) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001423 monitor_printf(mon, "USB support not enabled\n");
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001424 return;
1425 }
1426
1427 for (port = used_usb_ports; port; port = port->next) {
1428 dev = port->dev;
1429 if (!dev)
1430 continue;
1431 switch(dev->speed) {
1432 case USB_SPEED_LOW:
1433 speed_str = "1.5";
1434 break;
1435 case USB_SPEED_FULL:
1436 speed_str = "12";
1437 break;
1438 case USB_SPEED_HIGH:
1439 speed_str = "480";
1440 break;
1441 default:
1442 speed_str = "?";
1443 break;
1444 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001445 monitor_printf(mon, " Device %d.%d, Speed %s Mb/s, Product %s\n",
1446 0, dev->addr, speed_str, dev->devname);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001447 }
1448}
1449
1450/***********************************************************/
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001451/* PCMCIA/Cardbus */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001452
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001453static struct pcmcia_socket_entry_s {
1454 PCMCIASocket *socket;
1455 struct pcmcia_socket_entry_s *next;
1456} *pcmcia_sockets = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001457
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001458void pcmcia_socket_register(PCMCIASocket *socket)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001459{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001460 struct pcmcia_socket_entry_s *entry;
1461
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01001462 entry = g_malloc(sizeof(struct pcmcia_socket_entry_s));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001463 entry->socket = socket;
1464 entry->next = pcmcia_sockets;
1465 pcmcia_sockets = entry;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001466}
1467
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001468void pcmcia_socket_unregister(PCMCIASocket *socket)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001469{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001470 struct pcmcia_socket_entry_s *entry, **ptr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001471
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001472 ptr = &pcmcia_sockets;
1473 for (entry = *ptr; entry; ptr = &entry->next, entry = *ptr)
1474 if (entry->socket == socket) {
1475 *ptr = entry->next;
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01001476 g_free(entry);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001477 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001478}
1479
1480void pcmcia_info(Monitor *mon)
1481{
1482 struct pcmcia_socket_entry_s *iter;
1483
1484 if (!pcmcia_sockets)
1485 monitor_printf(mon, "No PCMCIA sockets\n");
1486
1487 for (iter = pcmcia_sockets; iter; iter = iter->next)
1488 monitor_printf(mon, "%s: %s\n", iter->socket->slot_string,
1489 iter->socket->attached ? iter->socket->card_string :
1490 "Empty");
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001491}
1492
1493/***********************************************************/
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001494/* machine registration */
1495
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001496static QEMUMachine *first_machine = NULL;
1497QEMUMachine *current_machine = NULL;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001498
1499int qemu_register_machine(QEMUMachine *m)
1500{
1501 QEMUMachine **pm;
1502 pm = &first_machine;
1503 while (*pm != NULL)
1504 pm = &(*pm)->next;
1505 m->next = NULL;
1506 *pm = m;
1507 return 0;
1508}
1509
1510static QEMUMachine *find_machine(const char *name)
1511{
1512 QEMUMachine *m;
1513
1514 for(m = first_machine; m != NULL; m = m->next) {
1515 if (!strcmp(m->name, name))
1516 return m;
1517 }
1518 return NULL;
1519}
1520
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001521static QEMUMachine *find_default_machine(void)
1522{
1523 QEMUMachine *m;
1524
1525 for(m = first_machine; m != NULL; m = m->next) {
1526 if (m->is_default) {
1527 return m;
1528 }
1529 }
1530 return NULL;
1531}
1532
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001533/***********************************************************/
1534/* main execution loop */
1535
1536static void gui_update(void *opaque)
1537{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001538 uint64_t interval = GUI_REFRESH_INTERVAL;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001539 DisplayState *ds = opaque;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001540 DisplayChangeListener *dcl = ds->listeners;
1541
1542 dpy_refresh(ds);
1543
1544 while (dcl != NULL) {
1545 if (dcl->gui_timer_interval &&
1546 dcl->gui_timer_interval < interval)
1547 interval = dcl->gui_timer_interval;
1548 dcl = dcl->next;
1549 }
David 'Digit' Turner5973c772011-05-10 07:06:00 +02001550 qemu_mod_timer(ds->gui_timer, interval + qemu_get_clock_ms(rt_clock));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001551}
1552
1553static void nographic_update(void *opaque)
1554{
1555 uint64_t interval = GUI_REFRESH_INTERVAL;
1556
David 'Digit' Turner5973c772011-05-10 07:06:00 +02001557 qemu_mod_timer(nographic_timer, interval + qemu_get_clock_ms(rt_clock));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001558}
1559
1560struct vm_change_state_entry {
1561 VMChangeStateHandler *cb;
1562 void *opaque;
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001563 QLIST_ENTRY (vm_change_state_entry) entries;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001564};
1565
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001566static QLIST_HEAD(vm_change_state_head, vm_change_state_entry) vm_change_state_head;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001567
1568VMChangeStateEntry *qemu_add_vm_change_state_handler(VMChangeStateHandler *cb,
1569 void *opaque)
1570{
1571 VMChangeStateEntry *e;
1572
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01001573 e = g_malloc0(sizeof (*e));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001574
1575 e->cb = cb;
1576 e->opaque = opaque;
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001577 QLIST_INSERT_HEAD(&vm_change_state_head, e, entries);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001578 return e;
1579}
1580
1581void qemu_del_vm_change_state_handler(VMChangeStateEntry *e)
1582{
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001583 QLIST_REMOVE (e, entries);
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01001584 g_free (e);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001585}
1586
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +02001587void vm_state_notify(int running, int reason)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001588{
1589 VMChangeStateEntry *e;
1590
1591 for (e = vm_change_state_head.lh_first; e; e = e->entries.le_next) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001592 e->cb(e->opaque, running, reason);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001593 }
1594}
1595
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001596void vm_start(void)
1597{
1598 if (!vm_running) {
1599 cpu_enable_ticks();
1600 vm_running = 1;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001601 vm_state_notify(1, 0);
David Turner6a9ef172010-09-09 22:54:36 +02001602 //qemu_rearm_alarm_timer(alarm_timer);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001603 resume_all_vcpus();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001604 }
1605}
1606
1607/* reset/shutdown handler */
1608
1609typedef struct QEMUResetEntry {
David Turner025c32f2010-09-10 14:52:42 +02001610 QTAILQ_ENTRY(QEMUResetEntry) entry;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001611 QEMUResetHandler *func;
1612 void *opaque;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001613} QEMUResetEntry;
1614
David Turner025c32f2010-09-10 14:52:42 +02001615static QTAILQ_HEAD(reset_handlers, QEMUResetEntry) reset_handlers =
1616 QTAILQ_HEAD_INITIALIZER(reset_handlers);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001617static int reset_requested;
David 'Digit' Turner088edf82011-05-09 15:59:28 +02001618static int shutdown_requested, shutdown_signal = -1;
1619static pid_t shutdown_pid;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001620static int powerdown_requested;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +02001621int debug_requested;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001622static int vmstop_requested;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001623
1624int qemu_shutdown_requested(void)
1625{
1626 int r = shutdown_requested;
1627 shutdown_requested = 0;
1628 return r;
1629}
1630
1631int qemu_reset_requested(void)
1632{
1633 int r = reset_requested;
1634 reset_requested = 0;
1635 return r;
1636}
1637
1638int qemu_powerdown_requested(void)
1639{
1640 int r = powerdown_requested;
1641 powerdown_requested = 0;
1642 return r;
1643}
1644
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001645static int qemu_debug_requested(void)
1646{
1647 int r = debug_requested;
1648 debug_requested = 0;
1649 return r;
1650}
1651
1652static int qemu_vmstop_requested(void)
1653{
1654 int r = vmstop_requested;
1655 vmstop_requested = 0;
1656 return r;
1657}
1658
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001659void qemu_register_reset(QEMUResetHandler *func, int order, void *opaque)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001660{
1661 QEMUResetEntry **pre, *re;
1662
1663 pre = &first_reset_entry;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001664 while (*pre != NULL && (*pre)->order >= order) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001665 pre = &(*pre)->next;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001666 }
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01001667 re = g_malloc0(sizeof(QEMUResetEntry));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001668 re->func = func;
1669 re->opaque = opaque;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001670 re->order = order;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001671 re->next = NULL;
1672 *pre = re;
1673}
1674
1675void qemu_system_reset(void)
1676{
1677 QEMUResetEntry *re;
1678
1679 /* reset all devices */
David Turner025c32f2010-09-10 14:52:42 +02001680 QTAILQ_FOREACH_SAFE(re, &reset_handlers, entry, nre) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001681 re->func(re->opaque);
1682 }
1683}
1684
1685void qemu_system_reset_request(void)
1686{
1687 if (no_reboot) {
1688 shutdown_requested = 1;
1689 } else {
1690 reset_requested = 1;
1691 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001692 qemu_notify_event();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001693}
1694
David 'Digit' Turner088edf82011-05-09 15:59:28 +02001695void qemu_system_killed(int signal, pid_t pid)
1696{
1697 shutdown_signal = signal;
1698 shutdown_pid = pid;
1699 qemu_system_shutdown_request();
1700}
1701
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001702void qemu_system_shutdown_request(void)
1703{
1704 shutdown_requested = 1;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001705 qemu_notify_event();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001706}
1707
1708void qemu_system_powerdown_request(void)
1709{
1710 powerdown_requested = 1;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001711 qemu_notify_event();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001712}
1713
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001714#ifdef CONFIG_IOTHREAD
1715static void qemu_system_vmstop_request(int reason)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001716{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001717 vmstop_requested = reason;
1718 qemu_notify_event();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001719}
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001720#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001721
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001722void main_loop_wait(int timeout)
1723{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001724 fd_set rfds, wfds, xfds;
1725 int ret, nfds;
1726 struct timeval tv;
1727
1728 qemu_bh_update_timeout(&timeout);
1729
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +02001730 os_host_main_loop_wait(&timeout);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001731
David 'Digit' Turner8354d2d2011-05-11 00:19:06 +02001732
1733 tv.tv_sec = timeout / 1000;
1734 tv.tv_usec = (timeout % 1000) * 1000;
1735
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001736 /* poll any events */
David 'Digit' Turner8354d2d2011-05-11 00:19:06 +02001737
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001738 /* XXX: separate device handlers from system ones */
1739 nfds = -1;
1740 FD_ZERO(&rfds);
1741 FD_ZERO(&wfds);
1742 FD_ZERO(&xfds);
David 'Digit' Turner8354d2d2011-05-11 00:19:06 +02001743 qemu_iohandler_fill(&nfds, &rfds, &wfds, &xfds);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001744 if (slirp_is_inited()) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001745 slirp_select_fill(&nfds, &rfds, &wfds, &xfds);
1746 }
David 'Digit' Turner8354d2d2011-05-11 00:19:06 +02001747
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001748 qemu_mutex_unlock_iothread();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001749 ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001750 qemu_mutex_lock_iothread();
David 'Digit' Turner8354d2d2011-05-11 00:19:06 +02001751 qemu_iohandler_poll(&rfds, &wfds, &xfds, ret);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001752 if (slirp_is_inited()) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001753 if (ret < 0) {
1754 FD_ZERO(&rfds);
1755 FD_ZERO(&wfds);
1756 FD_ZERO(&xfds);
1757 }
1758 slirp_select_poll(&rfds, &wfds, &xfds);
1759 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001760
David Turner6a9ef172010-09-09 22:54:36 +02001761 qemu_run_all_timers();
David 'Digit' Turnera7fb77d2010-05-10 23:50:54 -07001762
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001763 /* Check bottom-halves last in case any of the earlier events triggered
1764 them. */
1765 qemu_bh_poll();
1766
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001767}
1768
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001769static int vm_can_run(void)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001770{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001771 if (powerdown_requested)
1772 return 0;
1773 if (reset_requested)
1774 return 0;
1775 if (shutdown_requested)
1776 return 0;
1777 if (debug_requested)
1778 return 0;
1779 return 1;
1780}
1781
1782static void main_loop(void)
1783{
1784 int r;
1785
1786#ifdef CONFIG_IOTHREAD
1787 qemu_system_ready = 1;
1788 qemu_cond_broadcast(&qemu_system_cond);
1789#endif
1790
1791 for (;;) {
1792 do {
1793#ifdef CONFIG_PROFILER
1794 int64_t ti;
1795#endif
1796#ifndef CONFIG_IOTHREAD
1797 tcg_cpu_exec();
1798#endif
1799#ifdef CONFIG_PROFILER
1800 ti = profile_getclock();
1801#endif
1802 main_loop_wait(qemu_calculate_timeout());
1803#ifdef CONFIG_PROFILER
1804 dev_time += profile_getclock() - ti;
1805#endif
1806 } while (vm_can_run());
1807
1808 if (qemu_debug_requested())
1809 vm_stop(EXCP_DEBUG);
1810 if (qemu_shutdown_requested()) {
1811 if (no_shutdown) {
1812 vm_stop(0);
1813 no_shutdown = 0;
1814 } else
1815 break;
1816 }
1817 if (qemu_reset_requested()) {
1818 pause_all_vcpus();
1819 qemu_system_reset();
1820 resume_all_vcpus();
1821 }
1822 if (qemu_powerdown_requested())
1823 qemu_system_powerdown();
1824 if ((r = qemu_vmstop_requested()))
1825 vm_stop(r);
1826 }
1827 pause_all_vcpus();
1828}
1829
1830static void version(void)
1831{
1832 printf("QEMU PC emulator version " QEMU_VERSION QEMU_PKGVERSION ", Copyright (c) 2003-2008 Fabrice Bellard\n");
1833}
1834
1835static void help(int exitcode)
1836{
1837 version();
1838 printf("usage: %s [options] [disk_image]\n"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001839 "\n"
1840 "'disk_image' is a raw hard image image for IDE hard disk 0\n"
1841 "\n"
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001842#define DEF(option, opt_arg, opt_enum, opt_help) \
1843 opt_help
1844#define DEFHEADING(text) stringify(text) "\n"
David 'Digit' Turnerc1ac40a2011-06-01 16:12:04 +02001845#include "qemu-options.def"
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001846#undef DEF
1847#undef DEFHEADING
1848#undef GEN_DOCS
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001849 "\n"
1850 "During emulation, the following keys are useful:\n"
1851 "ctrl-alt-f toggle full screen\n"
1852 "ctrl-alt-n switch to virtual console 'n'\n"
1853 "ctrl-alt toggle mouse and keyboard grab\n"
1854 "\n"
1855 "When using -nographic, press 'ctrl-a h' to get some help.\n"
1856 ,
1857 "qemu",
1858 DEFAULT_RAM_SIZE,
1859#ifndef _WIN32
1860 DEFAULT_NETWORK_SCRIPT,
1861 DEFAULT_NETWORK_DOWN_SCRIPT,
1862#endif
1863 DEFAULT_GDBSTUB_PORT,
1864 "/tmp/qemu.log");
1865 exit(exitcode);
1866}
1867
1868#define HAS_ARG 0x0001
1869
1870enum {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001871#define DEF(option, opt_arg, opt_enum, opt_help) \
1872 opt_enum,
1873#define DEFHEADING(text)
David 'Digit' Turnerc1ac40a2011-06-01 16:12:04 +02001874#include "qemu-options.def"
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001875#undef DEF
1876#undef DEFHEADING
1877#undef GEN_DOCS
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001878};
1879
1880typedef struct QEMUOption {
1881 const char *name;
1882 int flags;
1883 int index;
1884} QEMUOption;
1885
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001886static const QEMUOption qemu_options[] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001887 { "h", 0, QEMU_OPTION_h },
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001888#define DEF(option, opt_arg, opt_enum, opt_help) \
1889 { option, opt_arg, opt_enum },
1890#define DEFHEADING(text)
David 'Digit' Turnerc1ac40a2011-06-01 16:12:04 +02001891#include "qemu-options.def"
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001892#undef DEF
1893#undef DEFHEADING
1894#undef GEN_DOCS
David 'Digit' Turnerc1ac40a2011-06-01 16:12:04 +02001895 { NULL, 0, 0 },
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001896};
1897
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001898static void select_vgahw (const char *p)
1899{
1900 const char *opts;
1901
1902 cirrus_vga_enabled = 0;
1903 std_vga_enabled = 0;
1904 vmsvga_enabled = 0;
1905 xenfb_enabled = 0;
1906 if (strstart(p, "std", &opts)) {
1907 std_vga_enabled = 1;
1908 } else if (strstart(p, "cirrus", &opts)) {
1909 cirrus_vga_enabled = 1;
1910 } else if (strstart(p, "vmware", &opts)) {
1911 vmsvga_enabled = 1;
1912 } else if (strstart(p, "xenfb", &opts)) {
1913 xenfb_enabled = 1;
1914 } else if (!strstart(p, "none", &opts)) {
1915 invalid_vga:
1916 fprintf(stderr, "Unknown vga type: %s\n", p);
1917 exit(1);
1918 }
1919 while (*opts) {
1920 const char *nextopt;
1921
1922 if (strstart(opts, ",retrace=", &nextopt)) {
1923 opts = nextopt;
1924 if (strstart(opts, "dumb", &nextopt))
1925 vga_retrace_method = VGA_RETRACE_DUMB;
1926 else if (strstart(opts, "precise", &nextopt))
1927 vga_retrace_method = VGA_RETRACE_PRECISE;
1928 else goto invalid_vga;
1929 } else goto invalid_vga;
1930 opts = nextopt;
1931 }
1932}
1933
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001934#define MAX_NET_CLIENTS 32
1935
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001936#ifdef _WIN32
1937/* Look for support files in the same directory as the executable. */
1938static char *find_datadir(const char *argv0)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001939{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001940 char *p;
1941 char buf[MAX_PATH];
1942 DWORD len;
1943
1944 len = GetModuleFileName(NULL, buf, sizeof(buf) - 1);
1945 if (len == 0) {
1946 return NULL;
1947 }
1948
1949 buf[len] = 0;
1950 p = buf + len - 1;
1951 while (p != buf && *p != '\\')
1952 p--;
1953 *p = 0;
1954 if (access(buf, R_OK) == 0) {
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01001955 return g_strdup(buf);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001956 }
1957 return NULL;
1958}
1959#else /* !_WIN32 */
1960
1961/* Find a likely location for support files using the location of the binary.
1962 For installed binaries this will be "$bindir/../share/qemu". When
1963 running from the build tree this will be "$bindir/../pc-bios". */
1964#define SHARE_SUFFIX "/share/qemu"
1965#define BUILD_SUFFIX "/pc-bios"
1966static char *find_datadir(const char *argv0)
1967{
1968 char *dir;
1969 char *p = NULL;
1970 char *res;
1971#ifdef PATH_MAX
1972 char buf[PATH_MAX];
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001973#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001974 size_t max_len;
1975
1976#if defined(__linux__)
1977 {
1978 int len;
1979 len = readlink("/proc/self/exe", buf, sizeof(buf) - 1);
1980 if (len > 0) {
1981 buf[len] = 0;
1982 p = buf;
1983 }
1984 }
1985#elif defined(__FreeBSD__)
1986 {
1987 int len;
1988 len = readlink("/proc/curproc/file", buf, sizeof(buf) - 1);
1989 if (len > 0) {
1990 buf[len] = 0;
1991 p = buf;
1992 }
1993 }
1994#endif
1995 /* If we don't have any way of figuring out the actual executable
1996 location then try argv[0]. */
1997 if (!p) {
1998#ifdef PATH_MAX
1999 p = buf;
2000#endif
2001 p = realpath(argv0, p);
2002 if (!p) {
2003 return NULL;
2004 }
2005 }
2006 dir = dirname(p);
2007 dir = dirname(dir);
2008
2009 max_len = strlen(dir) +
2010 MAX(strlen(SHARE_SUFFIX), strlen(BUILD_SUFFIX)) + 1;
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01002011 res = g_malloc0(max_len);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002012 snprintf(res, max_len, "%s%s", dir, SHARE_SUFFIX);
2013 if (access(res, R_OK)) {
2014 snprintf(res, max_len, "%s%s", dir, BUILD_SUFFIX);
2015 if (access(res, R_OK)) {
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01002016 g_free(res);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002017 res = NULL;
2018 }
2019 }
2020#ifndef PATH_MAX
2021 free(p);
2022#endif
2023 return res;
2024}
2025#undef SHARE_SUFFIX
2026#undef BUILD_SUFFIX
2027#endif
2028
2029char *qemu_find_file(int type, const char *name)
2030{
2031 int len;
2032 const char *subdir;
2033 char *buf;
2034
2035 /* If name contains path separators then try it as a straight path. */
2036 if ((strchr(name, '/') || strchr(name, '\\'))
2037 && access(name, R_OK) == 0) {
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01002038 return g_strdup(name);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002039 }
2040 switch (type) {
2041 case QEMU_FILE_TYPE_BIOS:
2042 subdir = "";
2043 break;
2044 case QEMU_FILE_TYPE_KEYMAP:
2045 subdir = "keymaps/";
2046 break;
2047 default:
2048 abort();
2049 }
2050 len = strlen(data_dir) + strlen(name) + strlen(subdir) + 2;
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01002051 buf = g_malloc0(len);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002052 snprintf(buf, len, "%s/%s%s", data_dir, subdir, name);
2053 if (access(buf, R_OK)) {
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01002054 g_free(buf);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002055 return NULL;
2056 }
2057 return buf;
2058}
2059
2060int main(int argc, char **argv, char **envp)
2061{
2062 const char *gdbstub_dev = NULL;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002063 uint32_t boot_devices_bitmap = 0;
2064 int i;
2065 int snapshot, linux_boot, net_boot;
David Turner6a9ef172010-09-09 22:54:36 +02002066 const char *icount_option = NULL;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002067 const char *initrd_filename;
2068 const char *kernel_filename, *kernel_cmdline;
2069 const char *boot_devices = "";
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002070 DisplayState *ds;
2071 DisplayChangeListener *dcl;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002072 int cyls, heads, secs, translation;
2073 const char *net_clients[MAX_NET_CLIENTS];
2074 int nb_net_clients;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002075 const char *bt_opts[MAX_BT_CMDLINE];
2076 int nb_bt_opts;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002077 int hda_index;
2078 int optind;
2079 const char *r, *optarg;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002080 CharDriverState *monitor_hd = NULL;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002081 const char *monitor_device;
2082 const char *serial_devices[MAX_SERIAL_PORTS];
2083 int serial_device_index;
2084 const char *parallel_devices[MAX_PARALLEL_PORTS];
2085 int parallel_device_index;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002086 const char *virtio_consoles[MAX_VIRTIO_CONSOLES];
2087 int virtio_console_index;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002088 const char *loadvm = NULL;
2089 QEMUMachine *machine;
2090 const char *cpu_model;
2091 const char *usb_devices[MAX_USB_CMDLINE];
2092 int usb_devices_index;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002093 int tb_size;
2094 const char *pid_file = NULL;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002095 const char *incoming = NULL;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002096 CPUState *env;
2097 int show_vnc_port = 0;
2098
David 'Digit' Turnera7fb77d2010-05-10 23:50:54 -07002099 init_clocks();
2100
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002101 qemu_cache_utils_init(envp);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002102
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002103 QLIST_INIT (&vm_change_state_head);
David 'Digit' Turnerc1ac40a2011-06-01 16:12:04 +02002104 os_setup_early_signal_handling();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002105
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002106 module_call_init(MODULE_INIT_MACHINE);
2107 machine = find_default_machine();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002108 cpu_model = NULL;
2109 initrd_filename = NULL;
2110 ram_size = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002111 snapshot = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002112 kernel_filename = NULL;
2113 kernel_cmdline = "";
2114 cyls = heads = secs = 0;
2115 translation = BIOS_ATA_TRANSLATION_AUTO;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002116 monitor_device = "vc:80Cx24C";
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002117
2118 serial_devices[0] = "vc:80Cx24C";
2119 for(i = 1; i < MAX_SERIAL_PORTS; i++)
2120 serial_devices[i] = NULL;
2121 serial_device_index = 0;
2122
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002123 parallel_devices[0] = "vc:80Cx24C";
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002124 for(i = 1; i < MAX_PARALLEL_PORTS; i++)
2125 parallel_devices[i] = NULL;
2126 parallel_device_index = 0;
2127
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002128 for(i = 0; i < MAX_VIRTIO_CONSOLES; i++)
2129 virtio_consoles[i] = NULL;
2130 virtio_console_index = 0;
2131
2132 for (i = 0; i < MAX_NODES; i++) {
2133 node_mem[i] = 0;
2134 node_cpumask[i] = 0;
2135 }
2136
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002137 usb_devices_index = 0;
2138
2139 nb_net_clients = 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002140 nb_bt_opts = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002141 nb_drives = 0;
2142 nb_drives_opt = 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002143 nb_numa_nodes = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002144 hda_index = -1;
2145
2146 nb_nics = 0;
2147
2148 tb_size = 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002149 autostart= 1;
2150
2151 register_watchdogs();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002152
2153 optind = 1;
2154 for(;;) {
2155 if (optind >= argc)
2156 break;
2157 r = argv[optind];
2158 if (r[0] != '-') {
2159 hda_index = drive_add(argv[optind++], HD_ALIAS, 0);
2160 } else {
2161 const QEMUOption *popt;
2162
2163 optind++;
2164 /* Treat --foo the same as -foo. */
2165 if (r[1] == '-')
2166 r++;
2167 popt = qemu_options;
2168 for(;;) {
2169 if (!popt->name) {
2170 fprintf(stderr, "%s: invalid option -- '%s'\n",
2171 argv[0], r);
2172 exit(1);
2173 }
2174 if (!strcmp(popt->name, r + 1))
2175 break;
2176 popt++;
2177 }
2178 if (popt->flags & HAS_ARG) {
2179 if (optind >= argc) {
2180 fprintf(stderr, "%s: option '%s' requires an argument\n",
2181 argv[0], r);
2182 exit(1);
2183 }
2184 optarg = argv[optind++];
2185 } else {
2186 optarg = NULL;
2187 }
2188
2189 switch(popt->index) {
2190 case QEMU_OPTION_M:
2191 machine = find_machine(optarg);
2192 if (!machine) {
2193 QEMUMachine *m;
2194 printf("Supported machines are:\n");
2195 for(m = first_machine; m != NULL; m = m->next) {
2196 printf("%-10s %s%s\n",
2197 m->name, m->desc,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002198 m->is_default ? " (default)" : "");
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002199 }
2200 exit(*optarg != '?');
2201 }
2202 break;
2203 case QEMU_OPTION_cpu:
2204 /* hw initialization will check this */
2205 if (*optarg == '?') {
2206/* XXX: implement xxx_cpu_list for targets that still miss it */
2207#if defined(cpu_list)
2208 cpu_list(stdout, &fprintf);
2209#endif
2210 exit(0);
2211 } else {
2212 cpu_model = optarg;
2213 }
2214 break;
2215 case QEMU_OPTION_initrd:
2216 initrd_filename = optarg;
2217 break;
2218 case QEMU_OPTION_hda:
2219 if (cyls == 0)
2220 hda_index = drive_add(optarg, HD_ALIAS, 0);
2221 else
2222 hda_index = drive_add(optarg, HD_ALIAS
2223 ",cyls=%d,heads=%d,secs=%d%s",
2224 0, cyls, heads, secs,
2225 translation == BIOS_ATA_TRANSLATION_LBA ?
2226 ",trans=lba" :
2227 translation == BIOS_ATA_TRANSLATION_NONE ?
2228 ",trans=none" : "");
2229 break;
2230 case QEMU_OPTION_hdb:
2231 case QEMU_OPTION_hdc:
2232 case QEMU_OPTION_hdd:
2233 drive_add(optarg, HD_ALIAS, popt->index - QEMU_OPTION_hda);
2234 break;
2235 case QEMU_OPTION_drive:
2236 drive_add(NULL, "%s", optarg);
2237 break;
2238 case QEMU_OPTION_mtdblock:
2239 drive_add(optarg, MTD_ALIAS);
2240 break;
2241 case QEMU_OPTION_sd:
2242 drive_add(optarg, SD_ALIAS);
2243 break;
2244 case QEMU_OPTION_pflash:
2245 drive_add(optarg, PFLASH_ALIAS);
2246 break;
2247 case QEMU_OPTION_snapshot:
2248 snapshot = 1;
2249 break;
2250 case QEMU_OPTION_hdachs:
2251 {
2252 const char *p;
2253 p = optarg;
2254 cyls = strtol(p, (char **)&p, 0);
2255 if (cyls < 1 || cyls > 16383)
2256 goto chs_fail;
2257 if (*p != ',')
2258 goto chs_fail;
2259 p++;
2260 heads = strtol(p, (char **)&p, 0);
2261 if (heads < 1 || heads > 16)
2262 goto chs_fail;
2263 if (*p != ',')
2264 goto chs_fail;
2265 p++;
2266 secs = strtol(p, (char **)&p, 0);
2267 if (secs < 1 || secs > 63)
2268 goto chs_fail;
2269 if (*p == ',') {
2270 p++;
2271 if (!strcmp(p, "none"))
2272 translation = BIOS_ATA_TRANSLATION_NONE;
2273 else if (!strcmp(p, "lba"))
2274 translation = BIOS_ATA_TRANSLATION_LBA;
2275 else if (!strcmp(p, "auto"))
2276 translation = BIOS_ATA_TRANSLATION_AUTO;
2277 else
2278 goto chs_fail;
2279 } else if (*p != '\0') {
2280 chs_fail:
2281 fprintf(stderr, "qemu: invalid physical CHS format\n");
2282 exit(1);
2283 }
2284 if (hda_index != -1)
2285 snprintf(drives_opt[hda_index].opt,
2286 sizeof(drives_opt[hda_index].opt),
2287 HD_ALIAS ",cyls=%d,heads=%d,secs=%d%s",
2288 0, cyls, heads, secs,
2289 translation == BIOS_ATA_TRANSLATION_LBA ?
2290 ",trans=lba" :
2291 translation == BIOS_ATA_TRANSLATION_NONE ?
2292 ",trans=none" : "");
2293 }
2294 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002295 case QEMU_OPTION_numa:
2296 if (nb_numa_nodes >= MAX_NODES) {
2297 fprintf(stderr, "qemu: too many NUMA nodes\n");
2298 exit(1);
2299 }
2300 numa_add(optarg);
2301 break;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002302 case QEMU_OPTION_nographic:
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002303 display_type = DT_NOGRAPHIC;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002304 break;
2305#ifdef CONFIG_CURSES
2306 case QEMU_OPTION_curses:
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002307 display_type = DT_CURSES;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002308 break;
2309#endif
2310 case QEMU_OPTION_portrait:
2311 graphic_rotate = 1;
2312 break;
2313 case QEMU_OPTION_kernel:
2314 kernel_filename = optarg;
2315 break;
2316 case QEMU_OPTION_append:
2317 kernel_cmdline = optarg;
2318 break;
2319 case QEMU_OPTION_cdrom:
2320 drive_add(optarg, CDROM_ALIAS);
2321 break;
2322 case QEMU_OPTION_boot:
2323 boot_devices = optarg;
2324 /* We just do some generic consistency checks */
2325 {
2326 /* Could easily be extended to 64 devices if needed */
2327 const char *p;
David 'Digit' Turner707c8a82010-12-22 22:35:58 +01002328
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002329 boot_devices_bitmap = 0;
2330 for (p = boot_devices; *p != '\0'; p++) {
2331 /* Allowed boot devices are:
2332 * a b : floppy disk drives
2333 * c ... f : IDE disk drives
2334 * g ... m : machine implementation dependant drives
2335 * n ... p : network devices
2336 * It's up to each machine implementation to check
2337 * if the given boot devices match the actual hardware
2338 * implementation and firmware features.
2339 */
2340 if (*p < 'a' || *p > 'q') {
2341 fprintf(stderr, "Invalid boot device '%c'\n", *p);
2342 exit(1);
2343 }
2344 if (boot_devices_bitmap & (1 << (*p - 'a'))) {
2345 fprintf(stderr,
2346 "Boot device '%c' was given twice\n",*p);
2347 exit(1);
2348 }
2349 boot_devices_bitmap |= 1 << (*p - 'a');
2350 }
2351 }
2352 break;
2353 case QEMU_OPTION_fda:
2354 case QEMU_OPTION_fdb:
2355 drive_add(optarg, FD_ALIAS, popt->index - QEMU_OPTION_fda);
2356 break;
2357#ifdef TARGET_I386
2358 case QEMU_OPTION_no_fd_bootchk:
2359 fd_bootchk = 0;
2360 break;
2361#endif
2362 case QEMU_OPTION_net:
2363 if (nb_net_clients >= MAX_NET_CLIENTS) {
2364 fprintf(stderr, "qemu: too many network clients\n");
2365 exit(1);
2366 }
2367 net_clients[nb_net_clients] = optarg;
2368 nb_net_clients++;
2369 break;
2370#ifdef CONFIG_SLIRP
2371 case QEMU_OPTION_tftp:
2372 tftp_prefix = optarg;
2373 break;
2374 case QEMU_OPTION_bootp:
2375 bootp_filename = optarg;
2376 break;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002377 case QEMU_OPTION_redir:
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002378 net_slirp_redir(NULL, optarg, NULL);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002379 break;
2380#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002381 case QEMU_OPTION_bt:
2382 if (nb_bt_opts >= MAX_BT_CMDLINE) {
2383 fprintf(stderr, "qemu: too many bluetooth options\n");
2384 exit(1);
2385 }
2386 bt_opts[nb_bt_opts++] = optarg;
2387 break;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002388#ifdef HAS_AUDIO
2389 case QEMU_OPTION_audio_help:
2390 AUD_help ();
2391 exit (0);
2392 break;
2393 case QEMU_OPTION_soundhw:
2394 select_soundhw (optarg);
2395 break;
2396#endif
2397 case QEMU_OPTION_h:
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002398 help(0);
2399 break;
2400 case QEMU_OPTION_version:
2401 version();
2402 exit(0);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002403 break;
2404 case QEMU_OPTION_m: {
2405 uint64_t value;
2406 char *ptr;
2407
2408 value = strtoul(optarg, &ptr, 10);
2409 switch (*ptr) {
2410 case 0: case 'M': case 'm':
2411 value <<= 20;
2412 break;
2413 case 'G': case 'g':
2414 value <<= 30;
2415 break;
2416 default:
2417 fprintf(stderr, "qemu: invalid ram size: %s\n", optarg);
2418 exit(1);
2419 }
2420
2421 /* On 32-bit hosts, QEMU is limited by virtual address space */
David Turner025c32f2010-09-10 14:52:42 +02002422 if (value > (2047 << 20) && HOST_LONG_BITS == 32) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002423 fprintf(stderr, "qemu: at most 2047 MB RAM can be simulated\n");
2424 exit(1);
2425 }
2426 if (value != (uint64_t)(ram_addr_t)value) {
2427 fprintf(stderr, "qemu: ram size too large\n");
2428 exit(1);
2429 }
2430 ram_size = value;
2431 break;
2432 }
2433 case QEMU_OPTION_d:
2434 {
2435 int mask;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002436 const CPULogItem *item;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002437
2438 mask = cpu_str_to_log_mask(optarg);
2439 if (!mask) {
2440 printf("Log items (comma separated):\n");
2441 for(item = cpu_log_items; item->mask != 0; item++) {
2442 printf("%-10s %s\n", item->name, item->help);
2443 }
2444 exit(1);
2445 }
2446 cpu_set_log(mask);
2447 }
2448 break;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002449 case QEMU_OPTION_s:
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002450 gdbstub_dev = "tcp::" DEFAULT_GDBSTUB_PORT;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002451 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002452 case QEMU_OPTION_gdb:
2453 gdbstub_dev = optarg;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002454 break;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002455 case QEMU_OPTION_L:
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002456 data_dir = optarg;
2457 break;
2458 case QEMU_OPTION_bios:
2459 bios_name = optarg;
2460 break;
2461 case QEMU_OPTION_singlestep:
2462 singlestep = 1;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002463 break;
2464 case QEMU_OPTION_S:
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002465 autostart = 0;
2466 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002467#ifndef _WIN32
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002468 case QEMU_OPTION_k:
2469 keyboard_layout = optarg;
2470 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002471#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002472 case QEMU_OPTION_localtime:
2473 rtc_utc = 0;
2474 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002475 case QEMU_OPTION_vga:
2476 select_vgahw (optarg);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002477 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002478#if defined(TARGET_PPC) || defined(TARGET_SPARC)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002479 case QEMU_OPTION_g:
2480 {
2481 const char *p;
2482 int w, h, depth;
2483 p = optarg;
2484 w = strtol(p, (char **)&p, 10);
2485 if (w <= 0) {
2486 graphic_error:
2487 fprintf(stderr, "qemu: invalid resolution or depth\n");
2488 exit(1);
2489 }
2490 if (*p != 'x')
2491 goto graphic_error;
2492 p++;
2493 h = strtol(p, (char **)&p, 10);
2494 if (h <= 0)
2495 goto graphic_error;
2496 if (*p == 'x') {
2497 p++;
2498 depth = strtol(p, (char **)&p, 10);
2499 if (depth != 8 && depth != 15 && depth != 16 &&
2500 depth != 24 && depth != 32)
2501 goto graphic_error;
2502 } else if (*p == '\0') {
2503 depth = graphic_depth;
2504 } else {
2505 goto graphic_error;
2506 }
2507
2508 graphic_width = w;
2509 graphic_height = h;
2510 graphic_depth = depth;
2511 }
2512 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002513#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002514 case QEMU_OPTION_echr:
2515 {
2516 char *r;
2517 term_escape_char = strtol(optarg, &r, 0);
2518 if (r == optarg)
2519 printf("Bad argument to echr\n");
2520 break;
2521 }
2522 case QEMU_OPTION_monitor:
2523 monitor_device = optarg;
2524 break;
2525 case QEMU_OPTION_serial:
2526 if (serial_device_index >= MAX_SERIAL_PORTS) {
2527 fprintf(stderr, "qemu: too many serial ports\n");
2528 exit(1);
2529 }
2530 serial_devices[serial_device_index] = optarg;
2531 serial_device_index++;
2532 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002533 case QEMU_OPTION_watchdog:
2534 i = select_watchdog(optarg);
2535 if (i > 0)
2536 exit (i == 1 ? 1 : 0);
2537 break;
2538 case QEMU_OPTION_watchdog_action:
2539 if (select_watchdog_action(optarg) == -1) {
2540 fprintf(stderr, "Unknown -watchdog-action parameter\n");
2541 exit(1);
2542 }
2543 break;
2544 case QEMU_OPTION_virtiocon:
2545 if (virtio_console_index >= MAX_VIRTIO_CONSOLES) {
2546 fprintf(stderr, "qemu: too many virtio consoles\n");
2547 exit(1);
2548 }
2549 virtio_consoles[virtio_console_index] = optarg;
2550 virtio_console_index++;
2551 break;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002552 case QEMU_OPTION_parallel:
2553 if (parallel_device_index >= MAX_PARALLEL_PORTS) {
2554 fprintf(stderr, "qemu: too many parallel ports\n");
2555 exit(1);
2556 }
2557 parallel_devices[parallel_device_index] = optarg;
2558 parallel_device_index++;
2559 break;
2560 case QEMU_OPTION_loadvm:
2561 loadvm = optarg;
2562 break;
2563 case QEMU_OPTION_full_screen:
2564 full_screen = 1;
2565 break;
2566#ifdef CONFIG_SDL
2567 case QEMU_OPTION_no_frame:
2568 no_frame = 1;
2569 break;
2570 case QEMU_OPTION_alt_grab:
2571 alt_grab = 1;
2572 break;
2573 case QEMU_OPTION_no_quit:
2574 no_quit = 1;
2575 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002576 case QEMU_OPTION_sdl:
2577 display_type = DT_SDL;
2578 break;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002579#endif
2580 case QEMU_OPTION_pidfile:
2581 pid_file = optarg;
2582 break;
2583#ifdef TARGET_I386
2584 case QEMU_OPTION_win2k_hack:
2585 win2k_install_hack = 1;
2586 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002587 case QEMU_OPTION_rtc_td_hack:
2588 rtc_td_hack = 1;
2589 break;
2590 case QEMU_OPTION_acpitable:
2591 if(acpi_table_add(optarg) < 0) {
2592 fprintf(stderr, "Wrong acpi table provided\n");
2593 exit(1);
2594 }
2595 break;
2596 case QEMU_OPTION_smbios:
2597 if(smbios_entry_add(optarg) < 0) {
2598 fprintf(stderr, "Wrong smbios provided\n");
2599 exit(1);
2600 }
2601 break;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002602#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002603#ifdef CONFIG_KQEMU
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002604 case QEMU_OPTION_no_kqemu:
2605 kqemu_allowed = 0;
2606 break;
2607 case QEMU_OPTION_kernel_kqemu:
2608 kqemu_allowed = 2;
2609 break;
2610#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002611#ifdef CONFIG_KVM
2612 case QEMU_OPTION_enable_kvm:
2613 kvm_allowed = 1;
2614#ifdef CONFIG_KQEMU
2615 kqemu_allowed = 0;
2616#endif
2617 break;
2618#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002619 case QEMU_OPTION_usb:
2620 usb_enabled = 1;
2621 break;
2622 case QEMU_OPTION_usbdevice:
2623 usb_enabled = 1;
2624 if (usb_devices_index >= MAX_USB_CMDLINE) {
2625 fprintf(stderr, "Too many USB devices\n");
2626 exit(1);
2627 }
2628 usb_devices[usb_devices_index] = optarg;
2629 usb_devices_index++;
2630 break;
2631 case QEMU_OPTION_smp:
2632 smp_cpus = atoi(optarg);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002633 if (smp_cpus < 1) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002634 fprintf(stderr, "Invalid number of CPUs\n");
2635 exit(1);
2636 }
2637 break;
2638 case QEMU_OPTION_vnc:
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002639 display_type = DT_VNC;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002640 vnc_display = optarg;
2641 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002642#ifdef TARGET_I386
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002643 case QEMU_OPTION_no_acpi:
2644 acpi_enabled = 0;
2645 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002646 case QEMU_OPTION_no_hpet:
2647 no_hpet = 1;
2648 break;
2649 case QEMU_OPTION_no_virtio_balloon:
2650 no_virtio_balloon = 1;
2651 break;
2652#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002653 case QEMU_OPTION_no_reboot:
2654 no_reboot = 1;
2655 break;
2656 case QEMU_OPTION_no_shutdown:
2657 no_shutdown = 1;
2658 break;
2659 case QEMU_OPTION_show_cursor:
2660 cursor_hide = 0;
2661 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002662 case QEMU_OPTION_uuid:
2663 if(qemu_uuid_parse(optarg, qemu_uuid) < 0) {
2664 fprintf(stderr, "Fail to parse UUID string."
2665 " Wrong format.\n");
2666 exit(1);
2667 }
2668 break;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002669 case QEMU_OPTION_option_rom:
2670 if (nb_option_roms >= MAX_OPTION_ROMS) {
2671 fprintf(stderr, "Too many option ROMs\n");
2672 exit(1);
2673 }
2674 option_rom[nb_option_roms] = optarg;
2675 nb_option_roms++;
2676 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002677#if defined(TARGET_ARM) || defined(TARGET_M68K)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002678 case QEMU_OPTION_semihosting:
2679 semihosting_enabled = 1;
2680 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002681#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002682 case QEMU_OPTION_name:
2683 qemu_name = optarg;
2684 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002685#if defined(TARGET_SPARC) || defined(TARGET_PPC)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002686 case QEMU_OPTION_prom_env:
2687 if (nb_prom_envs >= MAX_PROM_ENVS) {
2688 fprintf(stderr, "Too many prom variables\n");
2689 exit(1);
2690 }
2691 prom_envs[nb_prom_envs] = optarg;
2692 nb_prom_envs++;
2693 break;
2694#endif
2695#ifdef TARGET_ARM
2696 case QEMU_OPTION_old_param:
2697 old_param = 1;
2698 break;
2699#endif
2700 case QEMU_OPTION_clock:
2701 configure_alarms(optarg);
2702 break;
2703 case QEMU_OPTION_startdate:
2704 {
2705 struct tm tm;
David 'Digit' Turnerc1ac40a2011-06-01 16:12:04 +02002706 time_t rtc_start_date = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002707 if (!strcmp(optarg, "now")) {
2708 rtc_date_offset = -1;
2709 } else {
2710 if (sscanf(optarg, "%d-%d-%dT%d:%d:%d",
2711 &tm.tm_year,
2712 &tm.tm_mon,
2713 &tm.tm_mday,
2714 &tm.tm_hour,
2715 &tm.tm_min,
2716 &tm.tm_sec) == 6) {
2717 /* OK */
2718 } else if (sscanf(optarg, "%d-%d-%d",
2719 &tm.tm_year,
2720 &tm.tm_mon,
2721 &tm.tm_mday) == 3) {
2722 tm.tm_hour = 0;
2723 tm.tm_min = 0;
2724 tm.tm_sec = 0;
2725 } else {
2726 goto date_fail;
2727 }
2728 tm.tm_year -= 1900;
2729 tm.tm_mon--;
2730 rtc_start_date = mktimegm(&tm);
2731 if (rtc_start_date == -1) {
2732 date_fail:
2733 fprintf(stderr, "Invalid date format. Valid format are:\n"
2734 "'now' or '2006-06-17T16:01:21' or '2006-06-17'\n");
2735 exit(1);
2736 }
2737 rtc_date_offset = time(NULL) - rtc_start_date;
2738 }
2739 }
2740 break;
2741 case QEMU_OPTION_tb_size:
2742 tb_size = strtol(optarg, NULL, 0);
2743 if (tb_size < 0)
2744 tb_size = 0;
2745 break;
2746 case QEMU_OPTION_icount:
David Turner6a9ef172010-09-09 22:54:36 +02002747 icount_option = optarg;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002748 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002749 case QEMU_OPTION_incoming:
2750 incoming = optarg;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002751 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002752#ifdef CONFIG_XEN
2753 case QEMU_OPTION_xen_domid:
2754 xen_domid = atoi(optarg);
2755 break;
2756 case QEMU_OPTION_xen_create:
2757 xen_mode = XEN_CREATE;
2758 break;
2759 case QEMU_OPTION_xen_attach:
2760 xen_mode = XEN_ATTACH;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002761 break;
2762#endif
2763 }
2764 }
2765 }
2766
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002767 /* If no data_dir is specified then try to find it relative to the
2768 executable path. */
2769 if (!data_dir) {
2770 data_dir = find_datadir(argv[0]);
2771 }
2772 /* If all else fails use the install patch specified when building. */
2773 if (!data_dir) {
2774 data_dir = CONFIG_QEMU_SHAREDIR;
2775 }
2776
David 'Digit' Turnerc1ac40a2011-06-01 16:12:04 +02002777 if (pid_file && qemu_create_pidfile(pid_file) != 0) {
2778 os_pidfile_error();
2779 exit(1);
2780 }
2781
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002782#if defined(CONFIG_KVM) && defined(CONFIG_KQEMU)
2783 if (kvm_allowed && kqemu_allowed) {
2784 fprintf(stderr,
2785 "You can not enable both KVM and kqemu at the same time\n");
2786 exit(1);
2787 }
2788#endif
2789
2790 machine->max_cpus = machine->max_cpus ?: 1; /* Default to UP */
2791 if (smp_cpus > machine->max_cpus) {
2792 fprintf(stderr, "Number of SMP cpus requested (%d), exceeds max cpus "
2793 "supported by machine `%s' (%d)\n", smp_cpus, machine->name,
2794 machine->max_cpus);
2795 exit(1);
2796 }
2797
2798 if (display_type == DT_NOGRAPHIC) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002799 if (serial_device_index == 0)
2800 serial_devices[0] = "stdio";
2801 if (parallel_device_index == 0)
2802 parallel_devices[0] = "null";
2803 if (strncmp(monitor_device, "vc", 2) == 0)
2804 monitor_device = "stdio";
2805 }
2806
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002807#ifdef CONFIG_KQEMU
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002808 if (smp_cpus > 1)
2809 kqemu_allowed = 0;
2810#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002811 if (qemu_init_main_loop()) {
2812 fprintf(stderr, "qemu_init_main_loop failed\n");
2813 exit(1);
2814 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002815 linux_boot = (kernel_filename != NULL);
2816 net_boot = (boot_devices_bitmap >> ('n' - 'a')) & 0xF;
2817
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002818 if (!linux_boot && *kernel_cmdline != '\0') {
2819 fprintf(stderr, "-append only allowed with -kernel option\n");
2820 exit(1);
2821 }
2822
2823 if (!linux_boot && initrd_filename != NULL) {
2824 fprintf(stderr, "-initrd only allowed with -kernel option\n");
2825 exit(1);
2826 }
2827
2828 /* boot to floppy or the default cd if no hard disk defined yet */
2829 if (!boot_devices[0]) {
2830 boot_devices = "cad";
2831 }
David 'Digit' Turnerc1ac40a2011-06-01 16:12:04 +02002832 os_set_line_buffering();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002833
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002834 if (init_timer_alarm() < 0) {
2835 fprintf(stderr, "could not initialize alarm timer\n");
2836 exit(1);
2837 }
David Turner6a9ef172010-09-09 22:54:36 +02002838 configure_icount(icount_option);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002839
2840#ifdef _WIN32
2841 socket_init();
2842#endif
2843
2844 /* init network clients */
2845 if (nb_net_clients == 0) {
2846 /* if no clients, we use a default config */
2847 net_clients[nb_net_clients++] = "nic";
2848#ifdef CONFIG_SLIRP
2849 net_clients[nb_net_clients++] = "user";
2850#endif
2851 }
2852
2853 for(i = 0;i < nb_net_clients; i++) {
2854 if (net_client_parse(net_clients[i]) < 0)
2855 exit(1);
2856 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002857 net_client_check();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002858
2859#ifdef TARGET_I386
2860 /* XXX: this should be moved in the PC machine instantiation code */
2861 if (net_boot != 0) {
2862 int netroms = 0;
2863 for (i = 0; i < nb_nics && i < 4; i++) {
2864 const char *model = nd_table[i].model;
2865 char buf[1024];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002866 char *filename;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002867 if (net_boot & (1 << i)) {
2868 if (model == NULL)
2869 model = "ne2k_pci";
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002870 snprintf(buf, sizeof(buf), "pxe-%s.bin", model);
2871 filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, buf);
2872 if (filename && get_image_size(filename) > 0) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002873 if (nb_option_roms >= MAX_OPTION_ROMS) {
2874 fprintf(stderr, "Too many option ROMs\n");
2875 exit(1);
2876 }
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01002877 option_rom[nb_option_roms] = g_strdup(buf);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002878 nb_option_roms++;
2879 netroms++;
2880 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002881 if (filename) {
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01002882 g_free(filename);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002883 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002884 }
2885 }
2886 if (netroms == 0) {
2887 fprintf(stderr, "No valid PXE rom found for network device\n");
2888 exit(1);
2889 }
2890 }
2891#endif
2892
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002893 /* init the bluetooth world */
2894 for (i = 0; i < nb_bt_opts; i++)
2895 if (bt_parse(bt_opts[i]))
2896 exit(1);
2897
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002898 /* init the memory */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002899 if (ram_size == 0)
2900 ram_size = DEFAULT_RAM_SIZE * 1024 * 1024;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002901
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002902#ifdef CONFIG_KQEMU
2903 /* FIXME: This is a nasty hack because kqemu can't cope with dynamic
2904 guest ram allocation. It needs to go away. */
2905 if (kqemu_allowed) {
2906 kqemu_phys_ram_size = ram_size + 8 * 1024 * 1024 + 4 * 1024 * 1024;
2907 kqemu_phys_ram_base = qemu_vmalloc(kqemu_phys_ram_size);
2908 if (!kqemu_phys_ram_base) {
2909 fprintf(stderr, "Could not allocate physical memory\n");
2910 exit(1);
2911 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002912 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002913#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002914
2915 /* init the dynamic translator */
2916 cpu_exec_init_all(tb_size * 1024 * 1024);
2917
2918 bdrv_init();
2919
2920 /* we always create the cdrom drive, even if no disk is there */
2921
2922 if (nb_drives_opt < MAX_DRIVES)
2923 drive_add(NULL, CDROM_ALIAS);
2924
2925 /* we always create at least one floppy */
2926
2927 if (nb_drives_opt < MAX_DRIVES)
2928 drive_add(NULL, FD_ALIAS, 0);
2929
2930 /* we always create one sd slot, even if no card is in it */
2931
David 'Digit' Turnercb42a1b2010-12-23 02:54:08 +01002932 if (nb_drives_opt < MAX_DRIVES) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002933 drive_add(NULL, SD_ALIAS);
David 'Digit' Turnercb42a1b2010-12-23 02:54:08 +01002934 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002935
2936 /* open the virtual block devices */
David 'Digit' Turnercb42a1b2010-12-23 02:54:08 +01002937 if (snapshot)
2938 qemu_opts_foreach(qemu_find_opts("drive"), drive_enable_snapshot, NULL, 0);
2939 if (qemu_opts_foreach(qemu_find_opts("drive"), drive_init_func, &machine->use_scsi, 1) != 0)
2940 exit(1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002941
David Turner6a9ef172010-09-09 22:54:36 +02002942 //register_savevm("timer", 0, 2, timer_save, timer_load, NULL);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002943 register_savevm_live("ram", 0, 3, ram_save_live, NULL, ram_load, NULL);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002944
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002945 /* must be after terminal init, SDL library changes signal handlers */
David 'Digit' Turnerc1ac40a2011-06-01 16:12:04 +02002946 os_setup_signal_handling();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002947
2948 /* Maintain compatibility with multiple stdio monitors */
2949 if (!strcmp(monitor_device,"stdio")) {
2950 for (i = 0; i < MAX_SERIAL_PORTS; i++) {
2951 const char *devname = serial_devices[i];
2952 if (devname && !strcmp(devname,"mon:stdio")) {
2953 monitor_device = NULL;
2954 break;
2955 } else if (devname && !strcmp(devname,"stdio")) {
2956 monitor_device = NULL;
2957 serial_devices[i] = "mon:stdio";
2958 break;
2959 }
2960 }
2961 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002962
2963 if (nb_numa_nodes > 0) {
2964 int i;
2965
2966 if (nb_numa_nodes > smp_cpus) {
2967 nb_numa_nodes = smp_cpus;
2968 }
2969
2970 /* If no memory size if given for any node, assume the default case
2971 * and distribute the available memory equally across all nodes
2972 */
2973 for (i = 0; i < nb_numa_nodes; i++) {
2974 if (node_mem[i] != 0)
2975 break;
2976 }
2977 if (i == nb_numa_nodes) {
2978 uint64_t usedmem = 0;
2979
2980 /* On Linux, the each node's border has to be 8MB aligned,
2981 * the final node gets the rest.
2982 */
2983 for (i = 0; i < nb_numa_nodes - 1; i++) {
2984 node_mem[i] = (ram_size / nb_numa_nodes) & ~((1 << 23UL) - 1);
2985 usedmem += node_mem[i];
2986 }
2987 node_mem[i] = ram_size - usedmem;
2988 }
2989
2990 for (i = 0; i < nb_numa_nodes; i++) {
2991 if (node_cpumask[i] != 0)
2992 break;
2993 }
2994 /* assigning the VCPUs round-robin is easier to implement, guest OSes
2995 * must cope with this anyway, because there are BIOSes out there in
2996 * real machines which also use this scheme.
2997 */
2998 if (i == nb_numa_nodes) {
2999 for (i = 0; i < smp_cpus; i++) {
3000 node_cpumask[i % nb_numa_nodes] |= 1 << i;
3001 }
3002 }
3003 }
3004
3005 if (kvm_enabled()) {
3006 int ret;
3007
3008 ret = kvm_init(smp_cpus);
3009 if (ret < 0) {
3010 fprintf(stderr, "failed to initialize KVM\n");
3011 exit(1);
3012 }
3013 }
3014
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003015 if (monitor_device) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003016 monitor_hd = qemu_chr_open("monitor", monitor_device, NULL);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003017 if (!monitor_hd) {
3018 fprintf(stderr, "qemu: could not open monitor device '%s'\n", monitor_device);
3019 exit(1);
3020 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003021 }
3022
3023 for(i = 0; i < MAX_SERIAL_PORTS; i++) {
3024 const char *devname = serial_devices[i];
3025 if (devname && strcmp(devname, "none")) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003026 char label[32];
3027 snprintf(label, sizeof(label), "serial%d", i);
3028 serial_hds[i] = qemu_chr_open(label, devname, NULL);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003029 if (!serial_hds[i]) {
3030 fprintf(stderr, "qemu: could not open serial device '%s'\n",
3031 devname);
3032 exit(1);
3033 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003034 }
3035 }
3036
3037 for(i = 0; i < MAX_PARALLEL_PORTS; i++) {
3038 const char *devname = parallel_devices[i];
3039 if (devname && strcmp(devname, "none")) {
3040 char label[32];
3041 snprintf(label, sizeof(label), "parallel%d", i);
3042 parallel_hds[i] = qemu_chr_open(label, devname, NULL);
3043 if (!parallel_hds[i]) {
3044 fprintf(stderr, "qemu: could not open parallel device '%s'\n",
3045 devname);
3046 exit(1);
3047 }
3048 }
3049 }
3050
3051 for(i = 0; i < MAX_VIRTIO_CONSOLES; i++) {
3052 const char *devname = virtio_consoles[i];
3053 if (devname && strcmp(devname, "none")) {
3054 char label[32];
3055 snprintf(label, sizeof(label), "virtcon%d", i);
3056 virtcon_hds[i] = qemu_chr_open(label, devname, NULL);
3057 if (!virtcon_hds[i]) {
3058 fprintf(stderr, "qemu: could not open virtio console '%s'\n",
3059 devname);
3060 exit(1);
3061 }
3062 }
3063 }
3064
3065 module_call_init(MODULE_INIT_DEVICE);
3066
3067 machine->init(ram_size, boot_devices,
3068 kernel_filename, kernel_cmdline, initrd_filename, cpu_model);
3069
3070
3071 for (env = first_cpu; env != NULL; env = env->next_cpu) {
3072 for (i = 0; i < nb_numa_nodes; i++) {
3073 if (node_cpumask[i] & (1 << env->cpu_index)) {
3074 env->numa_node = i;
3075 }
3076 }
3077 }
3078
3079 current_machine = machine;
3080
3081 /* Set KVM's vcpu state to qemu's initial CPUState. */
3082 if (kvm_enabled()) {
3083 int ret;
3084
3085 ret = kvm_sync_vcpus();
3086 if (ret < 0) {
3087 fprintf(stderr, "failed to initialize vcpus\n");
3088 exit(1);
3089 }
3090 }
3091
3092 /* init USB devices */
3093 if (usb_enabled) {
3094 for(i = 0; i < usb_devices_index; i++) {
3095 if (usb_device_add(usb_devices[i], 0) < 0) {
3096 fprintf(stderr, "Warning: could not add USB device %s\n",
3097 usb_devices[i]);
3098 }
3099 }
3100 }
3101
3102 if (!display_state)
3103 dumb_display_init();
3104 /* just use the first displaystate for the moment */
3105 ds = display_state;
3106
3107 if (display_type == DT_DEFAULT) {
3108#if defined(CONFIG_SDL) || defined(CONFIG_COCOA)
3109 display_type = DT_SDL;
3110#else
3111 display_type = DT_VNC;
3112 vnc_display = "localhost:0,to=99";
3113 show_vnc_port = 1;
3114#endif
3115 }
David 'Digit' Turner707c8a82010-12-22 22:35:58 +01003116
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003117
3118 switch (display_type) {
3119 case DT_NOGRAPHIC:
3120 break;
3121#if defined(CONFIG_CURSES)
3122 case DT_CURSES:
3123 curses_display_init(ds, full_screen);
3124 break;
3125#endif
3126#if defined(CONFIG_SDL)
3127 case DT_SDL:
3128 sdl_display_init(ds, full_screen, no_frame);
3129 break;
3130#elif defined(CONFIG_COCOA)
3131 case DT_SDL:
3132 cocoa_display_init(ds, full_screen);
3133 break;
3134#endif
3135 case DT_VNC:
3136 vnc_display_init(ds);
3137 if (vnc_display_open(ds, vnc_display) < 0)
3138 exit(1);
3139
3140 if (show_vnc_port) {
3141 printf("VNC server running on `%s'\n", vnc_display_local_addr(ds));
3142 }
3143 break;
3144 default:
3145 break;
3146 }
3147 dpy_resize(ds);
3148
3149 dcl = ds->listeners;
3150 while (dcl != NULL) {
3151 if (dcl->dpy_refresh != NULL) {
David 'Digit' Turner5973c772011-05-10 07:06:00 +02003152 ds->gui_timer = qemu_new_timer_ms(rt_clock, gui_update, ds);
3153 qemu_mod_timer(ds->gui_timer, qemu_get_clock_ms(rt_clock));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003154 }
3155 dcl = dcl->next;
3156 }
3157
3158 if (display_type == DT_NOGRAPHIC || display_type == DT_VNC) {
David 'Digit' Turner5973c772011-05-10 07:06:00 +02003159 nographic_timer = qemu_new_timer_ms(rt_clock, nographic_update, NULL);
3160 qemu_mod_timer(nographic_timer, qemu_get_clock_ms(rt_clock));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003161 }
3162
3163 text_consoles_set_display(display_state);
3164 qemu_chr_initial_reset();
3165
3166 if (monitor_device && monitor_hd)
3167 monitor_init(monitor_hd, MONITOR_USE_READLINE | MONITOR_IS_DEFAULT);
3168
3169 for(i = 0; i < MAX_SERIAL_PORTS; i++) {
3170 const char *devname = serial_devices[i];
3171 if (devname && strcmp(devname, "none")) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003172 if (strstart(devname, "vc", 0))
3173 qemu_chr_printf(serial_hds[i], "serial%d console\r\n", i);
3174 }
3175 }
3176
3177 for(i = 0; i < MAX_PARALLEL_PORTS; i++) {
3178 const char *devname = parallel_devices[i];
3179 if (devname && strcmp(devname, "none")) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003180 if (strstart(devname, "vc", 0))
3181 qemu_chr_printf(parallel_hds[i], "parallel%d console\r\n", i);
3182 }
3183 }
3184
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003185 for(i = 0; i < MAX_VIRTIO_CONSOLES; i++) {
3186 const char *devname = virtio_consoles[i];
3187 if (virtcon_hds[i] && devname) {
3188 if (strstart(devname, "vc", 0))
3189 qemu_chr_printf(virtcon_hds[i], "virtio console%d\r\n", i);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003190 }
3191 }
3192
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003193 if (gdbstub_dev && gdbserver_start(gdbstub_dev) < 0) {
3194 fprintf(stderr, "qemu: could not open gdbserver on device '%s'\n",
3195 gdbstub_dev);
3196 exit(1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003197 }
3198
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003199 if (loadvm)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003200 do_loadvm(cur_mon, loadvm);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003201
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003202 if (incoming) {
3203 autostart = 0; /* fixme how to deal with -daemonize */
3204 qemu_start_incoming_migration(incoming);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003205 }
3206
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003207 if (autostart)
3208 vm_start();
3209
David 'Digit' Turnerc1ac40a2011-06-01 16:12:04 +02003210 os_setup_post();
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003211
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003212 main_loop();
3213 quit_timers();
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003214 net_cleanup();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003215
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003216 return 0;
3217}